We will go through specific module(Resilience4j-Retry) from Resilience4j which is a fault tolerance library designed for Java8 and functional programming and it is lightweight library with minimal dependencies (mainly vavr)
When you retry , there are many cases for example :
- cross micro services communication for remote systems calls which most likely will need circuit breaker logic added as well
- if you have business or functional logic that need to get a consistent end state and most likely it is asynchronous Flow
Ok , what you need to do to start using resileience4j retry :
if you are using maven:
<dependency> | |
<groupId>io.github.resilience4j</groupId> | |
<artifactId>resilience4j-retry</artifactId> | |
<version>0.13.2</version> | |
</dependency> | |
<dependency> | |
<groupId>io.github.resilience4j</groupId> | |
<artifactId>resilience4j-core</artifactId> | |
<version>0.13.2</version> | |
</dependency> |
if you are using gradle :
compile "io.github.resilience4j:resilience4j-core:0.13.2" | |
compile "io.github.resilience4j:resilience4j-retry:0.13.2" |
What can be covered by the retry module of resilience4j :
- Synchronous retry and Asynchronous retry
- Rety on exceptions or response predicate which can be useful if you want to retry on specific response value not just thrown exceptions
- Back-off strategy for the retry configuration plus max retry attempts
- Ignoring set of exceptions to not retry on
- It has support for checked(exception handling added) and unchecked functions executions (ex Function , Supplier , Callable , Runnable..)
- it could be integrated with spring if needed.
Now showing examples of the mentioned features up:
How to configure the Asynchronous retry , full code for testing resilience4j retry on Github
// Given the HelloWorldService returns Hello world | |
given(helloWorldService.returnHelloWorld()) | |
.willReturn(completedFuture("Hello world")); | |
final AsyncRetry retryContext = AsyncRetry.of("retryConfig", | |
// we set the response type to String | |
RetryConfig.<String>custom() | |
// max retry attempts | |
.maxAttempts(3) | |
// what are the ignore exception to no retry on | |
.ignoreExceptions(IllegalStateException.class) | |
// what are the exceptions to try on | |
.retryExceptions(TimeoutException.class) | |
// retry if the response contains world | |
.retryOnResult(s –> s.contains("world")) | |
// retry backoff strategy, IntervalFunction has many built in interface functions you can check it out | |
.intervalFunction(IntervalFunction.ofExponentialBackoff()) | |
.build()); | |
// Decorate the invocation of the HelloWorldService | |
Supplier<CompletionStage<String>> supplier = AsyncRetry.decorateCompletionStage( | |
retryContext, | |
scheduler, | |
() –> helloWorldService.returnHelloWorld()); | |
// When | |
String result = awaitResult(supplier); | |
// Then the helloWorldService should be invoked 1 time | |
BDDMockito.then(helloWorldService).should(Mockito.times(3)).returnHelloWorld(); | |
Assertions.assertEquals(result, "Hello world"); |
For Synchronous calls , you have many options (Supplier , Callable , Function , plus Checked version of them, please check resilience4j retry APIs for more information) :
Example :
// Given the HelloWorldService returns Hello world | |
BDDMockito.given(helloWorldService.returnHelloWorld()).willReturn("Hello world"); | |
// Create a Retry with default configuration | |
final RetryConfig tryAgain = RetryConfig.<String>custom().retryOnResult(s –> s.contains("Hello world")) | |
.maxAttempts(2).build(); | |
Retry retry = Retry.of("id", tryAgain); | |
// Decorate the invocation of the HelloWorldService | |
Supplier<String> supplier = Retry.decorateSupplier(retry, helloWorldService::returnHelloWorld); | |
// When | |
String result = supplier.get(); | |
// Then the helloWorldService should be invoked 1 time | |
BDDMockito.then(helloWorldService).should(Mockito.times(2)).returnHelloWorld(); | |
assertThat(result).isEqualTo("Hello world"); |
For more information , please check resilience4j Github and the code samples on GitHub as well .
In the next blogs I will cover spring and spring boot integration .
References :