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());
});
}
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.