19

I want to have a Mono that calls another async method that returns an Optional type to:

  1. have a value if the Optional is not empty,
  2. is MonoEmpty if the Optional value is empty.

Here's what I do right now:

Mono.fromCallable(() -> someApi.asyncCall()) .filter(Optional::isPresent) .map(Optional::get)

Obviously, this is not ideal since it uses two operators after the callable completed. If possible, I'd like to have the Mono.empty() or mono value from inside fromCallable.

What is the best way to achieve what I want?

3 Answers 3

30

There is an alternative with flatMap that's a bit better than Optional.isPresent and Optional.get that can lead to accidentally calling get on empty Optional:

Mono.fromCallable(() -> someApi.asyncCall())
  .flatMap(optional -> optional.map(Mono::just).orElseGet(Mono::empty))
1
  • 11
    How about Mono.fromCallable(() -> someApi.asyncCall()).flatMap(Mono::justOrEmpty)
    – aksh1618
    Commented Nov 17, 2020 at 12:56
14

Mono have justOrEmpty method that you can use with Optional<? extends T> type. When Optional.empty() == true we would have MonoEmpty.

Create a new Mono that emits the specified item if Optional.isPresent() otherwise only emits onComplete.

Mono<String> value = Mono.justOrEmpty(someApi.asyncCall());
2
  • 2
    The problem here is you make the call someApi.asyncCall() immediately. accepted answer is better solution.
    – RamPrakash
    Commented Feb 5, 2021 at 21:24
  • I checked the source!! someApi.asyncCall() is invoked immediately. not lazy. The expectation is - mono should not execute anything unless someone subscribes
    – RamPrakash
    Commented Feb 26, 2021 at 17:25
5

How about:

Optional<Integer> optional = Optional.of(5);
Mono<Optional<Integer>> monoWithOptional = Mono.just(optional);
Mono<Integer> monoWithoutOptional = monoWithOptional.flatMap(Mono::justOrEmpty);

Not the answer you're looking for? Browse other questions tagged or ask your own question.