I'm converting Spring Boot (MVC) application to Reactive Programming (Spring Webflux)
For making external rest calls, I'm using WebClient.
List<String> targetUrls = Arrays.asList("one","two","three");
int iteration = 1;
for(String target:targetUrls){
// make a rest call here
// if 200 break the loop
// else loop continues
}
The rest call here returns a Mono.
Is there a way to iterate over the list of urls(here in this case) and break the loop based on some response
Tried flatMap on the Mono and based on response can make a rest call to another url --> This works in case we know before hand the number of urls
CodePudding user response:
I'm not sure how you call the urls from the WebClient, but just assuming the URLs are passed to a method WebClient.get(String url)
, I will continue with the example.
The steps would be somewhat like you will first get a Flux of the URLs, then use flatMap
(because your response is a Mono), then use map
on these.
Flux.fromIterable(targetUrls)
.flatMap(webClient::get)
.map(response -> doSomethingWith(response))
Now you should have a Flux of responses. If the error handling from the WebClient isn't enough, you can also insert something inbetween.
Flux.fromIterable(targetUrls)
.flatMap(webClient::get)
.doOnError(errorHandler::handle)
.map(response -> doSomethingWith(response))
CodePudding user response:
There are several patterns you could apply to implement this logic
You can use flatMap
to execute multiple queries concurrently. By default, flatMap
will process Queues.SMALL_BUFFER_SIZE = 256
number of in-flight inner sequences.
Flux.fromIterable(targetUrls)
.flatMap(url -> webClient.get(url))
.map(response -> process(response))
You could control concurrency flatMap(url -> webClient.get(url), concurrency)
or use concatMap
operator if you want to execute queries sequentially.
Another useful pattern in case you need response to make decision about next request - use expand
operator. For example, in case of paginated requests.
webclient.get(url)
.expand(response -> {
if (<should stop>) {
// stop the loop
return Mono.empty();
}
return webclient.get(url);
});