-1

We are trying to convert an MVC, resttemplate, blocking, application into a WebFlux app.

Very straightforward in the “blocking world”, get a list inside a request payload, iterate through it and send N http requests to a third party rest API.

Very important it is a third party rest API, no control over it at all, and cannot ask them to implement a version taking the list, it has to be one by one.

Trivial with resttemplate, what would be the WebFlux equivalent please? This is a bit challenging, since it takes a Mono and returns a Mono. A small snippet will be great.

Thank you

@SpringBootApplication
@RestController
public class QuestionApplication {

    public static void main(String[] args) {
        SpringApplication.run(QuestionApplication.class, args);
    }

    @PostMapping("question")
    MyResponse question(@RequestBody MyRequest myRequest) {
        List<String>  myStrings = myRequest.getListOfString();
        List<Integer> myIds     = iterateAndSendRequestOneByOneGetIdFromString(myStrings);
        return new MyResponse(myIds);
    }

    private List<Integer> iterateAndSendRequestOneByOneGetIdFromString(List<String> myStrings) {
        List<Integer> ids = new ArrayList<>();
        for (String string : myStrings) {
            Integer id = new RestTemplate().postForObject("http://external-service:8080/getOneIdFromOneString", string, Integer.class);
            ids.add(id);
        }
        return ids;
    }

//    @PostMapping("how-to-do-the-same-with-WebFlux-WebClient-please?")
//    Mono<MyResponse> question(@RequestBody Mono<MyRequest> myRequestMono) {
//        return null;
//    }

}

class MyResponse {
    private List<Integer> myIds;
}

class MyRequest {
    private List<String> strings;
}
PatPanda
  • 3,644
  • 9
  • 58
  • 154

1 Answers1

1

The way to go is to use flatMap from Flux.

public Mono<MyResponse> getIdsFromStrings(MyRequest myRequest) {

  WebClient client =
      WebClient.builder().baseUrl("http://external-service:8080").build();

  return Flux.fromIterable(myRequest.getStrings())
      .flatMap(s -> client.post().uri("/getOneIdFromOneString").body(s, String.class).retrieve().bodyToMono(Integer.class))
      .collectList()
      .map(MyResponse::new);
}

.flatMap is an asynchronous operation and will execute your requests concurrently. You can also choose to set concurrency limits by using an overloaded method of flatMap (refer to documentation).

Akhil Bojedla
  • 1,968
  • 12
  • 19