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.
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.
I don't know much about vavr, but looking in the javadoc for the library, you can see the onFailure method takes a Consumer<? super Throwable> as a parameter. The problem is that consumers do not declare checked exceptions, so you will never be able throw checked exceptions from your lambda.
That being said, what I generally do in these cases is I create a "wrapping" class that will accept checked exceptions, all this wrapping class will do is catch any checked exceptions and wrap them in a runtime exception. For example:
public class ThrowingConsumerHelper {
public static <T> Consumer<T> throwingConsumer(
ThrowingConsumer<T> consumer) {
return object -> {
try {
consumer.accept(object);
} catch (Throwable t) {
throw new RuntimeException(t);
}
};
}
#FunctionalInterface
public interface ThrowingConsumer<T> {
void accept(T t) throws Exception;
}
}
And then use this like this:
import static ThrowingConsumerHelper.throwingConsumer;
public static void main(String[] args) {
onFailure(throwingConsumer(object -> { throw new Exception("Bug"); }));
}
public static void onFailure(Consumer<? super Throwable> consumer) {
// Do something
}
Related
I have recently started using RxJava2 in one of my projects and currently I am working on implementing error handling in it.
I have written a mock class below in which I was initially throwing the error after wrapping it in a custom exception. However some of the examples I came across on error handling on stackoverflow and other sites used Single.error instead.
I used both approaches and they resulted in my subscribers onError method being invoked with the / by zero exception. I didn't notice any difference between the two.
There is comprehensive documentation on Error Handling and Error Handling Operators along with a lot of other articles on how to handle the exception after it is thrown. But the information in the javadoc for Single.error and Observable.error is quite minimal.
Is there an advantage of using Single.error or Observable.error over just throwing the exception? When do we choose one approach over the other?
public class Test {
public static void main(String[] args){
Single.just(1)
.flatMap(x -> externalMethod(x))
.subscribe(
s -> System.out.println("Success : " + s),
e -> System.out.println("Error : "+e)
);
}
public static Single<Integer> externalMethod(int x){
int result = 0;
try{
/* Some database / time consuming logic */
result = x % 0;
}
catch (Exception e){
throw new CustomException(e.getMessage()); // --> APPROACH 1
OR
return Single.error(new CustomException(e.getMessage())); // --> APPROACH 2
}
return Single.just(result);
}
}
Actually it does not matter, becaues RxJava tries to catch and relay all Throwables
APPROACH 1 -- throw new CustomException();
(io.reactivex.internal.operators.single.SingleFlatMap)
#Override
public void onSuccess(T value) {
SingleSource<? extends R> o;
try {
o = ObjectHelper.requireNonNull(mapper.apply(value), "The single returned by the mapper is null");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
downstream.onError(e);
return;
}
if (!isDisposed()) {
o.subscribe(new FlatMapSingleObserver<R>(this, downstream));
}
}
You see here, that given mapper from flatMap is invoked with an try-catch. If the mapper throws a Throwable, the Throwable will be forwarded via onError to downstream subscriber.
APPROACH 2 -- return Single.error(...)
(io.reactivex.internal.operators.single.SingleError)
Single#error
#Override
protected void subscribeActual(SingleObserver<? super T> observer) {
Throwable error;
try {
error = ObjectHelper.requireNonNull(errorSupplier.call(), "Callable returned null throwable. Null values are generally not allowed in 2.x operators and sources.");
} catch (Throwable e) {
Exceptions.throwIfFatal(e);
error = e;
}
EmptyDisposable.error(error, observer);
}
public static void error(Throwable e, SingleObserver<?> observer) {
observer.onSubscribe(INSTANCE);
observer.onError(e);
}
Single#error emits given Throwable on subscription via #onError
When a value is emitted to Single#flatMap the mapper is applied and a subscription is opened returned value from the mapper.
(io.reactivex.internal.operators.single.SingleFlatMap.SingleFlatMapCallback.FlatMapSingleObserver)
#Override
public void onSubscribe(final Disposable d) {
DisposableHelper.replace(parent, d);
}
#Override
public void onError(final Throwable e) {
downstream.onError(e);
}
The returned Single returns a Single#error, which emits a Throwable via #onError. Given #onError will be delegated to the downstream subscriber via onError.
Performance wise one could be faster than the other, but this must be measured to have an exact image. Returning Single#error does more allocations and has more methods on the Stack (subscribeActual). On the other side, when throwing a Throwable it must be caught and handeled.
Therefore in my opinion it acutally does not matter, whether you use the one or the other.
Given a function that might throw:
public static int f() throws Exception {
// do something
}
Is there any way this code:
public static int catchF() throws Exception {
try {
return f();
} catch (Exception ex) {
throw ex;
}
}
is any different to calling f directly? I.e. could the caller detect the difference by inspecting the exception? Is there any discernible overhead in using catchF instead of f?
If there is no difference, can compilers, or the JVM, optimise a call to catchF into a direct call to f?
While this might seem like a strange thing to do, the use case would be to re-introduce an exception at the type level after earlier hiding it:
class Test {
// Hide the exception.
public static <X extends Exception, T> T throwUnchecked(Exception ex) throws X {
throw (X) ex;
}
// Interface for functions which throw.
interface Throws<T, R, X extends Exception> {
R apply(T t) throws X;
}
// Convert a function which throws a visible exception into one that throws a hidden exception.
public static <T, R, X extends Exception> Function<T, R> wrap(Throws<T, R, X> thrower) {
return t -> {
try {
return thrower.apply(t);
} catch(Exception ex) {
return throwUnchecked(ex);
}
};
}
// Unhide an exception.
public static <R, X extends Exception> R unwrap(Supplier<R> supp) throws X {
try {
return supp.get();
} catch (Exception ex) {
throw (X)ex;
}
}
public static Stream<Integer> test(Stream<String> ss) throws NumberFormatException {
return Test.<Stream<Integer>, NumberFormatException>unwrap(
() -> ss.map(wrap(Integer::parseInt))
);
}
public static void main(String[] args) throws NumberFormatException {
final List<Integer> li = test(Arrays.stream(new String[]{"1", "2", "3"})).collect(toList());
System.out.println(li);
}
}
The intent is to wrap functions that throw exception into ones where the exception is hidden at the type level. This makes the exceptions usable for example with streams.
is any different to calling f directly?
No.
I.e. could the caller detect the difference by inspecting the exception?
No, because you're not constructing a new exception at this point. The stack trace was constructed at the point where the new WhateverException(...) was invoked (not where the throw was, although they are often in the same place).
Typically, you rethrow a caught exception if you need to do some cleanup as a result of the exception:
try {
// ...
} catch (SomeException e) {
// Clean up resources.
throw e;
}
The fact that something happened as the call stack was unwound is neither visible nor relevant to the caller.
A quick demo can show that the stack traces are identical whether the exception is caught and rethrown or simply allowed to propagate.
Is there any discernible overhead in using catchF instead of f?
The overhead of constructing the exception will far outweight any overhead of this redundant construct.
An exception handler that simply rethrows and does not affect the known types of the exceptions has absolutely no semantic effect.
In theory, then, compilers or the JVM could optimize the try-catch out. In practice, I doubt that they do, because such code should be rare and not on hot paths (exceptions should never be); it's probably not worth the effort to implement such an optimization.
Is there a way to have an Observable just throw an exception that occurs from within a function like flatMap()?
In Java, on a normal function, you can specify that it may throw an exception:
public void dangerousFunction() throws IOException {}
Within an Observable function like flatMap(), I can't seem to find a similar syntax. I can use a try/catch like this:
myObservable.flatMap(() -> {
try {
return dangerousFunction();
} catch (IOException e) {
return Observable.error(e);
}
});
Is there a cleaner method for writing that? If I have lots of maps and/or Observables, that winds up being a lot of try/catch blocks cluttering up my code.
The standard approach to dealing with exceptions in a RxJava map() method is propagate the exception by catch-and-throw. For example:
.map(b -> {
try {
...
} catch (IOException ex) {
// manual catch and throw
throw new RuntimeException(ex);
// or catch-and-throw using a built-in helper
throw Exceptions.propagate(e);
}
})
This can be get quite verbose when repeated across multiple map() calls so you could define a helper to wrap this behaviour e.g.
observable.map(RxMapWrapper.wrapAndThrow(new RxMapWrapper.Func1Wrapper<A, B>() {
#Override
public B call(A document) throws Exception {
// your map logic here ...
}
}))
public class RxMapWrapper {
public static <T, R> Func1<T, R> wrapAndThrow(Func1Wrapper<T, R> caughtFunction) {
return t -> {
try {
return caughtFunction.call(t);
} catch (Exception e) {
throw Exceptions.propagate(e);
}
};
}
public interface Func1Wrapper<T, R> extends Function {
R call(T t) throws Exception;
}
}
If you only want to return Observable.error(e) inside catch blocks, you don't need try/catch at all. Exception would go to downstream and .subscribe(,throwable) will catch it anyway.
If you want to return some other/default object when error occurred, try these operators: onErrorReturnItem, onErrorResumeNext, onErrorReturn. This would be cleaner.
Other option would be implementing this onErrorReturnItem mechanism into your methods itself instead of throwing Exception.
With following code,
void key(Key) throws SomeCheckedException {
}
void supplier(Supplier<Key> s) throws SomeCheckedException {
ofNullable(s).ifPresent(s -> { // |
try { // |
key(s.get()); // |
} catch (final SomeCheckedException sce) { // |
// sce is coming from key() method // |
// How can I throw sce for outer method? // --/
}
});
}
How can I throw sce as if the method(supplier) method is throwing it?
Please note that above code is just an example. I need the key(s.get()) to be inside a lambda expression.
void supplier(Supplier<Key> s) throws SomeCheckException {
key(s.get());
}
You can't. Supplier#get() does not declare to throw any (checked) exceptions. Remember that a lambda expression simply creates an instance, it doesn't actually invoke the target functional interface method.
If you want to, you can wrap the checked exception in an unchecked exception and throw that.
If you want to process checked exceptions in a safe manner you need a helper method which provides the facility of wrapping the exception into a sub-type of RuntimeException. Here is such a helper function which uses Generic’s type safety to ensure that only declared exceptions will be re-thrown (unless you use an unsafe operation):
public static <E extends Throwable> void attempt(
Consumer<Function<E,RuntimeException>> action) throws E {
final class CarryException extends RuntimeException {
final E carried;
CarryException(E cause) {
super(cause);
carried=cause;
}
}
try { action.accept( CarryException::new ); }
catch(CarryException ex) { throw ex.carried; }
}
It supports an arbitrary action which will receive a function which does the temporary wrapping of the checked exception type to the RuntimeException. This wrapping will be transparent, the method attempt will either complete normally or throw the original checked exception E (or an unrelated unchecked exception if one occurs).
So you can use it like this:
public static void processIterm(Supplier<Key> s)
throws SomeCheckedException {
attempt( (Function<SomeCheckedException, RuntimeException> thrower) ->
Optional.ofNullable(s).ifPresent(nonNull -> {
try { key(nonNull.get()); } // assuming key may throw SomeCheckedException
catch(SomeCheckedException e) { throw thrower.apply(e); }
}));
}
Due to the nested operations the compiler is unable to infer the exception type automatically. The code above use an explicit declaration of the thrower parameter type. Alternatively you can use a type invocation of the helper method like
ContainingClass.<SomeCheckedException>attempt( thrower ->
Optional.ofNullable(s).ifPresent(nonNull -> {
try { key(nonNull.get()); }
catch(SomeCheckedException e) { throw thrower.apply(e); }
}));
I want a method that can throw any Throwable including sub classes of Exception. Ive got something that takes an exception, stashes it in a thread local, then invokes a class.newInstance. That class ctor declares that it throws Exception then takes the threadlocal and throws it. Problem is it does not work for the two declared Exceptions thrown by Class.newInstance() namely IllegalAccessException and InstantiationException.
Im guessing any other method using some sun.* class is just a hack and not really reliable.
Wrapping is not an option because that means catchers are catching a diff type and that's just too simple and boring...
static public void impossibleThrow(final Throwable throwable) {
Null.not(throwable, "throwable");
if (throwable instanceof RuntimeException) {
throw (RuntimeException) throwable;
}
if (throwable instanceof Error) {
throw (Error) throwable;
}
try {
THROW.set((Exception) throwable);
THROWER.newInstance();
} catch (final InstantiationException screwed) {
throw new Error(screwed);
} catch (final IllegalAccessException screwed) {
throw new Error(screwed);
} finally {
THROW.remove();
}
}
private final static Class<Impossible> THROWER = Impossible.class;
private final static ThreadLocal<Exception> THROW = new ThreadLocal<Exception>();
static private class Impossible {
#SuppressWarnings("unused")
public Impossible() throws Exception {
throw THROW.get();
}
}
From Java Puzzlers (puzzle 43):
public static void impossibleThrow(Throwable t)
{
Thread.currentThread().stop(t); // Deprecated method.
}
The book shows other methods of achieving the same problem, one is a simplified version of yours, the other exploits generic type erasure to throw any Throwable where an Error is expected.
If you want an Exception to bubble up through code not expecting that exception then just wrap it in a RuntimeException
} catch (RuntimeException e) {
throw e; // only wrap if needed
} catch (Exception e) {
throw new RuntimeException("FOO went wrong", e);
}
Remember to let the message be informative. Some day you will have to fix a bug based only on the information in the stack trace.
Wrapping an exception inside a RuntimeException (as suggested by Thorbjørn) is the way to go. However, you usually want to maintain the stacktrace of the original excpetion. Here's how:
public static void rethrow(final Throwable t)
{
if(t instanceof RuntimeException)
throw (RuntimeException) t;
RuntimeException e = new RuntimeException(t);
e.setStackTrace(t.getStackTrace());
throw e;
}
I patched javac to remove the error, compiled impossibleThrow(), renamed the source file to something that does not end in .java (which forces the next compile to use the existing .class) and used that.
There is some validity for this question as a debugging tool. Suppose you are working with some code that may have failed and you see that it (perhaps) catches certain exceptions and (perhaps) throws certain exceptions. You suspect that an unexpected exception was not caught. However, the underlying code/system is too complex and the bug is too intermittent to allow you to step through in the debugger. It can be usefull to add the throwing of an exception without changing the method in any other way. In this case, wrapping the exception with a RuntimeException would not work, because you want the calling methods to behave normally.