I have a project running on Vanilla Spring 4.2.5.RELEASE and JDK 1.7 and it uses RestTemplate with PoolingHttpClientConnectionManager, and I've initialized the client to use system properties
private HttpClient httpClient() {
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
poolingHttpClientConnectionManager.setMaxTotal(300);
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(200);
return HttpClientBuilder
.create()
.useSystemProperties()
.setConnectionManager(poolingHttpClientConnectionManager)
.build();
}
and set the following system properties -Dhttps.protocols=TLSv1.2
I'm clueless with this behavior, I've tried creating custom SSLConnectionSocketFactory
like this and it worked
SSLConnectionSocketFactory sslConnectionSocketFactory =
new SSLConnectionSocketFactory(SSLContexts.createDefault(),
new String[]{"TLSv1.2"},
null,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager =
new PoolingHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslConnectionSocketFactory)
.build());
but I have one more problem to fix which is trustStore for https call, this application is deployed in IBM WebSphere and since the httpClient is not using systemProperties set by WebSphere server I should add another code snippet(to point to IBM TrustStore), which I don't want to do because its too much work and ideally useSystemProperties() should solve both the problems...
SSLContext sslContext = SSLContexts
.custom()
.loadKeyMaterial(ResourceUtils.getFile(keystoreLocation), null, keystorePassword.toCharArray())
.loadTrustMaterial(ResourceUtils.getFile((truststoreLocation)), truststorePassword.toCharArray())
.build();
Please help on how to proceed...Thanks
After some debugging I found that calling useSystemProperties()
will not have any impact if we're setting the connectionManager, in .build()
function, there's an if condition to check if the connectionManager is set(refer the image below), only if its not set, it will use systemProperties(since specifying connection manager is a much low level customization on how remote calls should be made, we're supposed to set that in PoolingHttpClientConnectionManager initialization itself)
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new
PoolingHttpClientConnectionManager(RegistryBuilder
.create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSystemSocketFactory())
.build());
SSLConnectionSocketFactory.getSystemSocketFactory()
is the most important thing