Search code examples
spring-bootsslgroovy

Could not find matching constructor for HttpComponentsClientHttpRequestFactory during PK12 ssl configuration


I want to send requests with a SSL certificate using RestTemplate. To generate a RestTemplate, I created the function below.

protected RestTemplate createRestTemplate2(){
    KeyStore clientStore = KeyStore.getInstance("PKCS12");
    FileInputStream keyStoreFile = new FileInputStream("certifacate_file.p12");
    char[] keyStorePassword = "password".toCharArray();

    clientStore.load(keyStoreFile, keyStorePassword)

    SSLContext sslContext = SSLContextBuilder.create()
            .setProtocol("TLS")
            .loadKeyMaterial(clientStore, keyStorePassword)
            .loadTrustMaterial(new TrustSelfSignedStrategy())
            .build();

    SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext);

    HttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create().setSSLSocketFactory(sslConnectionSocketFactory).build();
    CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); // Error happens at here
    return new RestTemplate(requestFactory);
}

But when I run it, I'm getting the error below.

Could not find matching constructor for: org.springframework.http.client.HttpComponentsClientHttpRequestFactory(org.apache.hc.client5.http.impl.classic.InternalHttpClient)

In my project I'm using Apache HttpClient 5.x but the problem is new HttpComponentsClientHttpRequestFactory() doesn't use the same version, because of that I'm getting this error. But the problem is all the guides in the internet showing it to do this way but I'm unable to do it. Can you help me?


Solution

  • This doesn't answer your exact question (it is necessary to know what versions of Spring Framework and Apache HttpClient you are using to do that), but if you are using Spring Boot 3.1 or later you don't need to do this setup manually, as Spring Boot can configure the RestTemplate SSL connection for you.

    First, create an SSL bundle from the certificate:

    spring:
      ssl:
        bundle:
          jks:
            client:
              key:
                alias: "myalias"
              truststore:
                location: "classpath:certifacate_file.p12"
                password: "password"
                type: "PKCS12"
    

    Then create a RestTemplate using the SSL bundle:

    protected RestTemplate createRestTemplate2(RestTemplateBuilder builder, SslBundles sslBundles) {
      return restTemplateBuilder.setSslBundle(sslBundles.getBundle("client")).build();
    }