'Already Connected' exception trying to do POST request using Jersey Client API
Asked Answered
M

5

26

I'm creating integration tests for a JAX-RS/Jersey Webservice deployed on Tomcat 8 using arquillian.

I am trying to do a POST request like that:

E dummy = dummyFactory.manufacturePojo(getSubClassType());
dummy.setId(null);

Client client = ClientBuilder.newClient();
WebTarget target = client.target(BASE_URI).path("bandeira");

Response response = target.request(MediaType.APPLICATION_JSON)
            .header(HttpHeaders.AUTHORIZATION, CHAVE_TESTE)
            .header(HttpHeaders.CONTENT_TYPE, "application/json")
            .post(Entity.entity(dummy, MediaType.APPLICATION_JSON));

When I do that I get this exception:

Caused by: java.lang.IllegalStateException: Already connected
at sun.net.www.protocol.http.HttpURLConnection.setRequestProperty(HttpURLConnection.java:3000)
at org.glassfish.jersey.client.HttpUrlConnector.setOutboundHeaders(HttpUrlConnector.java:364)
at org.glassfish.jersey.client.HttpUrlConnector.access$100(HttpUrlConnector.java:91)
at org.glassfish.jersey.client.HttpUrlConnector$4.getOutputStream(HttpUrlConnector.java:327)
at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:201)
at org.glassfish.jersey.message.internal.CommittingOutputStream.commitStream(CommittingOutputStream.java:195)
at org.glassfish.jersey.message.internal.CommittingOutputStream.commit(CommittingOutputStream.java:263)
at org.glassfish.jersey.message.internal.OutboundMessageContext.commitStream(OutboundMessageContext.java:816)
at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:546)
at org.glassfish.jersey.client.HttpUrlConnector._apply(HttpUrlConnector.java:331)
at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:243)
at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:246)
... 149 more

I could use some heuristic since I am still learning arquillian and Jersey client API :) Thank you

Mcneill answered 9/3, 2015 at 21:1 Comment(1)
I don't know arquillian but the jersey-client piece looks ok to me. Can you debug and see if your header is properly written? You can see it from the response.Centerboard
L
31

It may be that java.lang.IllegalStateException: Already connected only masks the SSLHandshakeException. Please take a look at the issue #3000 (previously known as JERSEY-2728 bug).

Ladle answered 10/3, 2015 at 7:14 Comment(5)
looks like, but what would be the work around in this case? @Grzesiek D.Mcneill
@MarcosJ.CKichel Thats mean there is something wrong with your connection, so please double check your BASE_URI. Also you can try plain http instead of https (because https needs SSLContext provided, but I don't see it in your code).Ladle
hmmmmm, well, I am not using https anyway.. but I will for sure check the uri.. Thanks :D @Grzesiek D.Mcneill
Link rot here: the Jersey code and bugs are now in github here: github.com/jersey/jersey/issues/3000 (why on earth would Oracle shutter java.net - sigh)Wiretap
@Wiretap thanks, I've updated the answer. BTW: for me it's not a problem - GitHub may be a better platform collaboration than the old www.java.net.Ladle
K
6

This could be due to network connection problem. I met this problem since my VPN lost connection. Exceptions with "Already connected" reported during jackson serializing the mail body.(I imported the source code of Jersey and jackson-jaxrs-base for debugging). After I removed the mail body, then new Exception with error, "Unknown hostname", came out.

After I login to my VPN, everything works fine.

I am very unhappy about the Jersey client exception "Already connected" which gave me nothing but confusion.

Knossos answered 18/5, 2016 at 7:16 Comment(1)
This happens to me when I am not on the company network, or on the VPN!Fibroin
R
4

Probably the problem is in SSL negotiation. Try to add "trustall" Client initialization logic.

SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, new TrustManager[] { new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}

} }, new java.security.SecureRandom());

Client client = ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier((s1, s2) -> true)
.register(MultiPartFeature.class)
.register(new EncodingFeature("gzip", GZipEncoder.class))
.build();
Rigveda answered 29/7, 2015 at 10:38 Comment(3)
The underlying issue is SSL negotiation failing and the exception being swallowed; but even adding an all-trusting trust manager doesn't fix it for my case. I resorted to having Apache HTTP Client 4.4 Connection provider and installing an all-trusting trust manager which fixed the problemCidevant
This is a really bad idea :(. Please, fix things so you can trust the certificate properly, rather than throwing away the integrity you should get from using TLS.Gilbertina
@AndrewAylett basically: yes. in my case i didn't want to use SSL at all, but the other side forces me to.Wafd
N
2

You may be setting header property on http connection after calling connection.connect();

Naylor answered 15/11, 2016 at 1:44 Comment(1)
worked for me. I moved my connection.setRequestProperty before my connection.getOutputStream() and had success. Thank you!Oldie
A
0

Its probably an SSL exception being masked by the already connected exception. The easiest way to verify/debug the SSL exception is to add the following JVM flags:

-Djavax.net.debug=ssl:handshake:verbose:keymanager:trustmanager -Djava.security.debug=access:stack

This will tell the JVM to print out a whole host of SSL handshake information including any exceptions. From this information you should be able to see what the problem is.

Aufmann answered 6/9, 2021 at 9:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.