You are viewing a plain text version of this content. The canonical link for it is here.
Posted to httpclient-users@hc.apache.org by Dan Checkoway <dc...@gmail.com> on 2012/04/13 03:40:19 UTC

Timeouts not being obeyed

Hello,

I'm a long-time very happy user of HttpClient.  I have bumped into what I
believe is a bug...but it's possible I'm just abusing the API and missing
something simple.  :-)

I use ThreadSafeClientConnManager and a single shared instance of
DefaultHttpClient to manage a persistent HTTP connection pool.  It works
exactly as I need it to -- except it's not obeying timeouts.

What I need to do is set an arbitrary timeout for each individual request.
That is, I can't just set one timeout up front when I create the
HttpClient.  The timeout I need to use varies from request to request.

The way I'm *trying* to convey the timeout is by setting attributes on the
HttpContext as shown in the code below...but what I'm experiencing is that
my timeouts are being ignored.

I believe the root of the problem is that AbstractHttpClient is using its
determineParams() method, but that's completely disregarding the params
which may have been set on the context.

Can you let me know if (a) this is a bug and I'm doing things correctly on
my end, or (b) there's another proper way to convey desired SO_TIMEOUT
and/or connect timeout on a per-request basis?

Thanks!

public class HttpTimeoutExample {
    private ThreadSafeClientConnManager connMgr;
    private HttpClient httpClient;

    public HttpTimeoutBugExample(int connTtlMs, int maxTotal, int
defaultMaxPerRoute) {
        this.defaultConnectionTimeout = defaultConnectionTimeout;
        this.defaultSoTimeout = defaultSoTimeout;

        connMgr = new
ThreadSafeClientConnManager(SchemeRegistryFactory.createDefault(),
connTtlMs, TimeUnit.MILLISECONDS);
        connMgr.setMaxTotal(maxTotal);
        connMgr.setDefaultMaxPerRoute(defaultMaxPerRoute);

        httpClient = new DefaultHttpClient(connMgr);
    }

    public void doGetWithTimeout(String someUrl, boolean handleRedirects,
int timeLimitMs) {
        HttpUriRequest httpRequest = new HttpGet(someUrl);

        BasicHttpContext httpContext = new BasicHttpContext();
        httpContext.setAttribute(ClientPNames.HANDLE_REDIRECTS,
Boolean.valueOf(handleRedirects));

        // Set timeouts...these are being ignored!
        httpContext.setAttribute(CoreConnectionPNames.CONNECTION_TIMEOUT,
Integer.valueOf(timeLimitMs));
        httpContext.setAttribute(CoreConnectionPNames.SO_TIMEOUT,
Integer.valueOf(timeLimitMs));

        HttpResponse httpResponse = httpClient.execute(httpRequest,
httpContext);
        HttpEntity httpEntity = httpResponse.getEntity();
        try {
            // read the response entity
        } finally {
            EntityUtils.consume(httpEntity);
        }
    }
}

Re: Timeouts not being obeyed

Posted by Dan Checkoway <dc...@gmail.com>.
Oleg,

I just wanted to let you know that -- no surprise -- your advice worked
perfectly.  I changed these two lines:

        httpContext.setAttribute(CoreConnectionPNames.CONNECTION_TIMEOUT,
Integer.valueOf(timeLimitMs));
        httpContext.setAttribute(CoreConnectionPNames.SO_TIMEOUT,
Integer.valueOf(timeLimitMs));

to:


httpRequest.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
Integer.valueOf(timeLimitMs));

httpRequest.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT,
Integer.valueOf(timeLimitMs));

...and I now catch this perfectly as expected:

java.net.SocketTimeoutException: Read timed out

Thanks again, Oleg!

On Fri, Apr 13, 2012 at 6:08 PM, Dan Checkoway <dc...@gmail.com> wrote:

> Thanks very much, Oleg.  I'll give that a shot!
>
>
> On Fri, Apr 13, 2012 at 2:07 PM, Oleg Kalnichevski <ol...@apache.org>wrote:
>
>> On Thu, 2012-04-12 at 21:40 -0400, Dan Checkoway wrote:
>> > Hello,
>> >
>> > I'm a long-time very happy user of HttpClient.  I have bumped into what
>> I
>> > believe is a bug...but it's possible I'm just abusing the API and
>> missing
>> > something simple.  :-)
>> >
>> > I use ThreadSafeClientConnManager and a single shared instance of
>> > DefaultHttpClient to manage a persistent HTTP connection pool.  It works
>> > exactly as I need it to -- except it's not obeying timeouts.
>> >
>> > What I need to do is set an arbitrary timeout for each individual
>> request.
>> > That is, I can't just set one timeout up front when I create the
>> > HttpClient.  The timeout I need to use varies from request to request.
>> >
>> > The way I'm *trying* to convey the timeout is by setting attributes on
>> the
>> > HttpContext as shown in the code below...but what I'm experiencing is
>> that
>> > my timeouts are being ignored.
>> >
>> > I believe the root of the problem is that AbstractHttpClient is using
>> its
>> > determineParams() method, but that's completely disregarding the params
>> > which may have been set on the context.
>> >
>> > Can you let me know if (a) this is a bug and I'm doing things correctly
>> on
>> > my end, or (b) there's another proper way to convey desired SO_TIMEOUT
>> > and/or connect timeout on a per-request basis?
>> >
>> > Thanks!
>> >
>>
>> Dan
>>
>> The HTTP context is intended for sharing mutable runtime data. What you
>> want is to set HTTP parameters at the request level by using
>> HttpUriRequest#getParams()
>>
>> Hope this helps
>>
>> Oleg
>>
>>
>> > public class HttpTimeoutExample {
>> >     private ThreadSafeClientConnManager connMgr;
>> >     private HttpClient httpClient;
>> >
>> >     public HttpTimeoutBugExample(int connTtlMs, int maxTotal, int
>> > defaultMaxPerRoute) {
>> >         this.defaultConnectionTimeout = defaultConnectionTimeout;
>> >         this.defaultSoTimeout = defaultSoTimeout;
>> >
>> >         connMgr = new
>> > ThreadSafeClientConnManager(SchemeRegistryFactory.createDefault(),
>> > connTtlMs, TimeUnit.MILLISECONDS);
>> >         connMgr.setMaxTotal(maxTotal);
>> >         connMgr.setDefaultMaxPerRoute(defaultMaxPerRoute);
>> >
>> >         httpClient = new DefaultHttpClient(connMgr);
>> >     }
>> >
>> >     public void doGetWithTimeout(String someUrl, boolean
>> handleRedirects,
>> > int timeLimitMs) {
>> >         HttpUriRequest httpRequest = new HttpGet(someUrl);
>> >
>> >         BasicHttpContext httpContext = new BasicHttpContext();
>> >         httpContext.setAttribute(ClientPNames.HANDLE_REDIRECTS,
>> > Boolean.valueOf(handleRedirects));
>> >
>> >         // Set timeouts...these are being ignored!
>> >
>> httpContext.setAttribute(CoreConnectionPNames.CONNECTION_TIMEOUT,
>> > Integer.valueOf(timeLimitMs));
>> >         httpContext.setAttribute(CoreConnectionPNames.SO_TIMEOUT,
>> > Integer.valueOf(timeLimitMs));
>> >
>> >         HttpResponse httpResponse = httpClient.execute(httpRequest,
>> > httpContext);
>> >         HttpEntity httpEntity = httpResponse.getEntity();
>> >         try {
>> >             // read the response entity
>> >         } finally {
>> >             EntityUtils.consume(httpEntity);
>> >         }
>> >     }
>> > }
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
>> For additional commands, e-mail: httpclient-users-help@hc.apache.org
>>
>>
>

Re: Timeouts not being obeyed

Posted by Dan Checkoway <dc...@gmail.com>.
Thanks very much, Oleg.  I'll give that a shot!

On Fri, Apr 13, 2012 at 2:07 PM, Oleg Kalnichevski <ol...@apache.org> wrote:

> On Thu, 2012-04-12 at 21:40 -0400, Dan Checkoway wrote:
> > Hello,
> >
> > I'm a long-time very happy user of HttpClient.  I have bumped into what I
> > believe is a bug...but it's possible I'm just abusing the API and missing
> > something simple.  :-)
> >
> > I use ThreadSafeClientConnManager and a single shared instance of
> > DefaultHttpClient to manage a persistent HTTP connection pool.  It works
> > exactly as I need it to -- except it's not obeying timeouts.
> >
> > What I need to do is set an arbitrary timeout for each individual
> request.
> > That is, I can't just set one timeout up front when I create the
> > HttpClient.  The timeout I need to use varies from request to request.
> >
> > The way I'm *trying* to convey the timeout is by setting attributes on
> the
> > HttpContext as shown in the code below...but what I'm experiencing is
> that
> > my timeouts are being ignored.
> >
> > I believe the root of the problem is that AbstractHttpClient is using its
> > determineParams() method, but that's completely disregarding the params
> > which may have been set on the context.
> >
> > Can you let me know if (a) this is a bug and I'm doing things correctly
> on
> > my end, or (b) there's another proper way to convey desired SO_TIMEOUT
> > and/or connect timeout on a per-request basis?
> >
> > Thanks!
> >
>
> Dan
>
> The HTTP context is intended for sharing mutable runtime data. What you
> want is to set HTTP parameters at the request level by using
> HttpUriRequest#getParams()
>
> Hope this helps
>
> Oleg
>
>
> > public class HttpTimeoutExample {
> >     private ThreadSafeClientConnManager connMgr;
> >     private HttpClient httpClient;
> >
> >     public HttpTimeoutBugExample(int connTtlMs, int maxTotal, int
> > defaultMaxPerRoute) {
> >         this.defaultConnectionTimeout = defaultConnectionTimeout;
> >         this.defaultSoTimeout = defaultSoTimeout;
> >
> >         connMgr = new
> > ThreadSafeClientConnManager(SchemeRegistryFactory.createDefault(),
> > connTtlMs, TimeUnit.MILLISECONDS);
> >         connMgr.setMaxTotal(maxTotal);
> >         connMgr.setDefaultMaxPerRoute(defaultMaxPerRoute);
> >
> >         httpClient = new DefaultHttpClient(connMgr);
> >     }
> >
> >     public void doGetWithTimeout(String someUrl, boolean handleRedirects,
> > int timeLimitMs) {
> >         HttpUriRequest httpRequest = new HttpGet(someUrl);
> >
> >         BasicHttpContext httpContext = new BasicHttpContext();
> >         httpContext.setAttribute(ClientPNames.HANDLE_REDIRECTS,
> > Boolean.valueOf(handleRedirects));
> >
> >         // Set timeouts...these are being ignored!
> >         httpContext.setAttribute(CoreConnectionPNames.CONNECTION_TIMEOUT,
> > Integer.valueOf(timeLimitMs));
> >         httpContext.setAttribute(CoreConnectionPNames.SO_TIMEOUT,
> > Integer.valueOf(timeLimitMs));
> >
> >         HttpResponse httpResponse = httpClient.execute(httpRequest,
> > httpContext);
> >         HttpEntity httpEntity = httpResponse.getEntity();
> >         try {
> >             // read the response entity
> >         } finally {
> >             EntityUtils.consume(httpEntity);
> >         }
> >     }
> > }
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
> For additional commands, e-mail: httpclient-users-help@hc.apache.org
>
>

Re: Timeouts not being obeyed

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Thu, 2012-04-12 at 21:40 -0400, Dan Checkoway wrote:
> Hello,
> 
> I'm a long-time very happy user of HttpClient.  I have bumped into what I
> believe is a bug...but it's possible I'm just abusing the API and missing
> something simple.  :-)
> 
> I use ThreadSafeClientConnManager and a single shared instance of
> DefaultHttpClient to manage a persistent HTTP connection pool.  It works
> exactly as I need it to -- except it's not obeying timeouts.
> 
> What I need to do is set an arbitrary timeout for each individual request.
> That is, I can't just set one timeout up front when I create the
> HttpClient.  The timeout I need to use varies from request to request.
> 
> The way I'm *trying* to convey the timeout is by setting attributes on the
> HttpContext as shown in the code below...but what I'm experiencing is that
> my timeouts are being ignored.
> 
> I believe the root of the problem is that AbstractHttpClient is using its
> determineParams() method, but that's completely disregarding the params
> which may have been set on the context.
> 
> Can you let me know if (a) this is a bug and I'm doing things correctly on
> my end, or (b) there's another proper way to convey desired SO_TIMEOUT
> and/or connect timeout on a per-request basis?
> 
> Thanks!
> 

Dan

The HTTP context is intended for sharing mutable runtime data. What you
want is to set HTTP parameters at the request level by using
HttpUriRequest#getParams()

Hope this helps

Oleg


> public class HttpTimeoutExample {
>     private ThreadSafeClientConnManager connMgr;
>     private HttpClient httpClient;
> 
>     public HttpTimeoutBugExample(int connTtlMs, int maxTotal, int
> defaultMaxPerRoute) {
>         this.defaultConnectionTimeout = defaultConnectionTimeout;
>         this.defaultSoTimeout = defaultSoTimeout;
> 
>         connMgr = new
> ThreadSafeClientConnManager(SchemeRegistryFactory.createDefault(),
> connTtlMs, TimeUnit.MILLISECONDS);
>         connMgr.setMaxTotal(maxTotal);
>         connMgr.setDefaultMaxPerRoute(defaultMaxPerRoute);
> 
>         httpClient = new DefaultHttpClient(connMgr);
>     }
> 
>     public void doGetWithTimeout(String someUrl, boolean handleRedirects,
> int timeLimitMs) {
>         HttpUriRequest httpRequest = new HttpGet(someUrl);
> 
>         BasicHttpContext httpContext = new BasicHttpContext();
>         httpContext.setAttribute(ClientPNames.HANDLE_REDIRECTS,
> Boolean.valueOf(handleRedirects));
> 
>         // Set timeouts...these are being ignored!
>         httpContext.setAttribute(CoreConnectionPNames.CONNECTION_TIMEOUT,
> Integer.valueOf(timeLimitMs));
>         httpContext.setAttribute(CoreConnectionPNames.SO_TIMEOUT,
> Integer.valueOf(timeLimitMs));
> 
>         HttpResponse httpResponse = httpClient.execute(httpRequest,
> httpContext);
>         HttpEntity httpEntity = httpResponse.getEntity();
>         try {
>             // read the response entity
>         } finally {
>             EntityUtils.consume(httpEntity);
>         }
>     }
> }



---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org