users@jersey.java.net

[Jersey] Re: How to make my Jersey HTTPS client connection persistent?

From: Markus Karg <karg_at_quipsy.de>
Date: Mon, 2 Nov 2015 19:48:02 +0100

Did you try this: Don't use .post() but instead keep the resulting Invocation.Builder, and then in your loop simply apply .post(data) several times?

From: neoterikos4 [mailto:neoterikos4_at_yahoo.com]
Sent: Montag, 2. November 2015 19:29
To: users_at_jersey.java.net
Subject: [Jersey] How to make my Jersey HTTPS client connection persistent?

[RedHat enterprise linux server. Java version 8. Jersey version 2.21.]

Is there a way in Jersey to make an HTTPS client connection persistent?

(I am reading that HTTPS connections are persistent, but that is not the behavior I'm seeing with my client.)

I would like to create a connection, POST a number of messages using the same connection, and finally disconnect. I would like to keep the connection open, not have it close between POSTs.

I have the following java Jersey code:

// target is WebTarget

Response resp = target.request(mediaType).header("Connection", "keep-alive").post(Entity.entity(message, mediaType));

for (i = 0; i < 5; i++) {

    Thread.sleep(5000);

    LogService.log(srcId, LogLevel.TRACE, "Sleeping...");

}

// log succeeded or failed message here
In netstat, I see the ESTABLISHED connection show up, remain for 6-8 seconds, and then go away. I would like it to remain open, so the next POST can use the same connection without reconnecting.

Running with -Djavax.net.debug=all, I see the connection set up and the data POSTed:

...

%% Cached client session: [Session-1, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256]

[read] MD5 and SHA1 hashes: len = 16

...

Padded plaintext before ENCRYPTION: len = 288

...

0010: 50 4F 53 54 20 2F 41 41 41 2F 4D 4E 4F 50 2F 20 POST /AAA/MNOP/

0020: 48 54 54 50 2F 31 2E 31 0D 0A 41 63 63 65 70 74 HTTP/1.1..Accept

0030: 3A 20 74 65 78 74 2F 70 6C 61 69 6E 3B 20 63 68 : text/plain; ch

0040: 61 72 73 65 74 3D 61 73 63 69 69 0D 0A 43 6F 6E arset=ascii..Con

0050: 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 70 2D 61 6C nection: keep-al

0060: 69 76 65 0D 0A 43 6F 6E 74 65 6E 74 2D 54 79 70 ive..Content-Typ

0070: 65 3A 20 74 65 78 74 2F 70 6C 61 69 6E 3B 63 68 e: text/plain;ch

0080: 61 72 73 65 74 3D 61 73 63 69 69 0D 0A 55 73 65 arset=ascii..Use

0090: 72 2D 41 67 65 6E 74 3A 20 4A 65 72 73 65 79 2F r-Agent: Jersey/

00A0: 32 2E 32 31 20 28 48 74 74 70 55 72 6C 43 6F 6E 2.21 (HttpUrlCon

00B0: 6E 65 63 74 69 6F 6E 20 31 2E 38 2E 30 5F 34 35 nection 1.8.0_45

00C0: 29 0D 0A 48 6F 73 74 3A 20 -- -- -- -- -- -- -- )..Host: xxxxxxx

00D0: -- -- -- -- -- -- 3A 38 30 38 35 0D 0A 43 6F 6E xxxxxx:8085..Con

00E0: 74 65 6E 74 2D 4C 65 6E 67 74 68 3A 20 36 33 35 tent-Length: 635

...

pool-1-thread-1, WRITE: TLSv1.2 Application Data, length = 288

[Raw write]: length = 293

...
Then I see the response come back:

...

pool-1-thread-1, READ: TLSv1.2 Application Data, length = 160

Padded plaintext after DECRYPTION: len = 160

...

0010: 48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D HTTP/1.1 200 OK.

0020: 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 6B 65 65 .Connection: kee

0030: 70 2D 61 6C 69 76 65 0D 0A 44 61 74 65 3A 20 46 p-alive..Date: F

0040: 72 69 2C 20 33 30 20 4F 63 74 20 32 30 31 35 20 ri, 30 Oct 2015

0050: 32 33 3A 33 37 3A 32 39 20 47 4D 54 0D 0A 43 6F 23:37:29 GMT..Co

0060: 6E 74 65 6E 74 2D 6C 65 6E 67 74 68 3A 20 30 0D ntent-length: 0...

...

2015/303 23:37:34.826: TRACE myapp.BaseHttpsConnector.doPostFile:236 - Sleeping...

Keep-Alive-Timer, called close()

Keep-Alive-Timer, called closeInternal(true)

Keep-Alive-Timer, SEND TLSv1.2 ALERT: warning, description = close_notify

Padded plaintext before ENCRYPTION: len = 64

...

Keep-Alive-Timer, WRITE: TLSv1.2 Alert, length = 64

[Raw write]: length = 69

...

Keep-Alive-Timer, called closeSocket(true)

2015/303 23:37:39.829: TRACE myapp.BaseHttpsConnector.doPostFile:236 - Sleeping...

2015/303 23:37:44.831: TRACE myapp.BaseHttpsConnector.doPostFile:236 - Sleeping...

2015/303 23:37:49.833: TRACE myapp.BaseHttpsConnector.doPostFile:236 - Sleeping...

2015/303 23:37:54.836: TRACE myapp.BaseHttpsConnector.doPostFile:236 - Sleeping...

2015/303 23:37:54.836: INFO myapp.BaseHttpsConnector.doPostFile:261 - POST of file {myfile.xml} succeeded: 200: OK
So buried deep within the post() call, there is a Keep-Alive-Timer calling close() asynchronously on the connection, before I have done anything with the Response object. "Connection: keep-alive" is set in the headers for both the POST and the response. I also set the system property http.keepAlive to true in the client, even though that is the default anyway. How do I keep the connection from being closed, so that when the next message needs to be POSTed a short time later, the client can reuse the connection?

Thank you very much for your help!