Search code examples
javaspringmultithreadingfutureasyncresttemplate

Make API multiple times with AsyncRestTemplate and wait for all to complete


I have to make Rest API invocation using RestTemplate multiple time with different parameters. API is same but it is the parameter that is getting changed. Number of times is also variable. I want to use AsyncRestTemplate but my main Thread should wait until all API calls have been successfully completed. I also want to work with responses that each API call returned. Currently I am using RestTemplate. In basic form it is as following.

List<String> listOfResponses = new ArrayList<String>();
for (Integer studentId : studentIdsList) {
    String respBody;
    try {
        ResponseEntity<String> responseEntity = restTemplate.exchange(url, method, requestEntity, String.class);
    } catch (Exception ex) {
        throw new ApplicationException("Exception while making Rest call.", ex);
    }
    respBody = requestEntity.getBody();
    listOfResponses.add(respBody);          
}

How can I implement AsyncRestTemplate in this situation?


Solution

  • The main idea when using AsyncRestTemplate (or any asynchronous API, in fact), is to send all you requests in a first time, keeping the corresponding futures, then process all responses in a second time. You can simply do this with 2 loops:

    List<ListenableFuture<ResponseEntity<String>>> responseFutures = new ArrayList<>();
    for (Integer studentId : studentIdsList) {
        // FIXME studentId is not used
        ListenableFuture<ResponseEntity<String>> responseEntityFuture = restTemplate.exchange(url, method, requestEntity, String.class);
        responseFutures.add(responseEntityFuture);
    }
    // now all requests were send, so we can process the responses
    List<String> listOfResponses = new ArrayList<>();
    for (ListenableFuture<ResponseEntity<String>> future: responseFutures) {
        try {
            String respBody = future.get().getBody();
            listOfResponses.add(respBody);
        } catch (Exception ex) {
            throw new ApplicationException("Exception while making Rest call.", ex);
        }
    }
    

    Note: if you need to pair the responses with the original requests, you can replace the list of futures with a map or a list of request+response objects.

    I also noted that studentId is not used in your question.