0
votes

I have the below HandlerFunction that takes a POST request of a "BookingRecord". I get a Mono from ServerRequest using bodyToMono(), and then subscribe to the Mono, as I need the BookingRecord type back, to call a REST service to get back a Mono"", using WebClient. I have declared fare as an instance variable so that I can use it in return statement.

public class BookingHandler
{
   private Mono<Fare>           fare;
   private WebClient            webClient= = WebClient.create("http://localhost:8080");

   public HandlerFunction<ServerResponse> book = request -> {

    request.bodyToMono(BookingRecord.class)
            .subscribe(br ->
            {
                fare = this.webClient.get()
                        .uri("/fares/get/{flightNumber}/{flightDate}", br.getFlightNumber(), br
                                .getFlightDate())
                        .retrieve()
                        .bodyToMono(Fare.class);
            });
    return ServerResponse.ok()
            .body(BodyInserters.fromPublisher(fare, Fare.class));
};
}

But this code doesn't work. The subscribe doesn't seem to execute!! Why is that?

I had to change it to below code for it to work!.

 request.bodyToMono(BookingRecord.class)
                        .subscribe(br ->
                    {
                    flightNumber = br.getFlightNumber();
                    flightDate = br.getFlightDate();
                });

        fare = this.webClient.get()
                .uri("/fares/get/{flightNumber}/{flightDate}", flightNumber, flightDate)
                .retrieve()
                .bodyToMono(Fare.class);

So why my first code is not calling subscribe? I am using SpringBoot 2.1.0.M4.

1

1 Answers

1
votes

Behind the scenes, you are already subscribing by waiting on the result, so no real need to subscribe again. You need to view each step as a building block, so first you get the booking record (1), when this is completed, then build a url with the record (2), then request URL (3), when this is completed return the response body (4). You need to build each of these into one flow (5). Your second example worked because you either got lucky that the subscribe finished before you built the url, or because it was populated in another execution.

public HandlerFunction<ServerResponse> book = request -> request.bodyToMono(BookingRecord.class) //(1)
                .map(br -> this.webClient.get()
                        .uri("/fares/get/{flightNumber}/{flightDate}", br.getFlightNumber(), br
                                .getFlightDate()) //(2)
                        .retrieve() (3)
                        .bodyToMono(Fare.class) (4)
                ).flatMap(fare -> ServerResponse.ok().body(BodyInserters.fromPublisher(fare, Fare.class))) (5)

;