Configuring HttpClient With Spring RestTemplate
Configuring HttpClient With Spring RestTemplate
RestTemplate
https://howtodoinjava.com/spring-boot2/resttemplate/resttemplate-httpclient-java-config/
In the Spring RestTemplate example, we learned to access REST APIs inside a Spring
application. In this tutorial, we are extending the RestTemplate configuration to use Apache
HttpClient 4.
The purpose of this tutorial is to give you a pre-cooked recipe for a little head-start and save
you from writing all bits and pieces, which really takes lots of time.
1. HttpClient Configuration
The real HTTP client to use is CloseableHttpClient bean. It is what RestTemplate will
use to get the connection to API endpoints.
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContextBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
/**
* - Supports both HTTP and HTTPS
* - Uses a connection pool to re-use connections and save overhead of
creating connections.
* - Has a custom connection keep-alive strategy (to apply a default keep-
alive if one isn't specified)
* - Starts an idle connection monitor to continuously clean up stale
connections.
*/
@Configuration
@EnableScheduling
public class HttpClientConfig {
@Bean
public PoolingHttpClientConnectionManager poolingConnectionManager() {
SSLContextBuilder builder = new SSLContextBuilder();
try {
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
} catch (NoSuchAlgorithmException | KeyStoreException e) {
LOGGER.error("Pooling Connection Manager Initialisation failure
because of " + e.getMessage(), e);
}
Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder
.<ConnectionSocketFactory>create().register("https", sslsf)
.register("http", new PlainConnectionSocketFactory())
.build();
PoolingHttpClientConnectionManager poolingConnectionManager = new
PoolingHttpClientConnectionManager(socketFactoryRegistry);
poolingConnectionManager.setMaxTotal(MAX_TOTAL_CONNECTIONS);
return poolingConnectionManager;
}
@Bean
public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() {
return new ConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(HttpResponse response,
HttpContext context) {
HeaderElementIterator it = new BasicHeaderElementIterator
(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
while (it.hasNext()) {
HeaderElement he = it.nextElement();
String param = he.getName();
String value = he.getValue();
@Bean
public CloseableHttpClient httpClient() {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(REQUEST_TIMEOUT)
.setConnectTimeout(CONNECT_TIMEOUT)
.setSocketTimeout(SOCKET_TIMEOUT).build();
return HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(poolingConnectionManager())
.setKeepAliveStrategy(connectionKeepAliveStrategy())
.build();
}
@Bean
public Runnable idleConnectionMonitor(final
PoolingHttpClientConnectionManager connectionManager) {
return new Runnable() {
@Override
@Scheduled(fixedDelay = 10000)
public void run() {
try {
if (connectionManager != null) {
LOGGER.trace("run IdleConnectionMonitor - Closing
expired and idle connections...");
connectionManager.closeExpiredConnections();
connectionManager.closeIdleConnections(CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS
, TimeUnit.SECONDS);
} else {
LOGGER.trace("run IdleConnectionMonitor - Http
Client Connection manager is not initialised");
}
} catch (Exception e) {
LOGGER.error("run IdleConnectionMonitor - Exception
occurred. msg={}, e={}", e.getMessage(), e);
}
}
};
}
}
Current Time 0:00
Duration 1:45
Here we are configuring RestTemplate bean which we will finally use to invoke REST
APIs. As mentioned above, it uses CloseableHttpClient bean instance to build
ClientHttpRequestFactory, which is used to create RestTemplate.
HttpComponentsClientHttpRequestFactory is ClientHttpRequestFactory
implementation that uses Apache HttpComponents HttpClient to create requests.
We have used @Scheduled annotation in httpClient configuration. To support this, we
have to add support for the scheduled execution of the thread. For that, we have used bean
ThreadPoolTaskScheduler which internally utilizes ScheduledThreadPoolExecutor to
schedule commands to run after a given delay or to execute periodically.
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import
org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Autowired
CloseableHttpClient httpClient;
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new
RestTemplate(clientHttpRequestFactory());
return restTemplate;
}
@Bean
public HttpComponentsClientHttpRequestFactory
clientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory
clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setHttpClient(httpClient);
return clientHttpRequestFactory;
}
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new
ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("poolScheduler");
scheduler.setPoolSize(50);
return scheduler;
}
}
3. Demo
To use the above configured RestTemplate, simply inject it into the controller or any other
bean.
@RestController
public class EmployeeController {
@Autowired
RestTemplate restTemplate;
Primarily, you will be required to have two dependencies i.e. httpclient and spring-web.
We are using the spring boot application, so the pom file looks like this:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
</dependencies>
Happy Learning !!
Download Sourcecode