views:

288

answers:

2

I'm new to Java development so please bear with me. Also, I hope I'm not the champion of tl;dr :).

I'm using HttpClient to make requests over Http (duh!) and I'd gotten it to work for a simple servlet that receives an URL as a query string parameter. I realized that my code could use some refactoring, so I decided to make my own HttpResponseHandler, to clean up the code, make it reusable and improve exception handling.

I currently have something like this:

public class HttpResponseHandler implements ResponseHandler<InputStream>{

    public InputStream handleResponse(HttpResponse response)
            throws ClientProtocolException, IOException {

        int statusCode = response.getStatusLine().getStatusCode();
        InputStream in = null;

        if (statusCode != HttpStatus.SC_OK) {
            throw new HttpResponseException(statusCode, null);
        } else {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                in = entity.getContent();
                // This works
                // for (int i;(i = in.read()) >= 0;) System.out.print((char)i); 
            }
        }
        return in;
    }
}

And in the method where I make the actual request:

HttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet(target);
ResponseHandler<InputStream> httpResponseHandler = new HttpResponseHandler();
try {
    InputStream in = httpclient.execute(httpget, httpResponseHandler);
    // This doesn't work
    // for (int i;(i = in.read()) >= 0;) System.out.print((char)i);     
    return in;
} catch (HttpResponseException e) {
throw new HttpResponseException(e.getStatusCode(), null);
}

The problem is that the input stream returned from the handler is closed. I don't have any idea why, but I've checked it with the prints in my code (and no, I haven't used them both at the same time :). While the first print works, the other one gives a closed stream error.

I need InputStreams, because all my other methods expect an InputStream and not a String. Also, I want to be able to retrieve images (or maybe other types of files), not just text files.

I can work around this pretty easily by giving up on the response handler (I have a working implementation that doesn't use it), but I'm pretty curious about the following:

  1. Why does it do what it does?
  2. How do I open the stream, if something closes it?
  3. What's the right way to do this, anyway :)?

I've checked the docs and I couldn't find anything useful regarding this issue. To save you a bit of Googling, here's the Javadoc and here's the HttpClient tutorial (Section 1.1.8 - Response handlers).

Thanks,
Alex

+1  A: 

The automatic resource management which is called closes the stream for you to make sure all resources are freed and ready for the next task.

If you want streams then you best bet is to copy it to a ByteArray and return a ByteArrayInputStream if the content is relatively modest.

If the content is not modest, then you'll have to do the resource management your self and not the the ResponseHandler.

Peter Tillemans
How would you define 'modest'? :)
Alex Ciminian
Depends on the number of concurrent connections and the memory size of the machine. Nowadays several megabytes to 10's of megabytes can be considered 'modest'.It has to fit in memory.
Peter Tillemans
+1  A: 

It closes the stream because ResponseHandler must handle the whole response. Even if you get an open stream, it should be at the end of stream.

The stream is closed by BasicHttpEntity's consumeContent() call to ensure you don't read from the stream again.

In your case, you don't really need ResponseHandler.

ZZ Coder