title: Spring RestTemplate receiving sun.security.validator.ValidatorException: PKIX path building failed:
body: <p>I'm trying to connect to a third party URL that is over HTTPS. They told us that all we need is to send them a HTTPS POST (no certificates/keystore required). However, I'm receiving the following exception:</p>
  
  <pre><code>org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://mep.moxtra.com/sample/api/v1/auth/cus/token": sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:666)
  at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
  at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:407)
  Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
  at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1959)
  at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
  at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
  at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1514)
  at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
  at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
  at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1072)
  at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1385)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1413)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1397)
  at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
  at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
  at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
  at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:359)
  at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
  at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
  at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
  at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
  at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
  at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
  at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
  at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
  at org.springframework.http.client.HttpComponentsClientHttpRequest.executeInternal(HttpComponentsClientHttpRequest.java:89)
  at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
  at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:53)
  at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:652)
  ... 33 more
  
  Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
  at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397)
  at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302)
  at sun.security.validator.Validator.validate(Validator.java:260)
  at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
  at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
  at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
  at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
  ... 56 more
  </code></pre>
  
  <p>This is the code I have and I managed to implement some of the approaches to allow Spring RestTemplate make a POST to a HTTPS API.</p>
  
  <pre><code>RestTemplate restTemplate = new RestTemplate(buildCustomRequestFactory());
  HttpHeaders requestHeaders = new HttpHeaders();
  requestHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
  //This will only add the parameters I need on the body to call the POST operation
  MultiValueMap&lt;String, String&gt; parametersMap = buildParametersMap(hubUserInfo);
  
  HttpEntity&lt;MultiValueMap&lt;String, String&gt;&gt; jsonRequestEntity = new HttpEntity&lt;MultiValueMap&lt;String,String&gt;&gt;(parametersMap, requestHeaders);
  try {
      ResponseEntity&lt;String&gt; response = restTemplate.postForEntity(moxtraApiUrl, jsonRequestEntity, String.class);
  
      System.out.println(response.getBody());
  } catch (Exception e) {
      e.printStackTrace();
  }
  </code></pre>
  
  <p>For the creation of the CustomRequestFactory:</p>
  
  <pre><code>private HttpComponentsClientHttpRequestFactory buildCustomRequestFactory() {
      HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
      CloseableHttpClient httpClient = HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
      requestFactory.setHttpClient(httpClient);
  
      return requestFactory;
  }
  </code></pre>
  
  <p>Do you know if I am missing some configuration or there's another approach to achieve making the POST request over HTTPS?</p>
  
  <p>Thanks in advance.</p>