RxJava throwing an exception or using onError

Viewed 492

Is there any way to decide whether an exception should be thrown by a method returning rxjava type or should be propagated through onError? If I have a method that should throw NPE if the argument is null, should this exception be thrown by the method itself or through the observable/flowable returned?

2 Answers

As a best practice, you should always propagate the error through onError. Otherwise, someone calling your method like this will end up not handling the exception properly:

public void doStuff() {
  someMethodReturningCompletable()
      .andThen(yourMethodThatThrows(argument))
      .subscribe(v -> { /* success */ }, err -> { /* this won't get called */);
}

If your method throws and exception immediately if argument is null, two bad things happen:

  1. You throw it before the subscribe call is even executed, and possibly before someMethodReturningCompletable() is actually executed (since it hasn't been subscribed to yet).
  2. The exception doesn't get propagated downstream, it just is thrown into doStuff(), and it isn't set up to handle that.

The way I think about it is: onError belongs to the stream, so it should notify about errors related to the stream. The argument of a method which returns a stream is part of the method's contract, not part of the stream itself.

Said another way: an issue creating the stream is not the same as an issue of execution of the stream.

So why should a violation of the method's contract go into the stream? I don't see an issue in checking that arguments respect some preconditions when the method is called and throwing an exception if they are violated.

Plus, this is also how many RxJava methods work, e.g. Observable.just and Observable.range.

Related