Implementing Retry Logic for Third‑Party APIs with Spring Retry in Spring Boot

This guide shows how to add a retry mechanism to Spring Boot applications using Spring Retry, covering dependency setup, enabling @EnableRetry, defining @Retryable with custom back‑off settings, handling failures with @Recover, writing unit tests, and observing behavior with different retry counts and exception filters.

The Dominant Programmer
The Dominant Programmer
The Dominant Programmer
Implementing Retry Logic for Third‑Party APIs with Spring Retry in Spring Boot

Transient network glitches can cause timeouts when a Spring Boot application calls a third‑party HTTP API. Adding a retry mechanism automatically re‑executes the call until it succeeds or the retry limit is reached.

Spring Retry

Spring Retry provides automatic re‑invocation of failed operations, useful for temporary errors such as brief network failures. Repository: https://github.com/spring-projects/spring-retry

Implementation Steps

Add Maven dependencies:

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

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.4</version>
</dependency>

Enable retry support in the Spring Boot entry class:

@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableRetry
public class RuoYiApplication {
    public static void main(String[] args) {
        SpringApplication.run(RuoYiApplication.class, args);
    }
}

Create an interface for the third‑party call:

public interface IRetryService {
    String getThirdApiData();
}

Implement the interface and annotate the method with @Retryable :

@Service
public class RetryServiceImpl implements IRetryService {
    // value: exception type to retry (Exception)
    // maxAttempts: total attempts including the first (10)
    // delay: initial wait in ms (2000)
    // multiplier: back‑off factor (1.5)
    @Override
    @Retryable(value = Exception.class, maxAttempts = 10,
               backoff = @Backoff(delay = 2000, multiplier = 1.5))
    public String getThirdApiData() {
        System.out.println("Calling API");
        return HttpRequest.get("http://127.0.0.1:4523/m1/2858210-0-default/testFastJson")
                          .timeout(4000)
                          .execute()
                          .body();
    }

    @Recover
    public String recover(Exception e) {
        return "Request failed";
    }
}

The @Retryable parameters control which exception triggers a retry, how many attempts are made, the initial delay, and the exponential back‑off factor. The @Recover method runs after all attempts fail.

Write a unit test to verify the behavior:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = RuoYiApplication.class,
                webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class SpringRetryTest {
    @Autowired
    private IRetryService iRetryService;

    @Test
    public void getThirdApiDataTest() {
        try {
            String data = iRetryService.getThirdApiData();
            System.out.println(data);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Observations

Setting maxAttempts to 5 while the API remains unreachable produces five retry attempts, as shown in the log screenshot:

Retry attempts with maxAttempts=5
Retry attempts with maxAttempts=5

Increasing maxAttempts to 10 and opening the API during the retry sequence results in a successful call after several attempts, as illustrated:

Retry attempts with maxAttempts=10
Retry attempts with maxAttempts=10

Advanced Usage

Retry can be limited to specific exception types:

@Retryable(
    value = { RestClientException.class, TimeoutException.class },
    maxAttempts = 3,
    backoff = @Backoff(delay = 1000, multiplier = 2)
)

Or certain exceptions can be excluded while retrying others:

@Retryable(
    value = { RestClientException.class },
    maxAttempts = 3,
    backoff = @Backoff(delay = 1000, multiplier = 2),
    exclude = { TimeoutException.class }
)

In the first example, retries occur for RestClientException or TimeoutException. In the second example, retries occur only for RestClientException, with TimeoutException excluded.

Full source code and additional details are available at https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/135519969

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaspring-bootUnit TestRetryableSpring Retry@EnableRetry
The Dominant Programmer
Written by

The Dominant Programmer

Resources and tutorials for programmers' advanced learning journey. Advanced tracks in Java, Python, and C#. Blog: https://blog.csdn.net/badao_liumang_qizhi

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.