[concurrency-interest] CompletableFuture exception handling

Dennis Sosnoski dms at sosnoski.com
Tue Jun 17 22:39:27 EDT 2014


I've been playing with an example of composing sequences of events 
represented by CompletableFutures. task1 starts directly, then when it 
completes successfully I want to start task2 and task3, when these both 
complete successfully I want to start task4, then when task4 completes I 
want to set the completion of the future that represents the entire set 
of tasks.

Here's code to do this with exceptions ignored:

     private static CompletableFuture<Integer> runNonblocking() {
         CompletableFuture<Integer> result = new 
CompletableFuture<Integer>();
         task1(1).thenAccept(i1 -> {
             CompletableFuture<Integer> future2 = task2(i1);
             CompletableFuture<Integer> future3 = task3(i1);
             future2.thenAcceptBoth(future3, (i2, i3) ->
                 task4(i2 + i3).thenAccept(i4 ->
                     result.complete(i4)));
         });
         return result;
     }

That seems reasonable and fairly easy to understand. But if I want to 
also propagate exception completions from the individual tasks into the 
composite task I get something like this:

     private static CompletableFuture<Integer> runNonblocking() {
         CompletableFuture<Integer> result = new 
CompletableFuture<Integer>();
         task1(1).whenComplete((i1, t1) -> {
             if (t1 != null) {
                 result.completeExceptionally(t1);
             } else {
                 CompletableFuture<Integer> future2 = task2(i1);
                 CompletableFuture<Integer> future3 = task3(i1);
                 future2.whenComplete((i2, t2) -> {
                     future3.whenComplete((i3, t3) -> {
                         if (t2 != null) {
                             result.completeExceptionally(t2);
                         } else if (t3 != null) {
                             result.completeExceptionally(t3);
                         } else {
                             task4(i2 + i3).whenComplete((i4, t4) -> {
                                 if (t4 != null) {
result.completeExceptionally(t4);
                                 } else {
                                     result.complete(i4);
                                 }
                             });
                         }
                     });
                 });
             }
         });
         return result;
     }

This seems, well, /exceptionally/ complex. Am I missing some simpler way 
of doing this kind of composition of futures, or am I just totally 
outside the use cases in wanting to do this in the first place?

It would be cleaner if whenComplete accepted two separate functions, one 
for success and the other for an exception, since that would get rid of 
the null checks.

Thanks for any feedback,

   - Dennis

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20140618/a1e909fb/attachment.html>


More information about the Concurrency-interest mailing list