Error handling in toBlocking()
Asked Answered
S

3

9

I'm refactoring an app to reactive paradigm using RxJava. I'm doing it step by step so I need to use toBlocking() in some cases in order to respect the interfaces, for the moment. How can I handle an error when use toBlocking()?

Before, I had something like this:

public List<Employee> getEmployees() {
    try {
        return repository.getEmployees();
    } catch(Exception e) {
        throw new MyCustomException();
    } 
}

Now, the repository has a reactive interface (returns Observable<List<Employee>>), so I'm doing this:

public List<Employee> getEmployees() {
    return repository.getEmployees().toBlocking().single(); 
}

Subscription to repository.getEmployees() may return an error Observable. My question is: how can I handle this error keeping it blocking?

I have found out a method singleOrDefault(), but something like singleOrThrow(new MyCustomException()) would be nice.

Sunless answered 14/3, 2017 at 12:39 Comment(0)
T
4

You can't do that, you will need to wrap it with try/catch block, toBlocking() transform the Observable to BlockingObservable which is not exactly reactive block, more like fancy collection, it's now lack the power of composing Observables, operators, controlling the thread/parallelism, and the basic construct of async API, which has error handling built in, (onError())

That what the docs stated about BlockingObservable:

It can be useful for testing and demo purposes, but is generally inappropriate for production applications (if you think you need to use a BlockingObservable this is usually a sign that you should rethink your design).

So, what is the point to act with blocking observable? if you can't change the interface to Observable, then you probably missing all the point of using Rx and Observable, which is (at ideal) to abstract out every event based operation in the system, and then being able to use the power of Operators/Composition/Async management and construct event streams in your system.
If you just wrap some API operation with Observable and then return it back to non-reactive world, then the consumer of the API can't enjoy all the aforementioned benefits of Rx.
So, I think you should reconsider what is the purpose of doing that, and what is your final goal, you can consider replacing to Reactive approach in few places in your system for start.

Tuxedo answered 14/3, 2017 at 13:34 Comment(1)
Thanks for the answer. Of course, you are right. It's useless use a reactive paradigm and then return to non-reactive model. But as I say in the question, I'm refactoring step by step: in the future I won't use BlockingObservable, but a complete reactive model. You clarified my doubt: I need to use a try/catch block. Thanks!Semeiology
C
2

We have another option to handler error by using variant method to handle error as onErrorReturn ...

public List<Employee> getEmployees() {
    return repository.getEmployees().onErrorReturn{
       //Do something 
       //Then return value in case error happened
    }.toBlocking().single(); 
}
Clasp answered 6/11, 2018 at 10:50 Comment(0)
L
1

Your MyCustomException is wrapped in RuntimeException by Rx, so you should catch RuntimeException then call getCuase() to get MyCustomException like below.

public List<Employee> getEmployees() {
    try {
        return repository.getEmployees().toBlocking().single(); 
    } catch (RuntimeException e) {
        MyCustomException myCustomException = e.getCause();
        if (e != null) {
            // caught MyCustomException
        }
    }
}
Leesaleese answered 1/7, 2019 at 3:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.