How to create a Mono<Void> that actually emits an element?
Asked Answered
N

1

8

So I want to create a Mono<Void> (or any Mono<SomeIgnorableType>) that actually emits an element. Why? Because I actually want to run an effect, and the result just implies the effect was run, YET, it can be ignored.

In Haskell Void is an uninhabitable type... like the Nothing in Scala. In Java Void is also uninhabitable, yet it is used more like the Unit type in Scala or the () (0 arity tuple) in Haskell. A type with only one inhabitant.

Ok, too much with the theory. My options so far:

  1. Mono.just((Void) null) throws an Exception.

  2. Mono.empty().single() (because I actually want to emit an event), ends up with failure, when one subscribes to it. And...

  3. Mono.just("something").then() runs the effect, but then I cannot chain it with other monos, because it only emits complete and error events.

So how???

Neisa answered 25/3, 2021 at 21:6 Comment(5)
I found this #48556582, which actually implies that this is not a reactor problem, more than a Java design problem. :facepalm: Java!Neisa
I'm actually starting to consider using Mono<Tuple0> (Tuple0 from Vavr).Neisa
A void Mono is naturally empty. You can construct it with Mono.empty(). Why do you need it to have a value? Sometimes it´s useful to emit a value (e.g. to zip with another mono). In this case I wrap the value in an Optional. I suppose you could use Mono<Optional<Void>> in your case.Tuppence
Exactly, I need it to emit a value to use FlatMap or Zip, or map or... Well, every method that needs a value on Mono. I migrated to rxjava Single<Tuple0> eventuallyNeisa
For instance if you want to zip a void mono completion a with another mono b then you can rather use a.then(b). If you are using rxjava then you can use CompletableTuppence
L
4

Java's lack of null-safety means the unit type concept doesn't translate particularly well. I've never been convinced when people have postulated Void as equivalent to a unit type. You can never instantiate it by design; you can assume that any reference containing the Void type is null, which I don't really see as a value - it's more the absence of any value (ie. an uninhabitable type.)

There's nothing that I would consider a "real" unit type built into Java, but you can create one trivially via the use of an enum with a single value:

public enum Unit {UNIT}

If your Mono type is then set to Unit, this does what you need - you can either complete the Mono with no value, you can complete it with a single Unit value (and ignore the value, just reacting to the fact it's there), or complete it with an error. It sounds like that's exactly what you're after.

That said, answering the question directly and ignoring whether you should (you shouldn't IMHO), you can mock Void to actually assign it a non-null value. Mockito can do it no problem, you just need to make sure Mockito is configured so it can mock final classes:

Void v = Mockito.mock(Void.class);
Mono.just(v)
        .doOnNext(actualVoid -> System.out.println(actualVoid))
        .block();

Prints: Mock for Void, hashCode: 1830745997

(It's not something I've ever done, nor felt the need to do, but that doesn't prevent you from technically doing it.)

Lashkar answered 25/3, 2021 at 22:33 Comment(1)
I ended up using the Tuple0 from vavr. I posted in the comments of the question my thoughts as I continued looking for solutions. What you suggested was one of my options tooNeisa

© 2022 - 2024 — McMap. All rights reserved.