Sheyko Dmitriy
Sheyko Dmitriy

Reputation: 413

How to use Reactor (Spring WebClient) to do analogue of for loop

I'm quite new to Reactor (Spring5 WebClient) and though I have figured how to do simple request and process it's output with map or flatmap I need to do a bit harder task now:

I have an endpoint which I can not change.

basic signature of this endpoint call is Get {host}/{endpointName}?System={integer from 1 to 3}&Form={integer from 1 to 5}

I need to call it repeatedly and to process output for this pairs:

{1, 1},
{1, 2},
{1, 3},
{1, 4},
...
{3, 2},
{3, 4},
{3, 5}

For one request it would be for example:

WebClient.create().get()
  .uri(uri -> uri.scheme("http")
    .host(myHost)
    .path(myPath)
    .queryParam("System", 1)
    .queryParam("Form", 1)
    .build())
  .exchange()
  .flatMap(response -> {
   //process response and produce desired output
   });

What I try to do is to: 1. Make multiple requests (basically iterating over map tha contains all pairs mentioned above) 2. Process each request result (processed result is added to json array that was created before WebClient) 3. When all requests are made - give "combined output".

Example: if request with combination 1,1 gives

[
{
"Name":"John",
"Surname":"Doe"
}
]

And pair 3, 5 gives

[
{
"Name":"Jane",
"Surname":"Dean"
}
]

Result of this WebClient call should be

[
{
"Name": "John",
"Surname: "Doe"
},
....
{
"Name": "Jane",
"Surname": "Dean"
}
]

I know about retry and repeat mechanics of Mono, I just can't figure how to do "multiple calls with different request parameters" part.

Is this even possible?

Upvotes: 2

Views: 2249

Answers (1)

Markus Appel
Markus Appel

Reputation: 3238

Use Flux.range in combination with flatMap:


Flux.range(1, 5)
    .flatMap(i -> Flux.range(1, 5).map(j -> Tuples.of(i, j)))
    .flatMap(t ->
        WebClient.create().get()
            .uri(uri -> uri.scheme("http")
                .host(myHost)
                .path(myPath)
                .queryParam("System", t.getT1())
                .queryParam("Form", t.getT2())
                .build())
            .exchange()
    )
    .flatMap(response -> /* Handle the response... */)

If the tuples that I have calculated in the example above are instead stored in a Map<Integer, Integer>, you have to change the code slightly:


Flux.fromIterable(intIntMap.entrySet())
    .flatMap(entry ->
        WebClient.create().get()
            .uri(uri -> uri.scheme("http")
                .host(myHost)
                .path(myPath)
                .queryParam("System", entry.getKey())
                .queryParam("Form", entry.getValue())
                .build())
            .exchange()
    )
    .flatMap(response -> /* Handle the response... */)

With these approaches, you will never leave the functional world, resulting in a cleaner and more concise piece of code.

Upvotes: 2

Related Questions