I have started a new project using Spring Webflux and I am fairly new to this reactive coding paradigm. So apologies in advance for questioning like newbies.

My controller method returns the response as Mono<ResponseEntity<String>> and I have three different services to call from where I am getting three different Mono object like this -

Mono<CustomObject> customMono = serivce1.method();Mono<Boolean> booleanMono = service2.method();Mono<String> stringMono = service3.method();

So in order prepare the response(Mono<ResponseEntity<String>>), I need to do something like this -

Mono.zip(customMono, booleanMono, stringMono, (customData, booleanData, stringData) -> {------return Mono.just(ResponseEntity.ok().body("-----"));});

The problem is, there are no such zip method to take 3 Mono and a function as parameters. I already found thise -https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Mono.html#zip-reactor.core.publisher.Mono-reactor.core.publisher.Mono-java.util.function.BiFunction-

but it doesn't fulfil my requirement. So issues I am facing

  • I can not use Mono.mergeWith or Mono.concaWith method because my Mono object are of different kind.
  • I can flatMap/map every Mono and create a chain. But I want service2 to be called parallel in a separate thread as it is not dependent on service1 call. But service3 call is dependent on service1 response.

In summary, what I need to do:

  • make service1 call at first
  • make service2 call separately on different thread
  • make service3 call which is dependent on service1 call data
  • generating the final response object (Mono<ResponseEntity<String>>) using the data from all the service call.

Thanks in advance. As a newbie, any suggestion is appreciated.

3

Best Answer


Whenever you zip the two mono then the third parameter will be BiFunction but with three-parameter, it returns a flatmap of tuple then in the tuple you will get the response of other Monos.You need to modify your code in the below manner.

Mono.zip(customMono, booleanMono, stringMono).flatMap(data->{data.getT1();data.getT2();data.getT3();return <your_response_object>;});

Now what will be the return type of getT1(),getT2() and getT3() ?

Obusally it will depend on what your Zip Mono return.

Hope so it will help you.

For your specific condition, you need Mono.zipWhen() which will ensure that your 3rd service call will have the data it requires from the response from service call 1

Mono.zip(monoResponse1,monoResponse2).zipWhen(data ->serviceCall3(data.getT1())).flatMap(response ->{response.getT1().getT1();//response from mono1response.getT1().getT2();//response from mono 2response.getT2();//response from mono 3return {create your mono response here};} );

I am also in my Reactive programming learning phase. So I started with doing zipWith on 2 method and started thinking what if I want to zip more than 2 methods!

I found out that I can chain the method with another zipWith.

greet().zipWith(name()).map(tuple -> tuple.getT1() + tuple.getT2()).zipWith(name2()).map(tuple -> tuple.getT1() + tuple.getT2());

Explanation: greet() returns a String Mono and I zipped it with name(). Then I again zipped the Mono returned from the 1st map() to the third method name2() and again did a map to get the desired response.

This is just another way to zip multiple methods. But, this may not solve all problems.