Lets say you have Mono<Integer> someIntegerSource = Mono.just(5)
and you want to assign it to a variable.
Is there a difference between these code snippets?
Case 1: doOnSuccess
someIntegerSource.doOnSuccess(number -> this.myNumber = number)
Case2: doOnNext
someIntegerSource.doOnNext(number -> this.myNumber = number)
Case 3: doOnSuccess + then (because i want to the assignment to be complete before emitting completion of the mono)
someIntegerSource.doOnSuccess(number -> this.myNumber = number).then()
1. Since doOnNext provides you the element flowing through the pipeline with a Consumer , it is after. Order is something like this: source emits item -> doOnNext lambda is triggered -> subscriber onNext is called: github.com/reactor/reactor-core/blob/master/reactor-core/src/…
Mono subscribe() The subscribe() method with no arguments subscribes to the Mono and requests for the data from the publisher. It does not consume the data and also has no error handling mechanism.
Read the documentation of the class Mono
and see the diagrams. Their explanation of behavior is pretty clear. There are hardly noticeable differences but still, they are:
Mono::doOnNext
triggers when the data is emitted successfully, which means the data is available and present.Mono::doOnSuccess
triggers when the Mono
completes successfully - result is either T
or null
, which means the processing itself successfully finished regardless the state of data and is executed although the data are not available or present but the pipeline itself succeed.Mono::then
as the end of the methods chain returns Mono<Void>
on complete and error signals.
Mono<Void>
from Mono<T>
. Note the two methods above don't throw the payload away.Follow the illustrative examples below:
A Mono
that holds a value triggers doOnNext
when the data is emitted successfully. This can be confusing to the doOnSuccess
, but contrary to such trigger, doOnNext
is triggered when any successful value is emitted including an empty Mono
, which is still valid.
Mono.just("Hello World")
.doOnNext(i -> System.out.println("On next: " + i))
.doOnSuccess(i -> System.out.println("On success: " + i))
.doOnError(i -> System.out.println("On error: " + i))
.block();
On next: Hello World
On success: Hello World
Remember, although the Mono
is empty (Mono.empty()
), it is still a valid response that triggers doOnSuccess
, however not doOnNext
, An empty Mono
can be understood as one with a valid response that doesn't represent the desired output that contains a useful value. It works on the same principle as Optional.empty()
. The Mono
is successful but has no real useful value that would trigger doOnNext
as it doesn't emit any value at all.
Mono.empty()
.doOnNext(i -> System.out.println("On next: " + i))
.doOnSuccess(i -> System.out.println("On success: " + i))
.doOnError(i -> System.out.println("On error: " + i))
.block();
Mono.just("Hello World")
.mapNotNull(s -> null)
.doOnNext(i -> System.out.println("On next: " + i))
.doOnSuccess(i -> System.out.println("On success: " + i))
.doOnError(i -> System.out.println("On error: " + i))
.block();
Both result in the same output:
On success: null
For sake of completeness to put in contrast with an empty Mono
, the erroneous doesn't trigger either doOnNext
or doOnSuccess
but does doOnError
instead:
Mono.error(new RuntimeException("Something wrong"))
.doOnNext(i -> System.out.println("On next: " + i))
.doOnSuccess(i -> System.out.println("On success: " + i))
.doOnError(i -> System.out.println("On error: " + i))
.block();
On error: java.lang.RuntimeException: Something wrong
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With