Home > Net >  Replacing a traditional java for loop logic into reactive programming using spring webflux and webcl
Replacing a traditional java for loop logic into reactive programming using spring webflux and webcl

Time:06-22

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

  • Related