'finally block equivalent for exception handling in CompletableFuture
I have CompletableFuture
which can return result or exception. I want to perform run some common code in case of exception and normal result. Similar to try catch finally
block
Current implementation
CompletableFuture<Integer> future= CompletableFuture.supplyAsync(this::findAccountNumber)
.thenApply(this::calculateBalance)
.thenApply(this::notifyBalance)
.exceptionally(ex -> {
//My Exception Handling logic
return 0;
});
Where i can put my finally logic ?
Solution 1:[1]
The closest equivalent to finally
is whenComplete
. Like handle
, it accepts a function receiving either, a result value or a throwable, but it doesn’t provide a substitution result value, but rather, the new completion stage will not alter the result, just like finally
.
So
static int decode(String s) {
try {
return Integer.parseInt(s);
}
finally {
System.out.println("finally action");
}
}
is equivalent to
static int decode1(String s) {
return CompletableFuture.completedFuture(s)
.thenApply(Integer::parseInt)
.whenComplete((myParsedInt, error) -> System.out.println("finally action"))
.join();
}
So when using with
for(String s: Arrays.asList("1234", "foo bar")) try {
System.out.println("decoded: "+decode(s));
} catch(Exception ex) {
System.out.println("decoding "+s+" failed with "+ex);
}
the first variant prints
finally action
decoded: 1234
finally action
decoding foo bar failed with java.lang.NumberFormatException: For input string: "foo bar"
and the latter prints
finally action
decoded: 1234
finally action
decoding foo bar failed with java.util.concurrent.CompletionException: java.lang.NumberFormatException: For input string: "foo bar"
Common to both is that an exception thrown within the finally action will supersede the original result, shadowing the exception, if the try block/ previous stage completed exceptionally.
Solution 2:[2]
handle()
Method provide more flexible approach. it takes a function receiving either correct result or exception:
From java doc
handle(BiFunction<? super T,Throwable,? extends U> fn)
Returns a new CompletionStage that, when this stage completes either normally or exceptionally, is executed with this stage's result and exception as arguments to the supplied function.
CompletableFuture<Integer> thenApply = CompletableFuture.supplyAsync(this::findAccountNumber)
.thenApply(this::calculateBalance)
.thenApply(this::notifyBalance)
.handle((ok, ex) -> {
System.out.println("Code That we want to run in finally ");
if (ok != null) {
System.out.println("No Exception !!");
} else {
System.out.println("Got Exception " + ex.getMessage());
return -1;
}
return ok;
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Top-Master |
Solution 2 | Niraj Sonawane |