Throwing an exception on subscription in RxJava

Viewed 3257

Consider the following code :

  public static void main(String[] args) {
    try {
        observableTesting();
    } catch (Exception ex) {
        System.out.println("Exception propagated : " + ex.getLocalizedMessage());
    }
}


private static void observableTesting() throws Exception{
    Observable.fromCallable(() -> { throw new Exception("TEST"); })
            .subscribe(
                    next -> {},
                    error ->
                    {
                        System.out.println("Error : " + error.getLocalizedMessage());
                        throw new Exception(error);
                    }

            );}

I would expect this to throw an exception and to propagate it to the calling function. This doesn't seem to produce the desirable effect.

As a workaround, I currently have to assign the error and throw it at the end of the function.

Are there any better ways to convert observable errors into exceptions?

2 Answers

It seem you're using rxjava-2. Under this version, the specification for errors state that all not handled Throwable will be delivered through either the Thread.UncaughtExceptionHandler installed on the system or the error handler installed via RxJavaPlugins.setErrorHandler(). If you're seeking to test the whether an observable throws or not, you can use TestObserver instead, as:

Observable
     .fromCallable(() -> { throw new Exception("TEST"); })
     .test()
     .assertSubscribed()
     .assertError(Exception.class);

the behavior that you're seeing is the expected behavior. refer to the documentation on error handling:

An Observable typically does not throw exceptions. Instead it notifies any observers that an unrecoverable error has occurred by terminating the Observable sequence with an onError notification.

There are some exceptions to this. For example, if the onError() call itself fails, the Observable will not attempt to notify the observer of this by again calling onError but will throw a RuntimeException, an OnErrorFailedException, or an OnErrorNotImplementedException.

to that end, re-throwing the exception is exactly what you should do to get the result that you're instead expecting.

Related