Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in...

25
Advanced Java CompletableFuture Features: Handling Runtime Exceptions Douglas C. Schmidt [email protected] www.dre.vanderbilt.edu/~schmidt Professor of Computer Science Institute for Software Integrated Systems Vanderbilt University Nashville, Tennessee, USA

Transcript of Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in...

Page 1: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

Advanced Java CompletableFuture Features:

Handling Runtime Exceptions

Douglas C. [email protected]

www.dre.vanderbilt.edu/~schmidt

Professor of Computer Science

Institute for Software

Integrated Systems

Vanderbilt University

Nashville, Tennessee, USA

Page 2: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

2

• Understand advanced featuresof completable futures, e.g.

• Factory methods initiate async computations

• Completion stage methods chaintogether actions to perform async result processing & composition

• Method grouping

• Single stage methods

• Two stage methods (and)

• Two stage methods (or)

• Apply these methods

• Handle runtime exceptions

Learning Objectives in this Part of the Lesson

Exception methods

Completion stage methods

Factory methodsArbitrary-arity

methods

Basic methods

Page 3: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

3

Handling Runtime Exceptionsin Completion Stages

Page 4: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

4

• Completion stage methodshandle runtime exceptions

Handling Runtime Exceptions in Completion Stages

See www.jesperdj.com/2015/09/26/the-future-is-completable-in-java-8

Exception methods

CompletionStage methods

Factory methodsArbitrary-arity

methods

Basic methods

Page 5: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

5

• Completion stage methodshandle runtime exceptions

Handling Runtime Exceptions in Completion StagesMethods Params Returns Behavior

whenComplete(Async)

BiConsumer

CompletableFuture withresult of earlier stage or throws exception

Handle outcome of a stage, whether a result value or an exception

handle(Async)

BiFunction

CompletableFuture withresult ofBiFunction

Handle outcome of a stage & return new value

exceptionally Function CompletableFuture<T>

When exception occurs, replace exception with result value

See community.oracle.com/docs/DOC-995305

Page 6: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

6

• This example shows three ways to handle exceptions w/completable futures

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

...An exception will occur if denominator param is 0!

See github.com/douglascraigschmidt/LiveLessons/tree/master/Java8/ex8

Page 7: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

7

• This example shows three ways to handle exceptions w/completable futures

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

...

An unhandled exception will terminate a program!

See rollbar.com/guides/java-throwing-exceptions

Page 8: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

8

• Using the handle() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.handle((fraction, ex) -> {

if (fraction == null)

return BigFraction.ZERO;

else

return fraction.multiply(sBigReducedFraction);

})

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

Handle outcome of the previous stage (always called, regardless of whether exception’s thrown)

See docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#handle

Page 9: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

9

• Using the handle() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.handle((fraction, ex) -> {

if (fraction == null)

return BigFraction.ZERO;

else

return fraction.multiply(sBigReducedFraction);

})

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

These values are mutually exclusive

Page 10: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

10

• Using the handle() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.handle((fraction, ex) -> {

if (fraction == null)

return BigFraction.ZERO;

else

return fraction.multiply(sBigReducedFraction);

})

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

The exception path

Page 11: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

11

• Using the handle() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.handle((fraction, ex) -> {

if (fraction == null)

return BigFraction.ZERO;

else

return fraction.multiply(sBigReducedFraction);

})

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

The “normal” path

Page 12: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

12

• Using the handle() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.handle((fraction, ex) -> {

if (fraction == null)

return BigFraction.ZERO;

else

return fraction.multiply(sBigReducedFraction);

})

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

handle() must return a value (& can thus change

the return value)

Page 13: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

13

• Using the handle() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.handle((fraction, ex) -> {

if (fraction == null)

return BigFraction.ZERO;

else

return fraction.multiply(sBigReducedFraction);

})

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

Display result as a mixed fraction

Page 14: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

14

• Using the exceptionally() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.exceptionally(ex -> BigFraction.ZERO)

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

See docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally

Page 15: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

15

• Using the exceptionally() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.exceptionally(ex -> BigFraction.ZERO)

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

An exception occurs if denominator is 0!

Page 16: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

16

• Using the exceptionally() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.exceptionally(ex -> BigFraction.ZERO)

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

Handle case where denominator != 0 (skipped if exception is thrown)

Page 17: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

17

• Using the exceptionally() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.exceptionally(ex -> BigFraction.ZERO)

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

Handle case where denominator == 0 & exception is thrown (otherwise skipped)

exceptionally() is akin to catch() in a Java try/catch block, i.e., control xfers to it

Page 18: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

18

• Using the exceptionally() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.exceptionally(ex -> BigFraction.ZERO)

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

Convert an exception to a 0 result

Page 19: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

19

• Using the exceptionally() method to handle exceptional or normal completions

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.exceptionally(ex -> BigFraction.ZERO)

.thenAccept(fraction ->

System.out.println(fraction.toMixedString()));

Display result as a mixed fraction

Page 20: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

20

• Using the whenComplete() method to perform a exceptional or normal action

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.whenComplete((fraction, ex) -> {

if (fraction != null)

System.out.println(fraction.toMixedString());

else

System.out.println(ex.getMessage());

});

Called under both normal & exception conditions

See docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#whenComplete

Page 21: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

21

• Using the whenComplete() method to perform a exceptional or normal action

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.whenComplete((fraction, ex) -> {

if (fraction != null)

System.out.println(fraction.toMixedString());

else

System.out.println(ex.getMessage());

});

These values are mutually exclusive

Page 22: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

22

• Using the whenComplete() method to perform a exceptional or normal action

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.whenComplete((fraction, ex) -> {

if (fraction != null)

System.out.println(fraction.toMixedString());

else

System.out.println(ex.getMessage());

});

Handle the normal case

Page 23: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

23

• Using the whenComplete() method to perform a exceptional or normal action

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.whenComplete((fraction, ex) -> {

if (fraction != null)

System.out.println(fraction.toMixedString());

else // ex != null

System.out.println(ex.getMessage());

});

Handle the exceptional case

Page 24: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

24

• Using the whenComplete() method to perform a exceptional or normal action

Handling Runtime Exceptions in Completion Stages

CompletableFuture

.supplyAsync(() ->

BigFraction.valueOf(100, denominator))

.thenApply(fraction ->

fraction.multiply(sBigReducedFraction))

.whenComplete((fraction, ex) -> {

if (fraction != null)

System.out.println(fraction.toMixedString());

else // ex != null

System.out.println(ex.getMessage());

});

whenComplete() is like Java Streams.peek(): it has a side-effect & doesn’t change the return value

See docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#peek

Page 25: Advanced Java CompletableFuture Features: Handling Runtime ... · Handling Runtime Exceptions in Completion Stages Methods Params Returns Behavior when Complete (Async) Bi Consumer

25

End of Advanced Java CompletableFuture Features: Handling Runtime Exceptions