I wrote the following code to test the performance of both the sync RestTemplate and AsyncRestTemplate. I just ran it a few times manually on POSTMAN.
We are just pa
I would say that you're missing the real benefits of the AsyncRest here. You should add callbacks to each requests you're sending so that the response will be processes only when available.
Indeed, the getForEntity
method of an AsyncRestTemplate
returns a ListenableFuture
to which you can connect a callback task. See the official doc ListenableFuture for further information.
For example in your case it could be:
for (int i = 0; i < 10; i++) {
ListenableFuture<ResponseEntity<String>> response = asyncRestTemplate.getForEntity(references.get(i), String.class);
response.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
@Override
public void onSuccess(ResponseEntity<String> result) {
// Do stuff onSuccess
links.add(result.getBody().toString());
}
@Override
public void onFailure(Throwable ex) {
log.warn("Error detected while submitting a REST request. Exception was {}", ex.getMessage());
}
});
}
The tricky thing with Java Future
is that it's not composable and it's really easy to block.
In this case, calling future.get()
makes your code block and wait until the response is back. In fact, this approach makes sequential calls and does not leverage the async nature of this RestTemplate
implementation.
The simplest way to fix this is to separate it in two loops:
ArrayList<Future<ResponseEntity<String>>> futures = new ArrayList<>();
for (String url : references.get()) {
futures.add(asyncRestTemplate.getForEntity(url, String.class)); //start up to 10 requests in parallel, depending on your pool
}
for (Future<ResponseEntity<String>> future : futures) {
ResponseEntity<String> entity = future.get(); // blocking on the first request
links.add(entity.getBody().toString());
}
Obviously there are more elegant solutions, especially if using JDK8 streams, lambdas and ListenableFuture/CompletableFuture or composition libraries.
Nowadays, AsyncRestTemplate
is @Deprecated
in favor of WebClient
. So nobody should use that class anymore!
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.html