9 messages in com.googlegroups.android-developersRe: Bug: HttpClient
FromSent OnAttachments
tomgibara30 Dec 2007 14:40 
Wink Saville30 Dec 2007 15:15 
glor...@gmail.com30 Dec 2007 19:53 
fry19 Jan 2008 15:51 
tomgibara20 Jan 2008 12:07 
fry21 Jan 2008 04:41 
baker23 Jan 2008 19:46 
fry24 Jan 2008 01:54 
baker27 Jan 2008 17:27 
Subject:Re: Bug: HttpClient
From:tomgibara (tomg@hotmail.com)
Date:01/20/2008 12:07:57 PM
List:com.googlegroups.android-developers

Thanks for that workaround, I'll try it out. As I hinted in my posting, I was too tired at the time to pursue it further and have ignored the problem since then (side stepping it mostly by not reusing HttpClient instances) so I'm glad you took the time to post your workaround.

The docs for the method state:

Defines whether stale connection check is to be used. Disabling stale connection check may result in slight performance improvement at the risk of getting an I/O error when executing a request over a connection that has been closed at the server side.

I presume this is referring to the situation when a server times-out a 'kept-alive' HTTP session. I don't know how often that will happen since I expect it depends on the behaviour of the HttpClient library code. Anyway, it's got to be better than the workaround I've been using.

On Jan 19, 11:51 pm, fry <bend@gmail.com> wrote:

Hi! I had the same problem - the workaround is rather simple:

httpclient.getHttpConnectionManager().getParams().setStaleCheckingEnabled(false);

On Dec 31 2007, 1:41 am, tomgibara <tomg@hotmail.com> wrote:

Phew... this has taken me many many hours to track down, mostly because I stumbled across it in the middle of some dense resource management code - and the problem is actually very far from there...

Here's a test method (with a trivial subsidiary method) that makes two sequential requests to the same server using two different GetMethod objects sharing oneHttpClientobject - I presume a very common situation:

private void testSequentialGet(String url) { HttpClientclient = newHttpClient(); byte[] buffer = new byte[8192]; try {

GetMethod get1 = new GetMethod(url); try { int status = client.executeMethod(get1); Log.i("test", "Status for " + url + " (1) = " + status); long read = exhaust(get1.getResponseBodyAsStream(), buffer); Log.i("test", "Bytes read for " + url + " (1) = " + read); } finally { get1.releaseConnection(); }

GetMethod get2 = new GetMethod(url); try { int status = client.executeMethod(get2); Log.i("test", "Status for " + url + " (2) = " + status); long read = exhaust(get2.getResponseBodyAsStream(), buffer); Log.i("test", "Bytes read for " + url + " (2) = " + read); } finally { get2.releaseConnection(); } } catch (HttpException e) { Log.i("test", "Test of " + url + " failed with an HTTP exception.", e); } catch (IOException e) { Log.i("test", "Test of " + url + " failed with an IO exception.", e); } }

private static long exhaust(final InputStream in, byte[] buffer) throws IOException { long read = 0L; try { for (int r = 0; r >= 0; r = in.read(buffer)) read += r; } finally { try { in.close(); } catch (IOException e) { } } return read; }

We can call this method (using the latest version of the emulator to- date: m3-rc37) with a number of different URLs:

testSequentialGet("http://www.google.com"); testSequentialGet("http://www.apache.org"); testSequentialGet("http://www.microsoft.com");

and the resulting output in the log is:

I/test(656): Status forhttp://www.google.com(1) = 200 I/test(656): Bytes read forhttp://www.google.com(1) = 5424 I/test(656): Status forhttp://www.google.com(2) = 200 I/test(656): Bytes read forhttp://www.google.com(2) = 5424

I/test(656): Status forhttp://www.apache.org(1) = 200 I/test(656): Bytes read forhttp://www.apache.org(1) = 17409 I/test(656): Test ofhttp://www.apache.orgfailedwith an IO exception.

I/test(656): Test ofhttp://www.microsoft.comfailedwith an IO exception. I/test(656): java.io.InterruptedIOException: Read timed out

Repeated requests to Google work as expected. The first request to Apache (running a development version of the Apache webserver) succeeds but the second request fails. The first request to Microsoft (running IIS7) fails. These are, as far as I can confirm, entirely reproducible exceptions, and I don't think I'm making any mistakes in my use of the JakartaHttpClientlibrary. Nor am I behind a proxy server.

Anecdotally, I think that the problems may be related to HTTP/1.1 Keep Alives. I have three pieces of evidence for this. Firstly, disabling Keep Alives on my local development server (which is where I first encountered the problem) seemed to remove the exception. Secondly, I briefly looked online for a popular site that runs with Keep Alives disabled, I found Slashdot (http://slashdot.org) which runs in this way (on an Apache webserver); repeated requests to the /. homepage do not trigger an exception. Thirdly, the exception itself (which I don't have the motivation to investigate further at this time) is the same in every case and looks like this:

I/test(680): at org.apache.harmony.luni.platform.OSFileSystem.readImpl(Native Method) I/test(680): at org.apache.harmony.luni.platform.OSFileSystem.read(OSFileSystem.java: 150) I/test(680): at java.io.FileInputStream.read(FileInputStream.java: 306) I/test(680): at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:173) I/test(680): at java.io.BufferedInputStream.read(BufferedInputStream.java:228) I/test(680): at org.apache.commons.httpclient.HttpConnection.isStale(HttpConnection.java: 509) I/test(680): at org.apache.commons.httpclient.HttpConnection.closeIfStale(HttpConnection.java: 434) I/test(680): at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java: 381) I/test(680): at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java: 170) I/test(680): at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java: 398) I/test(680): at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java: 326)

Checking forstaleconnections might have some interaction with persistent connections?

There are numerous plausible workarounds; if this bug is not to be fixed soon, I welcome any advice on the best workaround to adopt since