Java 9: Handle timeouts asynchronously using CompletableFuture's orTimeout and completeOnTimeout

When writing asynchronous code using CompletableFuture you can quickly end up in a scenario where you can't wait for a given task to finish. You simply need to timeout and move on.

This is something that has been addressed in Java 9 by introducing two new functions — orTimeout() and completeOnTimeout().

Consider the following scenario

Say we've started using the CompletableFuture API in a system that fetches articles. We're happy with the code except for one ting — we got some issues with a really slow call to the service that fetches the articles.

Timeout a CompletableFuture with an Exception using orTimeout()

One way to address this is to use the orTimeout() method.

What orTimeout does is to complete the CompletableFuture exceptionally if it doesn't complete by itself.

CompletableFuture.supplyAsync(this::getArticles)  
                 .orTimeout(1, TimeUnit.MINUTES);

// > ExecutionException: java.util.concurrent.TimeoutException

As you can see, all you need to provide is how long you're willing to wait before the timeout should occur.

In our example we use 1 minute, but you can use any time unit — everything from TimeUnit.NANOSECONDS to TimeUnit.DAYS

Timeout a CompletableFuture and provide another value using completeOnTimeout

Another option is to timeout by providing an alternative value.

You always have to consider what you need, but this variant is probably my favourite.

The thing is, when you compose functions in the way that CompletableFuture encourages you to do, you can use default values like this to make the system more fault tolerant instead of just failing exceptionally.

In our example, say we got a set of backup articles that we want to display instead of just failing if the getArticles method doesn't return in time.

Then we can use the completeOnTimeout method to return our backup articles.

CompletableFuture.supplyAsync(this::getArticles)  
                 .completeOnTimeout(getBackupArticles(),1, TimeUnit.SECONDS);

That's it. All we do is to provide the list of backup articles and how long we're willing to wait for the original articles before we timeout and return the backup articles instead.

Enjoyed the post?

If you don't want to miss future posts, make sure to subscribe