Search code examples
javaspring-bootreactive-programmingspring-webfluxwebflux

Multiple asynchronous calls using result of first call using spring webflux


I need to make an asynchronous call and use some values present in it to make multiple calls to same service. Combine the response on these calls with the first one and return.

For example When I make the first call I get below JSON, which has a list of ids. Now I have to make multiple calls to a service with these ids and make a list of their response and send it to downstream by appending it in same JSON.

 {“id”: 145,
    “object”:[{“id”:111}]
    }

I have tried using zipWhen and

Flux.fromIterable(userIds).parallel().runOn(Schedulers.elastic()).flatMap()

But resulting list always comes as empty or null. How can we achieve this? Am I missing something here?

Edit1: Resolved it by using Flux.fromIterable. Read more about it and finally understood the use and resolved it. The below method takes up one item from list and will call the inner method which will call multiple APIs:

return Flux.fromIterable(somelist).flatMap(listItem -> {
    return someMethodToCallAnotherAPIUsingZipWith(listItem);
    }).collectList();

Inner Method: It calls 1st API, passed its result to zipWith and using this result we can call another API or we can simply use it with its response.

private Mono<Object> someMethodToCallAnotherAPIUsingZipWith(String listItem) {
        return authService.getAccessToken().flatMap(accessToken ->
                webClient.get().uri(builder -> builder.path("/path").build(listItem))
                        .header(HttpHeaders.AUTHORIZATION, accessToken)
                        .retrieve()
                        .toEntity(Entity.class).log()
                        .flatMap(entity -> {
                            //manipulate your response or create new object using it
                            return Mono.just(entity);
                        }).zipWhen(consent -> webClient.get().uri(builder -> builder.path("/otherpath").build(listItem))
                        .header(HttpHeaders.AUTHORIZATION, accessToken)
                        .retrieve().bodyToMono(Entity.class).log()
                        .flatMap(entity -> {
                            //example
                            listItem = entity.getString();
                            return Mono.just(listItem);
                        }), (string1, string2) -> string1 + string2));
    }

Solution

  • private Mono<Object> someMethodToCallAnotherAPIUsingZipWith(String listItem) {
        return authService.getAccessToken().flatMap(accessToken ->
                webClient.get().uri(builder -> builder.path("/path").build(listItem))
                        .header(HttpHeaders.AUTHORIZATION, accessToken)
                        .retrieve()
                        .toEntity(Entity.class).log()
                        .flatMap(entity -> {
                            //manipulate your response or create new object using it
                            return Mono.just(entity);
                        }).zipWhen(consent -> webClient.get().uri(builder -> builder.path("/otherpath").build(listItem))
                        .header(HttpHeaders.AUTHORIZATION, accessToken)
                        .retrieve().bodyToMono(Entity.class).log()
                        .flatMap(entity -> {
                            //example
                            listItem = entity.getString();
                            return Mono.just(listItem);
                        }), (string1, string2) -> string1 + string2));
    }