2

During some reactive programming in Java using project reactor library, I stumbled upon a pattern for which I'm wondering if there is out of box support?

So I want the code below:

Mono.just("hello")
    .flatMap(hello -> reactiveAction(hello).thenReturn(hello))
    ..
    .;

to be turned into something like:

Mono.just("hello")
    .coolOperation(this::reactiveAction)
    ..
    .;   

I can not use doOnNext because what I want to do inside reactiveAction is not side effect. and reactive action is:

Mono<Integer> reactiveAction(String text){
  return ....
}
Mahdi Amini
  • 402
  • 1
  • 3
  • 17
  • 2
    This sounds like a nice feature request. You might open an issue in the Reactor GitHub repository. – Martin Tarjányi Apr 08 '20 at 19:52
  • 1
    @MichaelBerry Do you still insist on your comment that it is not possible? I think that the `Mono#delayUntil()` pretty well answer the question and it has been accepted. – Honza Zidek Nov 19 '21 at 23:58
  • 2
    @HonzaZidek Nope, I was wrong. Always happy to be wrong, I had no idea this operator existed until this question :-) – Michael Berry Nov 20 '21 at 00:49
  • @MichaelBerry So shall you delete it (so as not to confuse other readers :) ) and then we will remove this conversation? :) You with your 64k reputation might confuse some readers. Even Simon "Mr. Reactor" Baslé's original answer was not ideal :) – Honza Zidek Nov 22 '21 at 11:54

3 Answers3

9

Have you considered Mono#delayUntil?

Mono.just("hello")
    .delayUntil(hello -> reactiveAction(hello))
    ..
    .;
bsideup
  • 2,845
  • 17
  • 21
  • 1
    I wrote a test and apparently delayUntil satisfies my requirements. @bsideup are there any special considerations about delayUntil that I need to consider before using it? you know sometimes reactive functions are not to be just easily used. – Mahdi Amini Apr 13 '20 at 07:10
  • 2
    `delayUntil` fits your use case well and there isn't anything to consider before using it :) – bsideup Apr 13 '20 at 19:05
  • 1
    @MahdiAmini "you know sometimes reactive functions are not to be just easily used" - oh how terribly right you are! :) Anyway, thanks a lot for your question, I also overlooked the existence of the `Mono#delayUntil` method! – Honza Zidek Nov 22 '21 at 11:59
1

I can't find built-in solution, but you could create utility function:

public static <T> Function<Mono<T>, Publisher<T>> coolOperation(
        Function<T, Mono<?>> companionMonoFunction) {
    return originalMono -> originalMono
            .flatMap(t -> companionMonoFunction.apply(t)
                    .thenReturn(t));
}

And now you can use it with transform or transformDeffered:

Mono.just("hello")
    .transform(coolOperation(this::reactiveAction))
    ...;

But for me it doesn't look much prettier :)

Alexander Pankin
  • 3,787
  • 1
  • 13
  • 23
1

EDIT: see @bsideup answer, looks like delayUntil could fit the bill.

My original answer as an alternative suggestion:

I don't think there is any baked-in syntactic sugar to do this, as the "perform an async operation that depends on the original onNext" is the very definition of flatMap. We actually added the thenReturn(foo) as syntactic sugar over .then(Mono.just(foo)).

If you want to further shorten the code, offer an alternative to reactiveAction that also returns the original value:

Mono<String> reactiveActionBackground(String text){
  return reactiveAction(text).thenReturn(text);
}

which can then be invoked directly on flatMap rather than through transform:

Mono.just("hello")
    .flatMap(this::reactiveActionBackground);
Simon Baslé
  • 27,105
  • 5
  • 69
  • 70