Arun Guilal
Arun Guilal

Reputation: 33

convert for loop in java reactive programming - helidon

I am new to reactive programming and using helidon reactive java libraries in our code. I am unable to achieve the below use case.

I have a scenario as below.

First I invoke a REST API and get response.From the response that contains list of countries I have to invoke another REST api that retrieves the response for a country id and update the country object.

By the time I invoke second API and set value to country object as below the response is already returned. I get use .get() and wait() on Single as it blocks the thread.

Please suggest how to overcome the below for loop and update the list of objects reactive way.

Single<WebClientResponse> singleWebClientResp = webClient.get("REST_URL");

Single<String> apiResponse = singleWebClientResponse.flatMapSingle(webClientResponse -> {
        return webClientResponse.content().as(String.class);
});

apiResponse.flatMapSingle(fusionAPIResponseString -> {

    List<Country> countries = 
        objectMapper.readValue(fusionAPIResponseString,new TypeReference<List<Country>>() {});
        
    for (Country country : countries) {
        getCountryByRegion(country.getRegion()).forSingle(newCountry -> {

            LOGGER.log(Level.FINE, "newCountry ---> " + newCountry);

            country.setRegion(country.getRegion() + "modified" + newCountry);

        });
    }
        
});
        
private Single<String> getCountryByRegion(String regionName) {
    LOGGER.log(Level.FINE, "Entering getCountryByRegion");

    Single<WebClientResponse> singleWebClientResponse2 = webClient.get().path("v3.1/region/" + regionName)
            .contentType(MediaType.APPLICATION_JSON).request();

    Single<String> retVal = singleWebClientResponse2.flatMapSingle(webClientResponse -> {
        return webClientResponse.content().as(String.class);
    });

    LOGGER.log(Level.FINE, "Exiting getCountryByRegion");
    return retVal;

}

Regards

Upvotes: 1

Views: 328

Answers (1)

Romain Grecourt
Romain Grecourt

Reputation: 525

// NOTE: this should be a static constant
GenericType<List<Country>> countriesType = new GenericType<>() {};


// NOTE: create the webClient only once, not for every request
WebClient webClient = WebClient.builder()
                               .addMediaSupport(JacksonSupport.create())
                               .baseUri("service-url")
                               .build();

// the pipeline starts with the initial countries (i.e. Single<List<Country>>)
webClient.get()
        .path("/countries")
        // get the countries as List<Country>
        .request(countriesType)

        // add each country to the reactive pipeline (i.e. Multi<Country>)
        // to allow individual reactive mapping
        .flatMap(Multi::just)

        // map each country by creating a new country with new region
        // use flatMap to inline the webClient result in the reactive pipeline
        .flatMap(country ->
                webClient.get()
                         .path("/region/" + country.getRegion())
                         .request(String.class)
                         .map(newCountry -> new Country(newCountry, country.getRegion())))

        // aggregate all items (i.e. Single<List<Country>>)
        .collectList()
        .onError(res::send)
        .forSingle(res::send))

Upvotes: 3

Related Questions