I Know This Question is Redundant And Asked Several times, please bear with me. Am Kinda Stuck Here Otherwise Wouldn't Have Posted This. I have This Class Below HttpClientConfig Annotated With @Configuration And I Have Defined A bean of CloseableHttpClient Inside this Class Only Annotated With @Bean.
package demo.spice.test.config;
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.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
@EnableScheduling
/**
* This Class Uses a connection pool to re-use connections and save overhead of
* creating connections. <strong>Supports both HTTP and HTTPS</strong>
* <p>
* 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.
* </p>
*/
public class HttpClientConfig {
private static final Logger logger = LoggerFactory.getLogger(HttpClientConfig.class);
// Determines the timeout in milliseconds until a connection is established.
private static final int CONNECT_TIMEOUT = 30000;
// The timeout when requesting a connection from the connection manager.
private static final int REQUEST_TIMEOUT = 30000;
// The timeout for waiting for data
private static final int SOCKET_TIMEOUT = 60000;
private static final int MAX_TOTAL_CONNECTIONS = 50;
private static final int DEFAULT_KEEP_ALIVE_TIME_MILLIS = 10 * 1000;
private static final int CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS = 30;
/**
* This connection pool ensures that already opened connections are reused.
*
* @return PoolingHttpClientConnectionManager
*/
@Bean
public PoolingHttpClientConnectionManager poolingConnectionManager() {
logger.info("Inside HttpClientConfig. 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);
}
SSLConnectionSocketFactory sslsf = null;
try {
sslsf = new SSLConnectionSocketFactory(builder.build());
} catch (KeyManagementException | NoSuchAlgorithmException 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);
// Increase default max connection per route to 4
poolingConnectionManager.setDefaultMaxPerRoute(4);
logger.info("Exiting HttpClientConfig. poolingConnectionManager() ");
return poolingConnectionManager;
}
/**
* <p>
* A connection Keep-Alive strategy determines how long a connection may remain unused in the pool
* until it is closed. This ensures that connections that are no longer needed are closed again
* promptly.
* </p>
* <p>
* If the server does not send a Keep-Alive header in the response, the connections are kept alive
* for 10 seconds by default. This implementation is a workaround to bypass the Apache Keep-Alive
* strategy. Apaches strategy assumes that connections should remain alive indefinitely if the
* server does not send a Keep-Alive
* </p>
*
* @return ConnectionKeepAliveStrategy
*/
@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();
if (value != null && param.equalsIgnoreCase("timeout")) {
return Long.parseLong(value) * 1000;
}
}
return DEFAULT_KEEP_ALIVE_TIME_MILLIS;
}
};
}
@Bean
public CloseableHttpClient httpClient() {
logger.info("Inside HttpClientConfig. httpClient() ");
RequestConfig requestConfig =
RequestConfig.custom().setConnectionRequestTimeout(REQUEST_TIMEOUT)
.setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
logger.info("Exiting HttpClientConfig. httpClient() ");
return HttpClients.custom().setDefaultRequestConfig(requestConfig)
.setConnectionManager(poolingConnectionManager())
.setKeepAliveStrategy(connectionKeepAliveStrategy()).build();
}
/**
* Thread, which periodically check all connections and free up which have not been used and idle
* time has elapsed runs every 20 seconds and closes Outdated connections as well as long waiting
* connections
*
* @param connectionManager
* @return
*/
@Bean
public Runnable idleConnectionMonitor(final PoolingHttpClientConnectionManager connectionManager) {
return new Runnable() {
@Override
@Scheduled(fixedDelay = 10000)
public void run() {
logger.info("Scheduler Running");
try {
if (connectionManager != null) {
logger.info("run IdleConnectionMonitor - Closing expired and idle connections...");
connectionManager.closeExpiredConnections();
connectionManager.closeIdleConnections(CLOSE_IDLE_CONNECTION_WAIT_TIME_SECS,
TimeUnit.SECONDS);
} else {
logger
.info("run IdleConnectionMonitor - Http Client Connection manager is not initialised");
}
} catch (Exception e) {
logger.error("run IdleConnectionMonitor - Exception occurred. msg={}, e={}",
e.getMessage(), e);
}
}
};
}
@Bean
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setThreadNamePrefix("poolScheduler");
scheduler.setPoolSize(50);
return scheduler;
}
}
I Have Another Class In Which I Am Autowiring CloseableHttpClient but I am getting Error: Error creating bean with name 'callHelper': Unsatisfied dependency expressed through field 'closeableHttpClient'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.apache.http.impl.client.CloseableHttpClient' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations
package org.spice.demo.service;
/**
imports here
**/
@Component
public class CallHelper {
@Autowired
private CloseableHttpClient closeableHttpClient;
/**
* @param httpRequest
*/
private void executeCall(HttpRequestBase httpRequest) {
logger.info(" executeCall: " + httpRequest.toString());
for (Header header : httpRequest.getAllHeaders()) {
logger.debug("Header : key = " + header.getName() + " value = " + header.getValue());
}
CloseableHttpResponse response = null;
try {
response = closeableHttpClient.execute(httpRequest);
logger.debug(response.toString());
logger.info(" Inside Try executeCall: Ended");
} catch (Exception e) {
logger.error("Error while making http call", e);
} finally {
try {
if (response != null) {
EntityUtils.consumeQuietly(response.getEntity());
response.close();
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
}