Java Functional Retry with resilience4j-retry

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"

view raw

resi4j.gradel

hosted with ❤ by GitHub

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");

view raw

retry.java

hosted with ❤ by GitHub

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");

view raw

SyncRetry.java

hosted with ❤ by GitHub

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 :

  1. https://github.com/resilience4j/resilience4j

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s