question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Single.blockingGet() -> BlockingMultiObserver/ExceptionCatcher should not wrap Exceptions?

See original GitHub issue

Version 2.1.9

Assuming this code:

return Single.error(new IllegalArgumentException("I'm the cause"));

I think there’s a issue in the design of ExceptionCatcher.wrapOrThrow. When calling blockingGet(), it wraps any instance of Exception but leaves Runtime and Error as-is. So basically you throw an exception somewhere but the Rx framework bubbles it up with a wrapper you have to unwrap to get your initial cause.

/**
     * If the provided Throwable is an Error this method
     * throws it, otherwise returns a RuntimeException wrapping the error
     * if that error is a checked exception.
     * @param error the error to wrap or throw
     * @return the (wrapped) error
     */
    public static RuntimeException wrapOrThrow(Throwable error) {
        if (error instanceof Error) {
            throw (Error)error;
        }
        if (error instanceof RuntimeException) {
            return (RuntimeException)error;
        }
        return new RuntimeException(error);
    }

It’s especially painful in unit tests, where you catch an Exception and have to sometime exception.getCause() and sometime only exception is good enough. So if your Single would be consumed by a Subscriber but you want to test it by blockingGet to ease your life, you end up with an extra coating of exception that won’t be there in your real scenario, leading to glue code in tests that don’t behave like the original code.

      Single<String> anySingle = Single.error(new IOException("I'm the cause"));
      try {
         anySingle.blockingGet();
      }
      // catch (RuntimeException e) {
      // Should fail, but will pass
      // Assert.assertTrue(e.getCause() instanceof IOException);
      // }
      catch (Exception e) {
         // Should pass, but will fail
         Assert.assertTrue(e instanceof IOException);
      }

The caller code that invokes the ExceptionCatcher is BlockingMultiObserver.

public T blockingGet() {
        if (getCount() != 0) {
            try {
                BlockingHelper.verifyNonBlocking();
                await();
            } catch (InterruptedException ex) {
                dispose();
                throw ExceptionHelper.wrapOrThrow(ex);
            }
        }
        Throwable ex = error;
        if (ex != null) {
            throw ExceptionHelper.wrapOrThrow(ex);
        }
        return value;
    }

I believe that the blockingGet() method should actually throws Exception

Is there any workaround for that?

Thank you very much

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:9 (7 by maintainers)

github_iconTop GitHub Comments

2reactions
artem-zinnatullincommented, Apr 19, 2018

Yep, Jesse sent it too, what a facepalm then šŸ¤¦ā€ā™‚ļø

It was even discussed before in RxJava

Well, that was a fun exercise I guess…

2reactions
artem-zinnatullincommented, Apr 19, 2018

Soo, I personally thank everyone (sarcasm) in this issue because you got me to interested and it’s 5:34 am…

I’ve built 0-deps java library that allows throwing checked exceptions without wrapping and without declaring it in method description

https://github.com/artem-zinnatullin/java-uncheck-exceptions

It’s not on maven central yet, but jar is available on releases page (or you can build it, see README)

TL;TR: yep, in Java source code you can’t throw checked exception without wrapping or declaring it. But in Java bytecode you can, so I do it from bytecode (you can read more in README and check implementation).

If you like it, we can integrate that class into RxJava and maybe Guava later.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why should I not wrap every block in "try"-"catch"?
A method should only catch an exception when it can handle it in some sensible way. Otherwise, pass it on up, in the...
Read more >
RxJava and Error Handling - Baeldung
First, keep in mind that the Observable typically does not throw exceptions. Instead, by default, Observable invokes its Observer's onError() ...
Read more >
Error handling in RxJava - Dan Lew Codes
How do you ensure that an Exception in, say, flatMap() gets passed ... can simply return Observable.error() instead of wrapping/throwing:
Read more >
io.reactivex.internal.observers.BlockingMultiObserver java ...
Subscribes to and awaits the termination of this Completable instance in a blocking manner and * rethrows any exception emitted.
Read more >
From RxJava to Kotlin Flow: Error Handling - ProAndroidDev
Not a single error can escape chain. All the exceptions ... Consumers need to wrap Flow with try-catch if they want to handle...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found