[concurrency-interest] Layered exception handling with CompletableFuture

Zhong Yu zhong.j.yu at gmail.com
Tue Aug 26 20:02:15 EDT 2014

On Tue, Aug 26, 2014 at 5:15 PM, Millies, Sebastian <
Sebastian.Millies at softwareag.com> wrote:

>  Hello there,
> over at comp.lang.java.programmer, Dario Crivelli of lightstreamer.com
> has made an interesting observation concerning error handling with
> CompletableFuture.
> He said: “[CompletableFuture] views exceptions as some sort of showstoppers, not as special conditions each of which may deserve a different treatment. In fact, it does not allow you to selectively handling some types of exceptions while keeping others for further steps: you can only handle all types of possible exceptions in the same step, perhaps to log an error at the end of the processing” and wonders why this is so.
> If you pass futures around in the widespread kind of hierarchical structure, where each layer is responsible for handling certain exceptions, and exceptions may be converted and rethrown (think of data querying exceptions becoming converted to some kind of business logic exception), that may indeed become problematic. Looking at the signatures of
> handle <http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html#handle-java.util.function.BiFunction->(BiFunction <http://docs.oracle.com/javase/8/docs/api/java/util/function/BiFunction.html><? super T <http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html>,Throwable <http://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html>,? extends U> fn)
> and
> exceptionally
> <http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html#exceptionally-java.util.function.Function->
> (Function
> <http://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html>
> <Throwable
> <http://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html>,?
> extends T
> <http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html>
> > fn)
> one sees that one gets a catchall clause for Throwables, and that
> rethrowing is impossible because (Bi)Function#apply() does not throw.

Apparently, CompletableFuture does not  take too kindly to checked
exceptions [1].

A lot of people even consider checked exceptions a design mistake on the
language level. Nevertheless, most Java programmers and APIs do use checked
exceptions, for returning alternative results, and for flow controls.

A workaround is to create your own helper method like

    static <T,X> CF<T> catch_(CF<T> cf, Class<X> exceptionType, FuncE<X,T>
exceptionHandler) { ... }

where FuncE is similar to Function, except the apply() method throws

Then you can use it like

    catch_( future, SomeException.class, ex->someValue )

    catch_( future, SomeExcpetion.class, ex->throw new AnotherException() )

That is what we did in bayou Async API [2]. The problem you posted early
can be solved in bayou as

              .catch_(TimeoutException.class, ex->defaultValue);


Zhong Yu
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20140826/92af45a5/attachment.html>

More information about the Concurrency-interest mailing list