Configurable Feign Client Retry With Reusable Library and DRY
Learn how to implement and expose common retry features for Feign clients through application configuration, using the Spring Cloud Framework efficiently.
Join the DZone community and get the full member experience.
Join For FreeIn microservice architectures, resilient communication between services is vital. Feign, a declarative web service client, is a popular choice for simplifying HTTP communication. But there is no out-of-the-box retry mechanism provided, which can be plugged seamlessly with the Feign client. This is a good-to-have feature, as adding retry logic to Feign clients enhances fault tolerance.
This article demonstrates how to implement retry logic with conditional configuration to Feign client and package it in a common library using Maven. The idea is to use it to expose Feign retry and features similar to those of the consumer of this library. It also helps in the Separation of Concerns. This approach ensures reusability across multiple microservices, adhering to the DRY design principle.
Why Use Conditional Configuration?
With Spring Boot’s @ConditionalOnProperty
, we can toggle features dynamically based on externalized configuration properties. This makes our application flexible and environment-agnostic. We can enable or disable it per microservice by implementing retry logic as part of a reusable library with minimal effort.
Objectives
- Implement Feign retry logic as an aspect in a
common-config
library. - Use
@ConditionalOnProperty
to enable the consumer of this library to configure the retry logic dynamically based on configuration. - Add the
common-config
library as a Maven dependency in a microservice.
Step 1: Define the Configuration in the Shared Library
Create a Maven Module for common-config
Structure your project to include a Maven module for common-config
. Add the required dependencies to its pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Implement the Feign Retry Aspect
In the common-config
module, create the Feign retry aspect with conditional configuration:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Aspect
public class FeignRetryAspect {
@Before("execution(* com.example.feign.client..*(..))") // Example pointcut
public void beforeFeignCall() {
System.out.println("Feign Retry Aspect triggered.");//Used SOP just to show here, please done use it in production code
}
}
@Configuration
public class FeignRetryConfiguration {
@Bean
@ConditionalOnProperty(
name = "application.feign.retry.aspect.enabled",
havingValue = "true",
matchIfMissing = false
)
public FeignRetryAspect feignRetryAspect() {
return new FeignRetryAspect();
}
}
Here’s how the configuration works:
@Aspect
: Defines the Feign retry logic.@ConditionalOnProperty
: Checks if theapplication.feign.retry.aspect.enabled
property istrue
. If it’sfalse
or missing, the aspect will not be registered.
Step 2: Add Configuration to a Microservice
Add common-config as a Dependency
Publish the common-config
module to your Maven repository (e.g., Artifactory, Nexus, or a local repository). Then, include it as a dependency in your microservice’s pom.xml
:
<dependency>
<groupId>com.example</groupId>
<artifactId>common-config</artifactId>
<version>1.0.0</version>
</dependency>
Define the Feign Configuration in application.yml
In the microservice, configure the Feign retry aspect through the application.yml
file:
application:
feign:
retry:
aspect:
enabled: true
By setting application.feign.retry.aspect.enabled
to true
, the Feign retry aspect from the common-config
module will be enabled. Setting it to false
will disable it.
Step 3: Test the Configuration
Scenario 1: Enabling the Aspect
If the property application.feign.retry.aspect.enabled=true
is defined, the Feign retry aspect will be active, and you’ll see the retry logic applied to Feign client calls.
Output:
Feign Retry Aspect triggered.
Scenario 2: Disabling the Aspect
If the property application.feign.retry.aspect.enabled=false
or is missing, the aspect will not be registered, and no retry logic will be applied.
Output: (No aspect-related logs)
Step 4: Benefits of the Shared Library Approach
- Reusability: The
common-config
library encapsulates the retry logic, reducing duplication across microservices. - Configurability: Each microservice can enable or disable the aspect dynamically by setting the property in its configuration.
- Ease of Maintenance: Changes to the retry logic can be made centrally in the
common-config
library and automatically applied to all dependent microservices.
Step 5: Publish and Use Across Microservices
After testing locally, publish the common-config
library to your artifact repository. Other microservices can now include this dependency and leverage Feign retry logic with minimal effort.
Similarly, other common concerns can also be moved to common-config
library, and can be reused by multiple microservices through Maven dependencies, e.g., exception handling.
Conclusion
Implementing retry logic for Feign clients using a shared library provides a scalable and maintainable solution for microservice architectures. Using Spring Boot's conditional configuration and encapsulating the logic in a reusable library, you ensure fault tolerance while adhering to key design principles. This approach simplifies configuration for individual microservices, centralizes updates, and promotes consistency across the ecosystem.
Opinions expressed by DZone contributors are their own.
Comments