How to return Mono<B> from Mono<A> on error?

Sergey picture Sergey · Apr 18, 2018 · Viewed 7.6k times · Source

Let's say i have the following chain:

public Mono<B> someMethod( Object arg ) {
  Mono<A> monoA = Mono.just( arg ).flatMap( adapter1::doSomething );
  // success chain
  return monoA.map( B::buildSuccessResponse );
}

But in case of error i need to return different type of B, let's say, B.buildErrorResponse( a ). Any onError / doOnError methods can return only original Mono type (A), but not the one I need to return (B). How to return different Mono type in case of error?

Answer

Stav Alfi picture Stav Alfi · Apr 22, 2018
public Mono<B> someMethod(Object arg) {
    return Mono.just(arg)
            .flatMap(adapter1::doSomething)
            .onErrorResume(throwable -> throwable instanceof Exception,
                           throwable -> Mono.just(B.buildErrorResponse(throwable)))
            .map(B::buildSuccessResponse);
}

onErrorResume will catch the error signal if it was thrown in upstream and will replace all that stream (the upstream) with a new stream: Mono.just(B.buildErrorResponse(throwable)).


Side note about someMethod logic:

  1. In case of an error, this method will signal a next signal which indicates error signal: B.buildErrorResponse(throwable). It sounds like a bad idea because who will use someMethod must understand if the next signal he received from upstream (someMthod) is next or error signal by if-condition. Instead, let someMethod return the actual error signal and the user will react to that error as he wants by recognizing the error in, for example, onErrorResume.

  2. I have the same argument for B::buildSuccessResponse.

  3. The following code can be replaced: Mono.just(arg).flatMap(adapter1::doSomething) with adapter1.doSomething(arg).

All in all, the final code will be refactored to:

public Mono<B> someMethod(Object arg) {
    return adapter1.doSomething(arg).
}