Spring Retry provides the ability to automatically re-invoke a failed operation. This is helpful when errors may be transient in nature. For example, a momentary network glitch, network outage, server down, or deadlock.
You can configure the spring-retry
module using annotations. You can define the retry limits, fallback methods, etc.
In this post, you will learn how to use the spring-retry
module.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
|
Spring Retry Example
I will demonstrate a service implementation with a method that throws an exception in case of a failure. In such a case of exception, Spring retries to invoke the method 3 times.
In those 3 retry attempts, if a successful response is received from the method, then the response is returned to the caller. Ese a standard fallback method is called.
Defining the Interface
The code for the RetryService
interface is this.
1
2
3
4
5
6
7
|
package guru.springframework;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
public interface RetryService {
@Retryable(value = {CustomRetryException.class}, maxAttempts = 3, backoff = @Backoff(200))
public String retry() throws CustomRetryException;
}
|
The @Retrayable
annotation in Line 8 tells Spring that if we get CustomRetryException
from the method call, then the method call should be retried 3 times with an interval of 2 seconds before sending the response.
Note: The value
attribute in Line 8 tells Spring retry to act if the method throws CustomRetryException
. Also the default value of maxAttempts
is 3.
The code for the Implementation class is this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@Slf4j
@Service
public class RetryServiceImpl implements RetryService {
@Override
public String retry() throws CustomRetryException {
log.info("Throwing CustomRetryException in method retry");
throw new CustomRetryException("Throw custom exception");
}
@Recover
public String recover(Throwable throwable) {
log.info("Default Retry servive test");
return "Error Class :: " + throwable.getClass().getName();
}
}
|
In Line 11, the @Recover
annotation indicates that if you don’t get any success response after 3 retry, this fallback method will get called.
This is the code for the main class.
1
2
3
4
5
6
7
8
9
10
11
|
package guru.springframework;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
@EnableRetry
@SpringBootApplication
public class SpringRetryApplication {
public static void main(String[] args) {
SpringApplication.run(SpringRetryApplication.class, args);
}
}
|
You need to add @EnableRetry
annotation to enable retry.
Test the Application
The code for the SpringRetryApplicationTest
is this.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package guru.springframework;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@Slf4j
@SpringBootTest
public class SpringRetryApplicationTest {
@Autowired
RetryService retryService;
@Test
public void sampleRetryService() {
try {
final String message = retryService.retry();
log.info("message = " + message);
} catch (CustomRetryException e) {
log.error("Error while executing test {}", e.getMessage());
}
}
}
|
On Running the Test case, you will see the following output.
Here we get an exception in the backend and then spring retries the same method 3 times as specified. Also, you get fallback response after the retry limit is reached every time we are throwing CustomRetryException
.
Summary
The spring-retry
module is very helpful to automatically retry a failed operation by replacing itself with having a loop and breaking it once the limit is reached. This feature also comes in handy when you integrate with external APIs and need a robust fail-safe system that can handle system downtime or network downtime.
You can find the source code of this post here on Github.
Reference https://springframework.guru/retry-in-spring-boot-applications/