Skip to content

Commit 7f86b30

Browse files
author
alessandro.gherardi
committed
Properly close the Apache response so that connections can be reused
1 parent 6f00c6a commit 7f86b30

File tree

2 files changed

+48
-15
lines changed

2 files changed

+48
-15
lines changed

connectors/apache-connector/src/main/java/org/glassfish/jersey/apache/connector/ApacheConnector.java

+8-15
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ public ClientResponse apply(final ClientRequest clientRequest) throws Processing
471471
}
472472

473473
try {
474-
responseContext.setEntityStream(new HttpClientResponseInputStream(getInputStream(response)));
474+
responseContext.setEntityStream(getInputStream(response));
475475
} catch (final IOException e) {
476476
LOGGER.log(Level.SEVERE, null, e);
477477
}
@@ -610,18 +610,6 @@ private static Map<String, String> writeOutBoundHeaders(final MultivaluedMap<Str
610610
return stringHeaders;
611611
}
612612

613-
private static final class HttpClientResponseInputStream extends FilterInputStream {
614-
615-
HttpClientResponseInputStream(final InputStream inputStream) throws IOException {
616-
super(inputStream);
617-
}
618-
619-
@Override
620-
public void close() throws IOException {
621-
super.close();
622-
}
623-
}
624-
625613
private static InputStream getInputStream(final CloseableHttpResponse response) throws IOException {
626614

627615
final InputStream inputStream;
@@ -640,8 +628,13 @@ private static InputStream getInputStream(final CloseableHttpResponse response)
640628
return new FilterInputStream(inputStream) {
641629
@Override
642630
public void close() throws IOException {
643-
response.close();
644-
super.close();
631+
try {
632+
super.close();
633+
} catch (IOException ex) {
634+
// Ignore
635+
} finally {
636+
response.close();
637+
}
645638
}
646639
};
647640
}

connectors/apache-connector/src/test/java/org/glassfish/jersey/apache/connector/StreamingTest.java

+40
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,14 @@
4949
import javax.ws.rs.client.WebTarget;
5050
import javax.ws.rs.core.Application;
5151
import javax.ws.rs.core.MediaType;
52+
import javax.ws.rs.core.Response;
5253

5354
import javax.inject.Singleton;
5455

56+
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
57+
5558
import org.glassfish.jersey.client.ClientConfig;
59+
import org.glassfish.jersey.client.ClientProperties;
5660
import org.glassfish.jersey.server.ChunkedOutput;
5761
import org.glassfish.jersey.server.ResourceConfig;
5862
import org.glassfish.jersey.test.JerseyTest;
@@ -64,6 +68,7 @@
6468
* @author Petr Janouch (petr.janouch at oracle.com)
6569
*/
6670
public class StreamingTest extends JerseyTest {
71+
private PoolingHttpClientConnectionManager connectionManager;
6772

6873
/**
6974
* Test that a data stream can be terminated from the client side.
@@ -85,8 +90,36 @@ public void clientCloseTest() throws IOException {
8590
assertEquals("NOK", sendTarget.request().get().readEntity(String.class));
8691
}
8792

93+
/**
94+
* Tests that closing a response without reading the entity does not throw an exception.
95+
*/
96+
@Test
97+
public void clientCloseThrowsNoExceptionTest() throws IOException {
98+
Response response = target().path("/streamingEndpoint/get").request().get();
99+
response.close();
100+
}
101+
102+
/**
103+
* Tests that closing a response after completely reading the entity reuses the connection
104+
*/
105+
@Test
106+
public void reuseConnectionTest() throws IOException {
107+
Response response = target().path("/streamingEndpoint/get").request().get();
108+
InputStream is = response.readEntity(InputStream.class);
109+
byte[] buf = new byte[8192];
110+
is.read(buf);
111+
is.close();
112+
response.close();
113+
114+
assertEquals(1, connectionManager.getTotalStats().getAvailable());
115+
assertEquals(0, connectionManager.getTotalStats().getLeased());
116+
}
117+
88118
@Override
89119
protected void configureClient(ClientConfig config) {
120+
connectionManager = new PoolingHttpClientConnectionManager();
121+
config.property(ApacheClientProperties.CONNECTION_MANAGER, connectionManager);
122+
config.property(ClientProperties.READ_TIMEOUT, 1000);
90123
config.connectorProvider(new ApacheConnectorProvider());
91124
}
92125

@@ -118,5 +151,12 @@ public String sendEvent() {
118151
public ChunkedOutput<String> get() {
119152
return output;
120153
}
154+
155+
@GET
156+
@Path("get")
157+
@Produces(MediaType.TEXT_PLAIN)
158+
public String getString() {
159+
return "OK";
160+
}
121161
}
122162
}

0 commit comments

Comments
 (0)