Spring Retry

redo, restart, retry-151210.jpg

Retry is an important tool in our arsenal to make robust and efficient APIs, it helps us to automatically reinvoke a failed operation. This is because sometimes due to network glitches or DB errors, the call fails for the first time however succeeds next time. We can do retry using annotations, and RetryTemplate.

Spring Retry using Annotation

Step -1: Add Maven dependency

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>${version}</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>${version}</version>
</dependency>

Step -2 : Enable Retry

@EnableRetry
@SpringBootApplication
public class Application {

public static void main(String[] args) {
 Application.run(Application.class, args);
}

}

Step -3 : Create Retryable Method

  • @Retryable – would retry for 2 more times after first one, only if we receive a Exception of type CustomException, and Backoff of 200
  • @Recover – if we don’t get any success response after 3 retry, then the code falls to here and returns a handled response.
@Service
public class ExternalService {

    @Retryable(
            value = {CustomException.class},
            maxAttempts = 3, backoff = @Backoff(200))
    public String invokeDownStreamService() throws CustomException {
      ....
    }

    @Recover
    public String recover(Throwable t) {
        ....
    }
}

Note : Spring AOP works on object AOP proxies. https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-understanding-aop-proxies. Hence for retry to work you need to invoke Retryable on methods or interfaces

Spring Retry using RetryTemplate

Step – 1: Add Maven dependency

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>1.2.5.RELEASE</version>
</dependency>

Step -2 : Create a customRetryTemplate

Create a CustomRetryTemplate class, Below we have a customRetryTemplate which would

  • FixedBackOffPolicy : will retry after a backoff period of 100ms.
  • SimpleRetryPolicy : would retry for 2 more times after first one, only if we receive a Exception of type MyException.
@Configuration
public class CustomRetryTemplate {

    public static final int MAX_ATTEMPTS = 3;
    public static final long BACKOFF_PERIOD = 100;

    @Bean
    public RetryTemplate customRetryTemplate() {
        RetryTemplate retryTemplate = new RetryTemplate();

        FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy();
        fixedBackOffPolicy.setBackOffPeriod(BACKOFF_PERIOD);
        retryTemplate.setBackOffPolicy(fixedBackOffPolicy);

        Map<Class<? extends Throwable>, Boolean> retryableException=
                Collections.singletonMap(MyException.class,
                Boolean.TRUE);
        SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(MAX_ATTEMPTS, retryableException);
        retryTemplate.setRetryPolicy(retryPolicy);

        return retryTemplate;
    }

}


Step -3 : Execute CustomRetryTemplate


RetryTemplate provides different methods to invoke code in retry-able way, an example is the retryTemplate.execute(RetryCallback rc).

customRetryTemplate.execute(retryCallback -> {
	return myService.invokemethod(...);
});
error: Content is protected !!
Scroll to Top