0

Using spring WebFlux, I would like to send HTTP requests one-by-one until a response fulfils a certain criteria. I also need to collect all responses. In the blocking world, the solution would be something like this:

List<String> responses = new ArrayList<>();
String lastResponse;
do {
  lastResponse = webClient.get()
    .uri(uri)
    .retrieve()
    .bodyToMono(String.class)
    .block();
  responses.add(lastResponse);
} while(!finished(lastResponse));

How to implement this without blocking?

note: there is a naive solution with recursion, but I'm looking for a more elegant way:

private List<String> collectRemaining() {
  return webClient.get()
    .uri(uri)
    .retrieve()
    .bodyToMono(String.class)
    .flatMap(response -> {
      if(finished(response)) {
        return List.of(response);
      }
      return collectRemaining().flatMap(remaining ->
          Stream.concat(Stream.of(response), remaining.stream()).collect(Collectors.toList());
    });
}
Martin Tarjányi
  • 8,863
  • 2
  • 31
  • 49
nagy.zsolt.hun
  • 6,292
  • 12
  • 56
  • 95

1 Answers1

1

To replace recursion you can use expand() operator which makes it possible to generate the next element based on a previous one. It's commonly used to implement pagination logic. So something like the following could work:

webClient.get()
        .uri(uri)
        .retrieve()
        .bodyToMono(String.class)
        .expand(response -> {
            if (finished(response)) {
                return Mono.empty();
            }
            return webClient.get()
                    .uri(uri)
                    .retrieve()
                    .bodyToMono(String.class);
        }).collectList();

Inspired by this article.

Martin Tarjányi
  • 8,863
  • 2
  • 31
  • 49