Search code examples
javavavrresilience4j

How to throw exception when Try.of() fails?


I want to throw Exceptions that are extended from Exception if Try.ofCallable() fails.

I have a callable of the type:

final Callable<MyResponse> decoratedCallable =
    circuitBreakerService.getDecoratedMethod(
        myArg1, 
        () -> myFunction(myArg1, myArg2, myArg3)
    );

I am trying something like this:

Try.ofCallable(decoratedCallable).onFailure(throwable -> {
    if (throwable instanceof CallNotPermittedException) {
        throw new MyRuntimeExceptionA("msg1", throwable);
    } else {
        throw new MyRuntimeExceptionB("msg2", throwable);
    }
});

This works (the function that wraps the above two statements throws the correct exception MyRuntimeExceptionA and MyRuntimeExceptionB) if both MyRuntimeExceptionA and MyRuntimeExceptionB extend RuntimeException, but not if they extend Exception.

If they extend Exception then I am not able to throw them from the main function. The IDE asks to wrap them in try/catch - which I don't want.


Solution

  • You have two options. You can throw when you try to unwrap the Try by getting the value with the following code:

    Try.ofCallable(decoratedCallable)
        .getOrElseThrow(throwable -> {
            if (throwable instanceof CallNotPermittedException) {
                return new MyExceptionA("msg1", throwable);
            } else {
                return new MyExceptionB("msg2", throwable);
            }
        })
    

    or move out the error mapping code to before unwrapping with a similar code:

    Try.ofCallable(decoratedCallable)
        .mapFailure(
            Case(
                $(instanceOf(CallNotPermittedException.class)),
                throwable -> new MyExceptionA("msg1", throwable)
            ),
            Case($(), throwable -> new MyExceptionB("msg2", throwable))
        )
        .get()
    

    Both solutions will only throw when unrwapping, so if you want to throw early, you will have to unwrap early.

    Otherwise, I would take the advice others posted in comments not to throw exceptions if you are using Try. The whole point in using Try is to work with total functions instead of partial functions that can throw exceptions.