Asynchronous exceptions

We're almost done, but we need to cover two important things that we have to remember when writing asynchronous code: exceptions and timeouts. In synchronous code, we catch exceptions by using a try..catch block. Timeouts also trigger exceptions, so we can handle them in the same way. With asynchronous invocations, we catch exceptions in a different way. Exceptions are handled in callbacks, in a similar way to how we handle a future return value if the execution completes normally. The CompletionStage interface provides methods to register exception callbacks. Unless we return CompletionStage from a method, we have to remember to register an exception callback to handle exceptions, otherwise they would be silently ignored.

This is very different from a synchronous execution, where exceptions are propagated out of a method and are either caught in another component, by a container, or by the JVM as a last resort. In the asynchronous world, if there's no callback to handle an exception, we risk that nothing else will handle it and we won't find out about it at all. Ignoring exceptions may lead to lots of negative consequences, so we should always remember to add an exception callback at the end of asynchronous execution. 

The simplest way of catching exceptions with CompletionStage in an asynchronous JAX-RS method is to return CompletionStage. In this case, the container will register an exception handler and properly handle the exception, usually by printing an error message into the log. If we want to handle the exception ourselves, we can provide an exception handler with the exceptionally method. This method expects a lambda function that accepts a Throwable argument. The lambda function is executed if any of the previous stages ends with an exception, skipping all the intermediate stages. We will use this method to complete the REST response with an exception by calling the resume method with an exception instead of a result value, as follows:

finalStage.exceptionally(e -> {
Throwable cause = (e instanceof CompletionException) ? e.getCause() : e;
asyncResponse.resume(cause);
return null;
});

Because the exceptionally method almost always wraps the original exception into CompletionException, we retrieve the original exception with the getCause method. We also return the null value, just to satisfy the contract of the callback, as no further stage will use that value.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.73.175