I am writing a follow-on to the thread started by Christoph Jaehnigen on Wed, 23 Sep 2009 15:05:35 GMT about warnings emitted by the Apache HttpClient SimpleHttpConnectionManager. I am using commons-httpclient-3.1-rc1. This message appears:

>org.apache.commons.httpclient.SimpleHttpConnectionManager
>getConnectionWithTimeout
>WARNING: SimpleHttpConnectionManager being used incorrectly.  Be sure
>that HttpMethod.releaseConnection() is always called and that only one
>thread and/or method is using this connection manager at a time.

Below I have attached a simplified class that reproduces the problem. You can see that the code is single threaded and always, always calls method.releaseConnection(). Yet the warning still appears. Frustrating!

After some goofing I think I may have stumbled upon a workaround, and would like to get your input. Basically I added a call to method.abort() in the exception clause triggered by timeout. If that is done, I get no warning from SimpleConnectionManager. Is this the right thing to do, or is there some deeper issue to be solved?

Please reply, thanks.

chris...

p.s.  I see now that HC 4.0 is available, I better try that, huh?
package org.chris_lott.httptimeout;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.util.TimeoutController;

/**
 * Demonstrates how to use timeout when fetching HTTP.
 * Supposed to reproduce this warning:
 * 
 * org.apache.commons.httpclient.SimpleHttpConnectionManager
 * getConnectionWithTimeout
 * WARNING: SimpleHttpConnectionManager being used incorrectly.
 * Be sure that HttpMethod.releaseConnection() is always called
 * and thatonly one thread and/or method is using this connection
 * manager at a time.
 * 
 * @author Chris Lott
 *
 */
public class FetchByHttpWithTimeout {

        /**
         * Runs a HTTP method (get or post) with a specified timeout.
         * This very thin wrapper accepts a HttpClient and a method object.
         * Caller must establish all properties/parameters on both,
         * and must extract the response from the method.
         */
        class HttpMethodTimeoutWrapper implements Runnable {

                private final HttpClient httpClient;
                private final HttpMethodBase httpMethod;

                private int responseCode;
                private Exception httpException;

                /**
                 * @param client
                 * @param method
                 */
                public HttpMethodTimeoutWrapper(
                                HttpClient client,
                                HttpMethodBase method) {
                        this.httpClient = client;
                        this.httpMethod = method;
                }

                public int getResponseCode() {
                        return this.responseCode;
                }

                /**
                 * @return IOException or HttpException
                 */
                public Exception getHttpException() {
                        return this.httpException;
                }

                /**
                 * Calls the client to execute the method.
                 * This gets wrapped within a thread that has a timeout limit.
                 */
                public void run() {
                        try {
                                this.responseCode = 
this.httpClient.executeMethod(httpMethod);
                        }
                        catch (Exception ex) {
                                this.httpException = ex;
                        }
                }
        }

        private HttpClient client;

        public FetchByHttpWithTimeout() {
                this.client = new HttpClient();
                HttpClientParams httpClientParams = new HttpClientParams();
                
httpClientParams.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
                
httpClientParams.setBooleanParameter("http.protocol.single-cookie-header", 
true);
                client.setParams(httpClientParams);
        }

        private String getByHttp(String url, 
                        long timeoutLimit) throws Exception {

                GetMethod method = new GetMethod(url);

                // Limit the amount of time this can run
                // so a hung web site will not hang a pull.
                HttpMethodTimeoutWrapper wrapper = new HttpMethodTimeoutWrapper(
                                client, method);
                String response = null;

                try {
                        TimeoutController.execute(wrapper, timeoutLimit);
                        if (wrapper.getHttpException() == null) {
                                int responseCode = wrapper.getResponseCode();
                                System.out.println("responseCode is " + 
responseCode);
                                response = getResponse(method);
                        }
                }
                catch (TimeoutController.TimeoutException ex) {
                        System.out.println("Timed out!");
                        // This call to abort avoids the SimpleHttpConnection 
warning!
                        //if (! method.isAborted())
                        //      method.abort();
                }
                finally {
                        System.out.println("Releasing connection");
                        method.releaseConnection();
                }

                if (wrapper.getHttpException() != null)
                        throw wrapper.getHttpException();

                return response;
        }

        /**
         * Reads and returns response, converting from stream to String
         * 
         * @param method
         * @return
         * @throws IOException
         */
        private String getResponse(HttpMethodBase method) throws IOException {

                InputStream inputStream = method.getResponseBodyAsStream();
                if (inputStream == null)
                        return null;

                BufferedReader inputReader = new BufferedReader(new 
InputStreamReader(inputStream));
                StringBuffer outputBuffer = new StringBuffer();

                char data [] = new char [10240];
                int length;
                while ((length = inputReader.read(data)) >= 0)
                        outputBuffer.append(data, 0, length);

                return outputBuffer.toString();
        }

        public static void main(String [] args) {
                
                // This project has a commons-logging.properties file
                // in the src folder that chooses java.util.logging.
                // Only content is this line:
                // 
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Jdk14Logger
                
                try {
                        FetchByHttpWithTimeout fetcher = new 
FetchByHttpWithTimeout();
                        String url = "http://hc.apache.org/httpclient-3.x/";;
                        
                        // Reduce this until "Timed out!" messages appear;
                        // for me, this happens at 400msec or less.
                        int timeoutMsec = 300;
                        for (int i = 0; i < 3; ++i) {
                                System.out.println("Iter " + i + ": fetching 
with limit of " + timeoutMsec);
                                fetcher.getByHttp(url, timeoutMsec);
                        }
                        
                        System.out.println("Done.");
                }
                catch (Exception ex) {
                        System.err.println(ex.toString());
                }
        }
}

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to