25

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.

bivrantoshakil
  • 421
  • 1
  • 5
  • 10

3 Answers3

33

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.

Pratik Bhajankar
  • 1,144
  • 2
  • 14
  • 27
17

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 mono1
    response.getT1().getT2();//response from mono 2
    response.getT2();//response from mono 3
    return {create your mono response here};
} );
yash sugandh
  • 608
  • 4
  • 6
  • Thank you. can you please suggest a way how can I make the service2 call parallel/asynchronous? When I call the Mono.zip method, I want service2 response ready to be used right then. – bivrantoshakil Oct 19 '19 at 08:03
  • you can use service2 response right there by using data.getT2() – yash sugandh Oct 19 '19 at 19:32
0

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.

Ashish Singh
  • 399
  • 4
  • 11