0

I have an app that was running on my local development machine and also on Amazon Web Services (AWS).

From about lunchtime yesterday it suddenly started to generate this stack trace, whilst trying to perform a HTTP POST which previously had been working absolutely fine.

Exception: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target...
    sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
    sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
    sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
    sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
    sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
    sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
    sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
    sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
    sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
    sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
    sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
    org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
    org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
    org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:141)
    org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
    org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
    org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
    org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
    org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
    org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
    org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
    com.devology.extractors.GovUkExtractor.getHtmlResponseFromCheckMotGovUk(GovUkExtractor.java:219)
    com.devology.extractors.GovUkExtractor.search(GovUkExtractor.java:59)
    com.devology.rest.VehicleDataRestService.getIt(VehicleDataRestService.java:48)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:498)
    org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
    org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151)
    org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171)
    org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$TypeOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:195)
    org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
    org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:402)
    org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:349)
    org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:106)
    org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:259)
    org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
    org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
    org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    org.glassfish.jersey.internal.Errors.process(Errors.java:267)
    org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:318)
    org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:236)
    org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1010)
    org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:373)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:382)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:345)
    org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:220)
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:676)
    org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
    org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
    org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
    java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    java.lang.Thread.run(Thread.java:745)

The really strange thing was that I tried to change from using https back to http on my LOCAL development machine, which results in an expected problem because the page only serves https, so I swapped back to https (identical code to 5 minutes prior) and it started working.

I then checked on AWS on a build that was failing and that too started working again - that is absolutely no code changes.

Evidently it would seem it's not code related, I've seen some reports about adding stuff to the certificate store, but I've never touched this using the HTTP Client to download pages via https and it has worked okay until now.

What would cause this odd behaviour?

Here's a snippet of the code that breaks..

// SETUP THE COOKIE STORE (used in initial GET and subsequent POST)
BasicCookieStore cookieStore = new BasicCookieStore();

HttpClient client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build();

final HttpPost post = new HttpPost(CHECK_MOT_BASE_URL);
ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("registration", registrationNumber));
...
post.setEntity(new UrlEncodedFormEntity(postParameters));

// POST the request
HttpResponse response = client.execute(post); *** <<<<--- BROKE HERE ***

// Parse the response
String rawResponse = EntityUtils.toString(response.getEntity(), "UTF-8");

Although it's working fine now, it makes me nervous that it could break again.

Some thoughts ...

  • Could it be that their server time drifted and the certificate became untrusted?
  • Should I be doing something with the certificate store (I presume not because this is a third party public server)
  • Can't be AWS specific because I had the same problem on my local development machine, whereas yesterday morning it was okay.

Many thanks Rob.

RobbiewOnline
  • 1,350
  • 1
  • 16
  • 36
  • The problem is due to an unstrust certificate from server. The server could have changed the certificate. You need to include it in the truststore of the JRE. I have answered a similar question moments ago. Check if it is your problem http://stackoverflow.com/questions/37974551/documentum-rest-service-trusting-ssl-certificate-from-java-client/37987359#37987359 – pedrofb Jun 23 '16 at 10:09
  • Thanks Pedrofb - It's running again now without any code changes (I've not explicitly created/added to a certificate store). Is it possible that HttpClient has it's own certificate store? I'm also running in AWS via their ElasticBeanstalk, so the EC2 instances are provisioned automatically and I've never needed to manually deal with the trust stores. – RobbiewOnline Jun 23 '16 at 12:57
  • If you do not define a truststore, then is used the default of JRE at `jre/lib/security/cacerts`. Also with HttpClient. May be a temporal server failure providing the certificate chain... – pedrofb Jun 23 '16 at 13:09

0 Answers0