jdeferred / jdeferred

Java Deferred/Promise library similar to JQuery.

Home Page:jdeferred.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add Uncaught Exception Handler

saturnism opened this issue · comments

In DeferredManager, add ability to register a catch all uncaught exception handler. In case any Throwable was uncaught, pass it to the handler.

Applications should always try to handle known exceptions in the fail() handler explicitly. This is as a last-resort fallback.

By default, the handler will log the uncaught exception.

Related to #54

As I understand it, exceptions get recorded as the rejected value when the body of the promise throws an exception. This exception is sent to the FailureCallback if such callback is registered. This means handling exceptions that may occur during the task part of a promise is already managed.

What's missing is the case when unchecked exceptions occur during the following callbacks: then, done, fail, always. To be honest I think it's the job of the developer to handle these potential problems, as he/she already has to handle checked exceptions within these callbacks.

Adding another exception handler to Promise may look a bit odd, for example

deferredManager.when(() -> /* do the work */)
    .done(result -> throw new RuntimeException("boom!"))
    .fail(result -> {
         // handle exception that appeared in the _when_ block
         throw new IllegalStateException("oops"); })
    .always((state, result, throwable) -> {
         // well, guess we can throw too
         throw new IlegalArgumentException("Objection!"); })
    .exception(state, throwable -> {
        // this is the new callback capable of
        // handling exceptions thrown by
        // then, done, fail, always
    }); 

What happens if an exception is thrown during the exception block now? It's all turtles the way down.
Also, the always block is called regardless of how done and fail where handled. In this particular case the exception block should be called twice: one for the exception thrown by done/fail (depending on success or failure) and always, making this callback the only one that can be called more than once whereas the others can be called just one time.

Fixed with #131