Here is the piece of code
@Test
public void test_mono_void_mono_empty() {
Mono.just("DATA")
.flatMap(s -> Mono.just(s.concat("-")
.concat(s))
.doOnNext(System.out::println)
.then())
.switchIfEmpty(Mono.just("EMPTY")
.doOnNext(System.out::println)
.then())
.block();
}
that gives the following result to the console:
DATA-DATA
EMPTY
That means that the chain in the first flatMap
was recognized as an empty one.
On the other hand Reactor has the following class MonoEmpty that is returned by a Mono.empty()
method. On top of that, the method says the following:
/**
* Create a {@link Mono} that completes without emitting any item.
*
* <p>
* <img class="marble" src="doc-files/marbles/empty.svg" alt="">
* <p>
* @param <T> the reified {@link Subscriber} type
*
* @return a completed {@link Mono}
*/
public static <T> Mono<T> empty() {
return MonoEmpty.instance();
}
without emitting any item - but I emitted Void
typed object with then()
method.
What is the explanation of that?
Mono<Void> is a type. Mono. empty() is a method invocation that returns a Mono that that completes without emitting any item.
Mono<Void> should be used for Publisher that just completes without any value. It is intended to be used in implementations and return types, input parameters should keep using raw Publisher as much as possible. Note that using state in the java. util.
customerFlux. collectList() is resulting in a Mono which contains an empty list when the originating Flux is empty. Therefore, the Mono is not empty (because it contains an empty list) and ok() is invoked.
A given Mono
can publish either nothing, or a single value before sending a completion signal. (It can't publish null
- the reactive spec forbids it.) The generic type of the Mono
denotes the type of the object that might be emitted - but there's no guarantee it will be emitted.
A Mono<Foo>
for example can emit just a completion signal, or an instance of Foo
and then a completion signal.
There's two common scenarios where a value may not be published - the first is if a value may or may not exist (such as searching for an item in a database or collection). In that case, you'd still use a Mono<SomeType>
, and it may or may not emit a SomeType
instance. The second scenario is if a value will definitely never be published (often used when you just need notification that a task has completed), and for that, by convention, Mono<Void>
is always used. then()
, in your above example, falls into the second case.
The reason that Mono<Void>
is a special case is that, as you point out, Void
is a class that can never be instantiated by design. There's therefore no such thing as an instance of Void
, which means the Mono
can never emit a value before its completion signal.
The logical conclusion therefore is that a publisher of type Mono<Void>
can never emit a value, only a completion signal - and so it is used as such.
Okay, the answer is in the official java doc that says The Void class is an uninstantiable placeholder class to hold a reference to the Class object representing the Java keyword void
.
That means that its main idea is simply to represent the void return type as a class and contain a Class<Void>
public value. That's it. Besides, it's not instantiable as the constructor is private. All of that subsequently means that the only value we can assign to a Void
variable is null
what always is recognized as empty Mono
.
helpful discussion: Java generics void/Void types
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