A best Spring RestTemplate!

The RestTemplate is the central class for client-side HTTP access. It simplifies communication with HTTP servers, and enforces RESTful principles. It handles HTTP connections, leaving application code to provide URLs (with possible template variables) and extract results.

The template uses a ClientHttpRequestFactory for creating HTTP connections. The default ClientHttpRequestFactory is a SimpleClientHttpRequestFactory that uses standard J2SE classes like java.net.HttpURLConnection. And this is not really production ready... (why?) 

So, the solution is to use the org.springframework.http.client.HttpComponentsClientHttpRequestFactory, which is a ClientHttpRequestFactory delegating the creation of the requests to an HttpClient.

The result is:


import java.util.List;

import javax.inject.Inject;

import org.apache.http.HttpHost;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.CoreConnectionPNames;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
public class HttpConfig {

private static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 100;

private static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 5;

private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000);

@Inject
private ObjectMapper objectMapper;

@Bean
public ClientHttpRequestFactory httpRequestFactory() {
return new HttpComponentsClientHttpRequestFactory(httpClient());
}

@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate(httpRequestFactory());
List<HttpMessageConverter<?>> converters = restTemplate
.getMessageConverters();

for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter jsonConverter = (MappingJackson2HttpMessageConverter) converter;
jsonConverter.setObjectMapper(objectMapper);
}
}

return restTemplate;
}

@Bean
public HttpClient httpClient() {

PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();
HttpClient defaultHttpClient = new DefaultHttpClient(connectionManager);

connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL_CONNECTIONS);
connectionManager
.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTIONS_PER_ROUTE);
connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost(
"facebook.com")), 20);
connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost(
"twitter.com")), 20);
connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost(
"linkedin.com")), 20);
connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost(
"viadeo.com")), 20);

defaultHttpClient.getParams().setIntParameter(
CoreConnectionPNames.CONNECTION_TIMEOUT,
DEFAULT_READ_TIMEOUT_MILLISECONDS);
return defaultHttpClient;
}
}

Update (21/10/2013): 
Have a look here for the async version of RestTemplate: http://vincentdevillers.blogspot.fr/2013/10/a-best-spring-asyncresttemplate.html

Labels: ,