javaapache-httpclient-4.xapache-httpclient-5.x

Cannot resolve method 'setDefaultSocketFactory' in 'PoolingHttpClientConnectionManager'


I have to migrate this httpclient 4 code to httpclient 5:

import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;


  @Bean(name = "sslRestTemplateBean")
  public RestTemplate sslRestTemplate() throws Exception {
    char[] unlockPhrase = "test".toCharArray();
    SSLContext sslContext = SSLContextBuilder.create()
        .loadKeyMaterial(pkcsKeyStore("/key.p12", unlockPhrase), unlockPhrase)
        .build();
    HttpClient client = HttpClients.custom()
        .setSSLContext(sslContext)
        .build();
    return new RestTemplate(new HttpComponentsClientHttpRequestFactory(client));
  }

  private KeyStore pkcsKeyStore(String file, char... password) throws Exception {
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(file)) {
      keyStore.load(in, password);
    }
    return keyStore;
  }

  static RestTemplate createSslRestTemplate(SslCertificate sslCertificate) throws Exception {
    char[] password = generateRandomString().toCharArray();
    SSLContext sslContext = SSLContextBuilder.create()
        .loadKeyMaterial(keyStore(sslCertificate, password), password)
        .build();
    HttpClient client = HttpClients.custom()
        .disableAutomaticRetries()
        .setSSLContext(sslContext)
        .build();
    return new RestTemplate(new HttpComponentsClientHttpRequestFactory(client));
  }

I migrated in to this:

import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
import org.apache.hc.core5.ssl.SSLContextBuilder;


@Bean(name = "sslRestTemplateBean")
  public RestTemplate sslRestTemplate() throws Exception {
    char[] unlockPhrase = "test".toCharArray();
    SSLContext sslContext = SSLContextBuilder.create()
        .loadKeyMaterial(pkcsKeyStore("/key.p12", unlockPhrase), unlockPhrase)
        .build();

      // Create SSL socket factory
      SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);

      // Create connection manager with SSL socket factory
      PoolingHttpClientConnectionManager connectionManager =
              new PoolingHttpClientConnectionManager();
      connectionManager.setDefaultSocketFactory(sslSocketFactory);

      // Build HTTP client
      CloseableHttpClient client = HttpClients.custom()
              .setConnectionManager(connectionManager)
              .build();

      return new RestTemplate(new HttpComponentsClientHttpRequestFactory(client));
  }

  private KeyStore pkcsKeyStore(String file, char... password) throws Exception {
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    try (InputStream in = this.getClass().getClassLoader().getResourceAsStream(file)) {
      keyStore.load(in, password);
    }
    return keyStore;
  }

  static RestTemplate createSslRestTemplate(SslCertificate sslCertificate) throws Exception {
    char[] password = generateRandomString().toCharArray();
    SSLContext sslContext = SSLContextBuilder.create()
        .loadKeyMaterial(keyStore(sslCertificate, password), password)
        .build();

      // Create SSL socket factory
      SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext);

      // Create connection manager with SSL socket factory
      PoolingHttpClientConnectionManager connectionManager =
              new PoolingHttpClientConnectionManager();
      connectionManager.setDefaultSocketFactory(sslSocketFactory);

      // Build HTTP client
      CloseableHttpClient client = HttpClients.custom()
              .disableAutomaticRetries()
              .setConnectionManager(connectionManager)
              .build();

    return new RestTemplate(new HttpComponentsClientHttpRequestFactory(client));
  }

But I get error: Cannot resolve method 'setDefaultSocketFactory' in 'PoolingHttpClientConnectionManager'

Do you know how I can fix this issue and migrate the code properly?


Solution

  • In the latest version, SSLConnectionSocketFactory has been deprecated in favour of DefaultClientTlsStrategy. After creating the SSLContext, use this instead to create the connection manager:

    @Bean(name = "sslRestTemplateBean")
    public RestTemplate sslRestTemplate() throws Exception {
        char[] unlockPhrase = "test".toCharArray();
        SSLContext sslContext = SSLContextBuilder.create()
                .loadKeyMaterial(pkcsKeyStore("/key.p12", unlockPhrase), unlockPhrase)
                .build();
    
        // Create connection manager with SSL context
        PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
                .setTlsSocketStrategy(new DefaultClientTlsStrategy(sslContext))
                .build();
    
        // Build HTTP client
        CloseableHttpClient client = HttpClients.custom()
                .setConnectionManager(connectionManager)
                .build();
    
        return new RestTemplate(new HttpComponentsClientHttpRequestFactory(client));
    }