I've setup a RestTemplate and an AsyncRestTemplate in my project similar to the following:
http://vincentdevillers.blogspot.fr/2013/10/a-best-spring-asyncresttemplate.html
I've noticed that the connect timeout doesn't actually work unless I change the httpRequestFactory() bean to be the following:
@Bean
public ClientHttpRequestFactory httpRequestFactory() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient());
factory.setConnectTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
factory.setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
return factory;
}
If I set DEFAULT_READ_TIMEOUT_MILLISECONDS to 5, a timeout occurs when I use restTemplate (as expected). However, when I use AsyncRestTemplate, a timeout doesn't occur. I've modified the asyncHttpRequestFactory() like httpRequestFactory(), but no dice.
@Bean
public AsyncClientHttpRequestFactory asyncHttpRequestFactory() {
HttpComponentsAsyncClientHttpRequestFactory factory = new HttpComponentsAsyncClientHttpRequestFactory(asyncHttpClient());
factory.setConnectTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
factory.setReadTimeout(DEFAULT_READ_TIMEOUT_MILLISECONDS);
return factory;
}
Here's how I'm attempting to use AsyncRestTemplate in a Spring MVC Controller:
String url = "...";
// Start the clock
long start = System.currentTimeMillis();
ListenableFuture<ResponseEntity<String>> results = asyncRestTemplate.getForEntity(url, String.class);
// Wait until the request is finished
while (!(results.isDone())) {
Thread.sleep(10); //millisecond pause between each check
}
System.out.println("Elapsed time: " + (System.currentTimeMillis() - start));
return results.get().getBody();
How can I get AsyncRestTemplate to read my connection timeout settings?
On a related note, https://spring.io/guides/gs/async-method/ uses @Async and RestTemplate and seems to accomplish what I'm looking for. What's the advantage of using AsyncRestTemplate over RestTemplate?
Very similar to the sync one:
final SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
requestFactory.setTaskExecutor(new SimpleAsyncTaskExecutor());
requestFactory.setConnectTimeout(connectTimeout);
requestFactory.setReadTimeout(readTimeout);
final AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();
asyncRestTemplate.setAsyncRequestFactory(requestFactory);
From the source code, you can see that AsyncRestTemplate
instance is created by using a SimpleClientHttpRequestFactory
together with a SimpleAsyncTaskExecutor
. So you can just do the same using a SimpleClientHttpRequestFactory
instance whose timeout values are set.
The AsyncRestTemplate relies on HTTP client's NIO capabilities so you can manage a large number of connections with a small number of threads. To achieve the same with @Async + RestTemplate would require much more resources. If you're only doing it in a few places then it's probably okay although even then AsyncRestTemplate, since it exists, is a little nicer and more specialized for the use case.
As for the read timeout it looks like it might be an oversight. Feel free to create a ticket. A quick look at this page, the "HttpAsyncClient configuration" example, shows using:
IOReactorConfig.custom().setConnectTimeout(30000)
.
I suppose you could give that a quick try
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With