We often work in applications that interact with external services (Rest APIs or DB…). It can happen that a call to the external service sometimes fails, and we would want to have the ability to retry the failed call.
In Project Reactor, we have operators such as retry() and retryWhen() that we can use to retry the failed operation.
Retry failed operation with retry() method
The retry(long numRetries) re-subscribes to the Publisher sequence if it signals any error for a fixed number of times.
In this example, let’s set the code to retry 3 times in case we get the onError signal from the Publisher:
class ReactiveJavaTutorial { public static void main(String[] args) { Mono.just("data1") .concatWith(Flux.error(new RuntimeException("Exception occurred."))) .doOnError(ex -> System.out.println("LOG: Exception caught: " + ex)) .retry(3) //retry 3 times in case of an error .log() .subscribe(); } }
Retry failed with retryWhen() method
The retryWhen() method can perform a retry on a specific exception. Also, we can specify the delay between each of the retries.
Let’s write a program that retries 3 times with a delay of 2 seconds between each attempt. In this way, we can give the failing service time to recover.
class ReactiveJavaTutorial { public static void main(String[] args) { Mono.just("data1") .concatWith(Flux.error(new RuntimeException("Exception occurred."))) .retryWhen(Retry.fixedDelay(3, Duration.ofSeconds(2))) .log() .subscribe(); } }
Retrying using Backoff
With Backoff, the delay will be increased progressively after each attempt. In our example, it will be 2, 4, 8 seconds of delay.
class ReactiveJavaTutorial { public static void main(String[] args) { Mono.just("data1") .concatWith(Flux.error(new RuntimeException("Exception occurred."))) .retryWhen(Retry.backoff(3, Duration.ofSeconds(2))) .log() .subscribe(); } }
Retry only on specific exception
We would want to retry only when we get a specific exception from the server in real-world applications. Let’s set the code to retry only in case of the “InternalServerError” exception from the server.
class ReactiveJavaTutorial { public static void main(String[] args) { Mono.just("data1") .concatWith(Flux.error(new RuntimeException("Exception occurred."))) .retryWhen(Retry.backoff(3, Duration.ofSeconds(2)) .filter(throwable -> throwable instanceof InternalServerError)) .log() .subscribe(); } }
That was all about retrying the failed operations in Project Reactor. Proceed to the next lesson.
Happy coding!