Search code examples
javaspringwebsphereapache-httpclient-4.xresttemplate

useSystemProperties() is not working with Apache HttpClientBuilder.create() version 4.5.6


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


Solution

  • 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

    enter image description here