[concurrency-interest] CompletableFuture exception handling

Martin Buchholz martinrb at google.com
Wed Jun 18 15:09:47 EDT 2014


Probably just like in regular java code, handling exceptional behavior
should be rare because exceptions propagate through your code, and when
chaining a bunch of CompletableFutures, you can also by default let
exceptions propagate.  In the hopefully rare case where you do want to
handle the exceptions explicitly, you can use
handle/whenComplete/exceptionally/.

It's weird to call complete(value) in the leaf future.  Why not just
return .... .thenAcceptBoth(...)

But I haven't written "real" code using CompletableFuture myself - perhaps
others have and can report their experience?


On Tue, Jun 17, 2014 at 7:39 PM, Dennis Sosnoski <dms at sosnoski.com> wrote:

>  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
>
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20140618/acea12de/attachment.html>


More information about the Concurrency-interest mailing list