Skip to content
GitHub Twitter

Using Spring’s Retry Template on http calls

We don’t give up easily as developers, and neither do our services.

This blog will show you how to retry an HTTP request even if it fails until a condition is met.

img.png

The service that has some data currently listens on port 3333 and has one endpoint called /hello, but it’s down and returns 503 😢.

Our service needs to have an retry mechanism in place so it will retry couple of times until it throws an error. In order to achieve this we will use spring’s retry module (former part of spring batch).

@SpringBootApplication
@EnableRetry
public class RetryingHttpApplication {

    @Autowired
    private AmazingHttpClient amazingHttpClient;

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

    @Bean
    CommandLineRunner commandLineRunner(){ 
        return new CommandLineRunner() {
            @Override
            public void run(String... args) throws Exception {
                amazingHttpClient.getData();
            }
        };
    }
}

Once the module is in your classpath, you can enable the retry mechanism by annotations the application entrypoint with EnableRetry.

The command line runner invokes the getData() method with is used to communicate with the service which contains the data we need.

The method inside the http client looks like this

public String getData() {
        var restTemplateBuilder = new RestTemplateBuilder();
        RestTemplate template = restTemplateBuilder.build();
        return template.getForObject(
                "http://localhost:3333/hello",
                String.class
        );
    }

Now we want to apply the following rule when retrying

<i>If any exception is thrown while trying to read the data, retry every 2 seconds for 5 attempts.</i>

    @Retryable(retryFor = Exception.class, backoff = @Backoff(delay = 2000L), maxAttempts = 5)
    public String getData() {
        var restTemplateBuilder = new RestTemplateBuilder();
        RestTemplate template = restTemplateBuilder.build();
        return template.getForObject(
                "http://localhost:3333/hello",
                String.class
        );
    }

If you run the application now, you should see something like this in the logs which means that the service itself is trying 5 times to talk to the destination service.

2023-02-13T20:48:07.664+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=0
2023-02-13T20:48:09.685+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=1
2023-02-13T20:48:09.685+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=1
2023-02-13T20:48:11.688+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=2
2023-02-13T20:48:11.688+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=2
2023-02-13T20:48:13.696+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=3
2023-02-13T20:48:13.697+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=3
2023-02-13T20:48:15.705+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=4
2023-02-13T20:48:15.706+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Retry: count=4
2023-02-13T20:48:15.708+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Checking for rethrow: count=5
2023-02-13T20:48:15.708+01:00 DEBUG 50543 --- [           main] o.s.retry.support.RetryTemplate          : Retry failed last attempt: count=5