java 8 – CompletableFuture completeExceptionally example
Let’s see what happens when async calls exception is raised and how we can handle this situation.
Suppose we have a method which makes asynchronous call:
public Future doOperationAsync() {
CompletableFuture futureObj = new CompletableFuture<>();
new Thread(() -> {
String result = someOperation();
futureObj.complete(result);
}).start();
return futureObj;
}
if someOperation()
method is running fine, we don’t have any issues, doOperationAsync()
will execute and return the Future
object. But what happens if someOperation()
throws exception during execution time.
private String someOperation() {
throw new RuntimeException("Operation is not successful");
}
Unfortunately in this case raised exception will remain in the thread. As a result the caller will be blocked forever. One solution is to use the ovevrload method of get
method with a timeout, which will allow at least not be blocked forever and exit with TimeoutException
.
Future result = new CompletableExample().doOperationAsync();
result.get(4, TimeUnit.SECONDS);
[addToAppearHere]
However cleaner way would be to use CompletableFuture.completeExceptionally()
method. In this case the caller will receive ExecutionException
, which will contain also the original exception.
public Future doOperationAsync() {
CompletableFuture futureObj = new CompletableFuture<>();
new Thread(() -> {
try {
String result = someOperation();
futureObj.complete(result);
} catch (Exception e) {
futureObj.completeExceptionally(e);
}
}).start();
return futureObj;
}
Output will be
java.util.concurrent.ExecutionException: java.lang.RuntimeException: Operation is not successful
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.example.CompleteExceptionallyExample.main(CompleteExceptionallyExample.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.RuntimeException: Operation is not successful
at com.example.CompleteExceptionallyExample.someOperation(CompleteExceptionallyExample.java:32)
at com.example.CompleteExceptionallyExample.lambda$doOperationAsync$0(CompleteExceptionallyExample.java:22)
at java.lang.Thread.run(Thread.java:745)