Reputation: 255
I am trying to send a JSON request to a secure REST webservice using a keystore file and I am using Jersey API. Below is the snippet of my code
SslConfigurator sslConfigurator = SslConfigurator.newInstance().trustStoreFile("C:\\Users\\******\\test.keystore").trustStorePassword("password");
SSLContext sslContext = sslConfigurator.createSSLContext();
Client client = ClientBuilder.newBuilder().sslContext(sslContext).build();
WebTarget target = client.target("https://hostname:portnumber").path("resourse/methodname/v1");
Form form = new Form();
form.param("key1", "value1");
form.param("key2", "value2");
Response response = target.request(MediaType.APPLICATION_JSON_TYPE).post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
System.out.println(response);
But I am getting the following exception on the last but one line.
Exception in thread "main" javax.ws.rs.ProcessingException: Already connected
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:264)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:684)
at org.glassfish.jersey.client.JerseyInvocation$1.call(JerseyInvocation.java:681)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:444)
at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:681)
at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:437)
at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:343)
at TestMain.main(TestMain.java:29)
Caused by: java.lang.IllegalStateException: Already connected
at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:3014)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.setRequestProperty(HttpsURLConnectionImpl.java:316)
at org.glassfish.jersey.client.internal.HttpUrlConnector.setOutboundHeaders(HttpUrlConnector.java:421)
at org.glassfish.jersey.client.internal.HttpUrlConnector.access$100(HttpUrlConnector.java:96)
at org.glassfish.jersey.client.internal.HttpUrlConnector$4.getOutputStream(HttpUrlConnector.java:384)
at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:200)
at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:194)
at org.glassfish.jersey.message.internal.CommittingOutputStream.commit(CommittingOutputStream.java:262)
at org.glassfish.jersey.message.internal.OutboundMessageContext.commitStream(OutboundMessageContext.java:816)
at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:545)
at org.glassfish.jersey.client.internal.HttpUrlConnector._apply(HttpUrlConnector.java:388)
at org.glassfish.jersey.client.internal.HttpUrlConnector.apply(HttpUrlConnector.java:285)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:255)
... 10 more
Upvotes: 3
Views: 17787
Reputation: 860
It is actually a bug in jersey that the error message in the exception is basically wrong. Please see SSLHandshakeException masked by useless IllegalStateException: Already connected
So basically, it means that there is a problem in SSL handshaking between the server and client.
One of the causes of the exception is related to this: Jersey API Doc - 5.9. Securing a Client
... ClientBuilder also offers a method for defining a custom HostnameVerifier implementation. HostnameVerifier implementations are invoked when default host URL verification fails.
Important
A behaviour of HostnameVerifier is dependent on an http client implementation. HttpUrlConnector and ApacheConnector work properly, that means that after the unsuccessful URL verification HostnameVerifier is called and by means of it is possible to revalidate URL using a custom implementation of HostnameVerifier and go on in a handskahe processing. JettyConnector and GrizzlyConnector provide only host URL verification and throw a CertificateException without any possibility to use custom HostnameVerifier. Moreover, in case of JettyConnector there is a property JettyClientProperties.ENABLE_SSL_HOSTNAME_VERIFICATION to disable an entire host URL verification mechanism in a handshake.
If you are using Grizzly, you can't turn it off, but there is a workaround. It is to set a customized HostnameVerifier that the verify() always returns true in the client configuration:
Client c = ClientBuilder.newBuilder().sslContext(sslContext).hostnameVerifier(new HostnameVerifier(){
@Override
public boolean verify(String paramString, SSLSession paramSSLSession) {
return true;
}
}).build();
Upvotes: 6