24
votes

Here is how I use it -

private static final PoolingHttpClientConnectionManager connPool;

static {

        connPool = new PoolingHttpClientConnectionManager();
        // Increase max total connection to 200
        connPool.setMaxTotal(200);//configurable through app.properties
        // Increase default max connection per route to 50
        connPool.setDefaultMaxPerRoute(20);//configurable through app.properties

}

CloseableHttpClient httpClient = HttpClients.custom()
                .setConnectionManager(connPool) .build();

ALso I have put a finally block around http GET -

finally {
            try {
                httpClient.close();
            } catch (IOException e) {
                LOGGER.error(e.getMessage());   
            }
        }

Here is my stacktrace -

java.lang.IllegalStateException: Connection pool shut down
    at org.apache.http.util.Asserts.check(Asserts.java:34)
    at org.apache.http.pool.AbstractConnPool.lease(AbstractConnPool.java:169)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:217)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:157)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:194)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at com.A.B.C.CustomHttpClient.doGETAndValidate(CustomHttpClient.java:44)
    at com.A.B.C.SiteMonitorTask.monitorAndUpdateEndPoints(SiteMonitorTask.java:48)
    at com.A.B.C.SiteMonitorTask.run(SiteMonitorTask.java:37)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

I am using Quartz to schedule a job of monitoring Http end points.. Here is my connection pool configuration

totalMaxHttpConn=200
maxHttpConnPerRoute=20

Maven dependency.. artifact version

httpclient 4.3.1
httpcore 4.3.1

EDIT - Well the problem got away by not closing CloseableHttpClient in the finally block.. Can anyone tell why is it behaving like that? Why is connection pool shut down if i close a client?

Is the closeablehttpclient above is a handle to the pool rather than a single conn

2
And where is the code where you are accessing the pool? My bet is the pool is closed by someone/something when you are accessing it. - Praba
Does the code above suffice? - abipc
Was searching for a suitable doc link to explain that. You should be releasing the connection and not close it. You're not actually closing a client. IOW, a client is the actual connection that you create to your HTTP URL. - Praba
there is no API like release connection for CloseableHttpClient - abipc

2 Answers

12
votes

This behavior is due to a bug in HC 4.3. It has already been fixed in HC 4.4a1. As of 4.4 CloseableHttpClient#close should automatically shut down the connection pool only if exclusively owned by the client

52
votes

In version 4.4 the method setConnectionManagerShared was added to HttpClientBuilder. If you set it to true the client won't close the connection manager.

HttpClients.custom()
            .setConnectionManager(Util.getConnectionManager()) // shared connection manager
            .setConnectionManagerShared(true)