HttpClient and ConnectionPoolTimeoutException

Monday 15 November 2010

I've recently had a bit of trouble with my application's DefaultHttpClient instance throwing a ConnectionPoolTimeoutException quite consistently after a number of requests to the same location. (See bottom of the entry for a stacktrace).

There doesn't seem to be anything regarding this particular stacktrace in any of the Android developer forums up to now but coincidently Axis2 framework users (Also using Apache HttpClient) reported the same exception occuring after 3 requests to the same location, which is exactly what I experienced.

Here was my instance creation code for the HttpClient:

HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);

SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));

// Where ClientConfig.P_DEFAULT_CONN_TIMEOUT = 15 seconds
HttpConnectionParams.setConnectionTimeout(params, ClientConfig.P_DEFAULT_CONN_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, ClientConfig.P_DEFAULT_CONN_TIMEOUT);
ConnManagerParams.setTimeout(params, ClientConfig.P_DEFAULT_CONN_TIMEOUT);

httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(params, schemeRegistry), params);

If you're using TheradSafeClientConnManager be aware that there is a "Max connections per route" property available which is pretty well hidden, and again isn't mentioned in any of the example code I came across. Setting this to a higher value got rid of my issue.

...
ConnManagerParams.setMaxConnectionsPerRoute(params, new ConnPerRoute() {
    @Override
    public int getMaxForRoute(HttpRoute httproute)
    {
        return 10;
    }
});
...

The stacktrace:
fetch() sending failed to url http://192.168.0.45/blah
org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute.getEntryBlocking(ConnPoolByRoute.java:353)
    at org.apache.http.impl.conn.tsccm.ConnPoolByRoute$1.getPoolEntry(ConnPoolByRoute.java:238)
    at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager$1.getConnection(ThreadSafeClientConnManager.java:175)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:325)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
    at chesspresso.client.android.net.HttpCall.fetch(HttpCall.java:114)
    at chesspresso.client.android.net.HttpCall.fetch(HttpCall.java:134)
    at chesspresso.client.android.net.HttpCall.post(HttpCall.java:107)
    at chesspresso.client.android.net.ServerCallGoogle.loginGoogle(ServerCallGoogle.java:30)
    at chesspresso.client.android.activity.support.ActivityProcessesGoogle$LoginGoogleTask.doInBackground(ActivityProcessesGoogle.java:72)
    at chesspresso.client.android.activity.support.ActivityProcessesGoogle$LoginGoogleTask.doInBackground(ActivityProcessesGoogle.java:1)
    at android.os.AsyncTask$2.call(AsyncTask.java:185)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
    at java.lang.Thread.run(Thread.java:1096)

Apache HttpClient is obviously used quite a lot by many apps yet it's configurable parameters haven't been explained in android examples as well as they should be I would say.

1 comments:

felipecsl said...

Thank you very much. This fixed my timeouts as well!