Friday, February 15, 2013

RestTemplate and HttpClient 4.1 configuration

This example shows how to configure Spring RestTemplate with Apache HttpClient 4.1 as a transport.

In this example we will configure the following parameters:

  • connection timeout
  • read timeout
  • maximum connections (per host)
  • maximum connections (total)

Also, we will set up Http Basic Authentication using login and password.

We are going to use JavaConfig @Configuration class, that has all the parameters set from properties using @Value annotations.

@Configuration
public class RestClientConfig {

@Value("${rest.client.login}")
private String restClientLogin;

@Value("${rest.client.password}")
private String restClientPassword;

@Value("${rest.client.connectionTimeoutMillis}")
private int restClientConnectionTimeoutMillis;

@Value("${rest.client.readTimeoutMillis}")
private int restClientReadTimeoutMillis;

@Value("${rest.client.maxConnectionsPerHost}")
private int restClientMaxConnectionsPerHost;

@Value("${rest.client.maxTotalConnections}")
private int restClientMaxTotalConnections;

// ...

}

Lets define HttpClient @Bean by creating new PoolingClientConnectionManager and configuring maxConnectionsPerHost and maxTotalConnections.

@Bean
public HttpClient getHttpClient() {

final PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();
 
connectionManager.setDefaultMaxPerRoute(restClientMaxConnectionsPerHost); 
connectionManager.setMaxTotal(restClientMaxTotalConnections);

final DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager);
// ...
return httpClient;
}

Then we need to configure ClientHttpRequestFactory that allows to define read and connection timeouts.

@Bean
public ClientHttpRequestFactory getClientHttpRequestFactory() {

HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(getHttpClient());

factory.setConnectTimeout(restClientConnectionTimeoutMillis);
factory.setReadTimeout(restClientReadTimeoutMillis);

return factory;
}

Now we can create RestTemplate @Bean

@Bean
public RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
return restTemplate;
}

Now we need to configure Http Basic Authentication. To do Basic Authentication we need to add Authentication: Basic header to HTTP request. We can do it by registering a HttpRequestInterceptor that would add the header to every request.

public class HttpBasicAuthInterceptor implements HttpRequestInterceptor {

private UsernamePasswordCredentials creds;

public HttpBasicAuthInterceptor(UsernamePasswordCredentials creds) {
this.creds = creds;
}


@Override
public void process(HttpRequest request, HttpContext context) 
throws HttpException, IOException {
request.addHeader(new BasicScheme().authenticate(creds, request, context));
}

}

Register HttpRequestInterceptor in HttpClient:

HttpRequestInterceptor interceptor = new HttpBasicAuthInterceptor(new UsernamePasswordCredentials(restClientLogin, restClientPassword));

httpClient.addRequestInterceptor(interceptor);


Full source code:

@Configuration
public class RestClientConfig {


 @Value("${rest.client.login}")
 private String restClientLogin;

 @Value("${rest.client.password}")
 private String restClientPassword;


 @Value("${rest.client.connectionTimeoutMillis}")
 private int restClientConnectionTimeoutMillis;

 @Value("${rest.client.readTimeoutMillis}")
 private int restClientReadTimeoutMillis;

 @Value("${rest.client.maxConnectionsPerHost}")
 private int restClientMaxConnectionsPerHost;

 @Value("${rest.client.maxTotalConnections}")
 private int restClientMaxTotalConnections;

  
 @Bean
 public HttpClient getHttpClient() {

 final PoolingClientConnectionManager connectionManager = new PoolingClientConnectionManager();

 connectionManager.setDefaultMaxPerRoute(restClientMaxConnectionsPerHost);
 connectionManager.setMaxTotal(restClientMaxTotalConnections);

    
 final DefaultHttpClient httpClient = new DefaultHttpClient(connectionManager);

    HttpRequestInterceptor interceptor = new HttpBasicAuthInterceptor(new UsernamePasswordCredentials(restClientLogin, restClientPassword));

    httpClient.addRequestInterceptor(interceptor);

 return httpClient;

 }


 @Bean
 public ClientHttpRequestFactory getClientHttpRequestFactory() {

 HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(getHttpClient());

 factory.setConnectTimeout(restClientConnectionTimeoutMillis);
 factory.setReadTimeout(restClientReadTimeoutMillis);

 return factory;

 } 


 @Bean
 public RestTemplate getRestTemplate() {
 RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
 return restTemplate;
 }

}  


public class HttpBasicAuthInterceptor implements HttpRequestInterceptor {

 private UsernamePasswordCredentials creds;

 public HttpBasicAuthInterceptor(UsernamePasswordCredentials creds) {
 this.creds = creds;
 }

 @Override
 public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {

 request.addHeader(new BasicScheme().authenticate(creds, request, context));
 }

}





1 comment: