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]