1. Overview
In this tutorial, we’ll see how to use retry with delay in RxJava. When working with Observable, it is quite likely to get an error instead of a success. In such cases, we can use retry with delay to reattempt after some time.
2. Project Setup
To begin this, let’s create a Maven or a Gradle project. Here, we’re using a Maven-based project. Let’s add the rxjava dependency to our pom.xml file:
<dependency>
<groupId>io.reactivex.rxjava2</groupId>
<artifactId>rxjava</artifactId>
<version>2.2.21</version>
</dependency>
The dependency can be found on the Maven Central Page.
3. Retry in the Observable Lifecycle
Retry is used when an Observable source emits an error. This is a resubscription to the source in the hopes of getting completed without errors in the next attempt. Therefore, retry() and its other variants come into the picture only when the Observable emits an error.
3.1. Overloaded Variants of Retry
Apart from the retry() method discussed in the above section, RxJava provides two overloaded variants, retry(long) and retry(Func2).
The retry(long) returns an Observable that mirrors the source Observable. We resubscribe to this mirror only as long as it calls onError the specified number of times.
The retry(Func2) method takes a function that accepts a Throwable as input and produces a boolean as output. Here, we resubscribe to the mirror only if it returns true for the specific Exception and the retry count.
3.2. RetryWhen vs Retry
The retryWhen(Func1) provides us with an option to include custom logic to determine whether or not we should resubscribe to the mirror of the original Observable. This method accepts a function that takes the exception thrown by the onError handler.
If the function emits an item, we resubscribe to the mirror, while we don’t if it produces an onError notification.
4. Code Examples
Let’s now watch these concepts in action with the help of a few code snippets.
4.1. Successful Observable
If an Observable call succeeds, then the Observer’s onNext method is invoked. Let’s see an example:
@Test
public void givenObservable_whenSuccess_thenOnNext(){
Observable.just(remoteCallSuccess())
.subscribe(success -> {
System.out.println("Success");
System.out.println(success);
}, err -> {
System.out.println("Error");
System.out.println(err);
});
}
The method remoteCallSuccess() completes successfully and returns a String. In this case, the onNext() method of the subscriber is invoked, printing success messages.
4.2. Erroneous Observable
Let’s introduce a new utility function called remoteCallError() that mocks calling a remote server. This method is vulnerable to errors. Therefore, our retryWhen logic would kick in:
@Test
public void givenObservable_whenError_thenOnError(){
Observable.just(remoteCallError())
.subscribe(success -> {
System.out.println("Success");
System.out.println(success);
}, err -> {
System.out.println("Error");
System.out.println(err);
});
}
In this case, the remoteCallError() method causes an error. Therefore, the onError() method of the subscriber gets called. Consequently, error messages get printed.
4.3. Retrying with Delay
We can add a delay during the resubscription process:
@Test
public void givenError_whenRetry_thenCanDelay(){
Observable.just(remoteCallError())
.retryWhen(attempts -> {
return attempts.flatMap(err -> {
if (customChecker(err)) {
return Observable.timer(5000, TimeUnit.MILLISECONDS);
} else {
return Observable.error(err);
}
});
});
}
Similar to the previous case, the remoteCallError() method causes an error. Here, however, instead of notifying the observer’s onError() method, we give this Observable a chance to resubcribe. For this, we pass the exception to a customChecker() method, which returns a boolean. If the response is true, we return a new Observable with a delay of 5000 milliseconds (5 seconds). Otherwise, we return an error and notify the observer.
5. Conclusion
In this tutorial, we saw how to use
retryWhen and some of its related functions. We understood the cases under which
retry and
retryWhen help us solve our issues. The source code is available
over on GitHub.