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: https://layer4.fr/2013/10/a-best-spring-asyncresttemplate/

Related Posts

Comments (14)

Nice article!, may be worth to note..if you have an application that is heavily calling REST calls to the same server..to keep only once instance of the
HttpClient(with the MultiThreadedConnectionManager).

Indeed! You have to favorite an unique instanciation. Instantiating a HttpClient is costly in resources, we must focus on reuse, even singletons, as described in the doc:
« Generally it is recommended to have a single instance of HttpClient per communication component or even per application. However, if the application makes use of HttpClient only very infrequently, and keeping an idle instance of HttpClient in memory is not warranted, it is highly recommended to explicitly shut down the multithreaded connection manager prior to disposing the HttpClient instance. This will ensure proper closure of all HTTP connections in the connection pool. »

https://layer4.fr/2011/09/httpclient-best-pratices.html

Hi,

One question :

How about using Resttemplates for inter application calls?
I have two application A & B – A making calls on B..
Can i use RestTemplate in A to access Restful webservices on B?

Thank you, any idea how to get this working with SSL?

Instead of:
PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();

Use:
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));

PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager(schemeRegistry);

Enjoy 😉

Hi Vincent,
Thanks for the great article. With the latest Spring provided HttpComponentsClientHttpRequestFactory, it provides the best by default.
I have followed your blog and tried making one change and that setting max per route for one destination URL. It didn't work.
Here is what i did
The default Max Per Route is 5. However for one route, i wanted a bigger number. so i added the following code
connectionManager.setMaxPerRoute(new HttpRoute(new HttpHost("ebm.cheetahmail.com", 443, "https")), 16);

The logs show that Max per route of 5 is being used and not the new setting. Here is the log details for above route

[cookieAuthServiceScheduler-1] 02-19-2014 19:06:31 DEBUG PoolingClientConnectionManager: Connection request: [route: {s}->https://ebm.cheetahmail.com:443%5D%5Btotal kept alive: 0; route allocated: 0 of 5; total allocated: 0 of 100]
[cookieAuthServiceScheduler-1] 02-19-2014 19:06:31 DEBUG PoolingClientConnectionManager: Connection leased: [id: 0][route: {s}->https://ebm.cheetahmail.com:443%5D%5Btotal kept alive: 0; route allocated: 1 of 5; total allocated: 1 of 100]
[cookieAuthServiceScheduler-1] 02-19-2014 19:06:33 DEBUG PoolingClientConnectionManager: Connection [id: 0][route: {s}->https://ebm.cheetahmail.com:443%5D can be kept alive for 5000 MILLISECONDS
[cookieAuthServiceScheduler-1] 02-19-2014 19:06:33 DEBUG PoolingClientConnectionManager: Connection released: [id: 0][route: {s}->https://ebm.cheetahmail.com:443%5D%5Btotal kept alive: 1; route allocated: 1 of 5; total allocated: 1 of 100]

Do you know why?
I am using following versions
Spring 3.2.5.RELEASE
org.apache.httpcomponents httpclient 4.2
Thanks
Sri

Hi,

I am using RestTemplate to get data from server.. server is https, and I have imported required certificates in truststore. I want to make use of these truststore and make REST call using RestTemplate, can you tell me hoow can i achieve this ?

Regards.

Can you use PoolingClientConnectionManager if your application is using Controllers and deployed to an application server (Tomcat). It's not clear from the documentation:

"This connection manager implementation should be used inside an EJB container."

Hi, could you let me know how to do oauth with spring rest template -RestTemplate. Basically a alternative to OAuthConsumer consumer = new CommonsHttpOAuthConsumer(consumerKey,.consumerSecret).

Hi, could you let me know how to do oauth with spring rest template -RestTemplate. Basically a alternative to OAuthConsumer consumer = new CommonsHttpOAuthConsumer(consumerKey,.consumerSecret).

Thanks for the article! I'm trying to follow and trying to setup a connection factory. However, I get ClassNotFoundException for PoolingHttpClientConnectionManager. I'm afraid it has something to do with Websphere. I'm using Websphere 8.5 with Spring 4.0.3 and httpClient 4.5.2 version.

[…] wrote an article on the famous Spring’s RestTemplate some months ago (https://layer4.fr/2013/02/24/a-best-spring-resttemplate/). Since the last version of Spring 4, currently 4.0.0.M3, or the BUILD-SNAPSHOT for the most […]

I think these classes are deprecated now, Do you have any alternative with new classes?

Leave a comment