I usually post about HTTP stuff on Twitter - you can follow me there:

1. Overview

This tutorial will show how to configure a timeout with the Apache HttpClient 4.

If you want to dig deeper and learn other cool things you can do with the HttpClient – head on over to the main HttpClient tutorial.

2. Configure Timeouts via raw String parameters

The HttpClient comes with a lot of configuration parameters – and all of these can be set in a generic, map-like manner.

There are 3 timeout parameters to configure:

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
// httpParams.setParameter(ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));

A quick note is that the last parameter – the connection manager timeout – is commented out when using the 4.3.0 or 4.3.1 versions, because of this JIRA (due in 4.3.2).

3. Configure Timeouts via the API

The more important of these parameters – namely the first two – can also be set via a more type safe API:

DefaultHttpClient httpClient = new DefaultHttpClient();

int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(httpParams, timeout * 1000); // http.socket.timeout

The third parameter doesn’t have a custom setter in HttpConnectionParams, and it will still need to be set manually via the setParameter method.

4. Configure Timeouts using the new 4.3 Builder

The fluent, builder API introduced in 4.3 provides the right way to set timeouts at a high level:

int timeout = 5;
RequestConfig config = RequestConfig.custom()
  .setConnectTimeout(timeout * 1000)
  .setConnectionRequestTimeout(timeout * 1000)
  .setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = 
  HttpClientBuilder.create().setDefaultRequestConfig(config).build();

That is the recommended way of configuring all three timeouts in a type-safe and readable manner.

5. Timeout Properties Explained

Now, let’s explain what these various types of timeouts mean:

  • the Connection Timeout (http.connection.timeout) – the time to establish the connection with the remote host
  • the Socket Timeout (http.socket.timeout) – the time waiting for data – after the connection was established; maximum time of inactivity between two data packets
  • the Connection Manager Timeout (http.connection-manager.timeout) – the time to wait for a connection from the connection manager/pool

The first two parameters – the connection and socket timeouts – are the most important, but setting a timeout for obtaining a connection is definitely important in high load scenarios, which is why the third parameter shouldn’t be ignored.

6. Using the HttpClient

After being configured, the client can not be used to perform HTTP requests:

HttpGet getMethod = new HttpGet("http://host:8080/path");
HttpResponse response = httpClient.execute(getMethod);
System.out.println("HTTP Status of response: " + response.getStatusLine().getStatusCode());

With the previously defined client, the connection to the host will time out in 5 seconds, and if the connection is established but no data is received, the timeout will also be 5 additional seconds.

Note that the connection timeout will result in a org.apache.http.conn.ConnectTimeoutException being thrown, while socket timeout will result in a java.net.SocketTimeoutException.

7. Hard Timeout

While setting timeouts on establishing the HTTP connection and not receiving data is very useful, sometimes we need to set a hard timeout for the entire request.

For example the download of a potentially large file fits into this category – in this case, the connection may be successfully established, data may be consistently coming through, but we still need to ensure that the operation doesn’t go over some specific time threshold.

HttpClient doesn’t have any configuration that allows us to set an overall timeout for a request; it does however provide abort functionality for requests, so we can leverage that mechanism to implement a simple timeout mechanism:

HttpGet getMethod = new HttpGet("http://localhost:8080/spring-security-rest-template/api/bars/1");

int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
    @Override
    public void run() {
        if (getMethod != null) {
            getMethod.abort();
        }
    }
};
new Timer(true).schedule(task, hardTimeout * 1000);

HttpResponse response = httpClient.execute(getMethod);
System.out.println("HTTP Status of response: " + response.getStatusLine().getStatusCode());

We’re making use of the java.util.Timer and java.util.TimerTask to set up a simple delayed task which aborts the HTTP GET request after a 5 seconds hard timeout.

8. Timeout and DNS Round Robin – something to be aware of

It is quite common that some larger domains will be using a DNS round robin configuration – essentially having the same domain mapped to multiple IP addresses. This introduces a new challenge for timeout against such a domain, simply because of the way HttpClient will try to connect to that domain that times out:

  • HttpClient gets the list of IP routes to that domain
  • it tries the first one – that times out (with the timeouts we configure)
  • it tries the second one – that also times out
  • and so on …

So, as you can see – the overall operation will not time out when we expect it to. Instead – it will time out when all the possible routes have timed out, and what it more – this will happen completely transparently for the client (unless you have your log configured at the DEBUG level). Here is a simple example you can run and replicate this issue:

int timeout = 3;
RequestConfig config = RequestConfig.custom().
  setConnectTimeout(timeout * 1000).
  setConnectionRequestTimeout(timeout * 1000).
  setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();

HttpGet request = new HttpGet("http://www.google.com:81");
response = client.execute(request);

You will notice the retrying logic with a DEBUG log level:

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.212:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator - 
 Connect to www.google.com/173.194.34.212:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.208:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator - 
 Connect to www.google.com/173.194.34.208:81 timed out. Connection will be retried using another IP address

DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.google.com/173.194.34.209:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator - 
 Connect to www.google.com/173.194.34.209:81 timed out. Connection will be retried using another IP address
...

9. Conclusion

This tutorial discussed how to configure the various types of timeouts available for an HttpClient. It also illustrated a simple mechanism for hard timeout of an ongoing http connection.

The implementation of these examples can be found in the github project – this is an Eclipse based project, so it should be easy to import and run as it is.

I usually post about HTTP stuff on Twitter - you can follow me there:


  • Biniam A.

    Great article! Thank you so much. I found all the answers I was looking for.

    For subsection “Configure Timeouts via the API”, the 3rd parameter can be set using:

    httpParams.setIntParameter(“http.connection.timeout”, connectionTimeout);

    • That particular section deals with the higher level API with which we can avoid using the raw property – mainly using HttpConnectionParams – your suggestion will work, but it’s not using the high level API. Additionally, that method is already described in Subsection 2.
      Thanks,
      Eugen.

  • VinMap

    I’ve tried this on Windows 7; tried steps 4-7 using httpclient 4.3.3 and httpcore 4.3.2, but it doesn’t work. For steps 4-6, I get no timeouts and no exceptions occur until 15 seconds later (this exception occurs regardless of whether I have implemented steps 4-6, when I have set each timeout to 2 seconds (i.e., 1000). Also, i also implemented step 7 for a hard timeout of 2 seconds, but it doesn’t abort. The abort() does execute (I know because I also placed a print statement in the run() function), however the execute() still runs for a total of 15 seconds (i.e., it does not exit upon 2 seconds) and does not break out of it. Any ideas? Basically, I am trying to simulate no internet connection by just flipping the network switch to off on my PC. When I do this, it doesn’t timeout after 2 seconds as I have tried to using the above code. Please let me know if you have any ideas. thanks. You can email me directly, which would be preferable. Thanks for any help.

    • Hey Vin, thanks for pointing this out. The issue is a bit tricky – here’s what’s happening.
      When you’re working against a raw IP, then that’s your single route and if that times out, then there’s no other route to retry and the timeout works.
      However, if you’re working against a domain, there may be multiple routes to that domain, via multiple IPs – in which case, the client will go through all of them before finally giving up.
      So – what that means is – say you have 3 routes to try, and you set you timeout to 2 seconds – you’ll actually have to wait for 6 seconds before you actually see the timeout. You can see the low level details of this behaviour here: HttpClientConnectionOperator.connect.
      So – with this in mind, you’ll have to either use an IP if you can, or use the hard timeout.
      Hope this helps. I’ll also try to update the article since this is a good thing to keep in mind.
      Cheers,
      Eugen.

  • xingxiudong

    maximum time of inactivity between two data packets

    Not unstanded….
    Please say more….

    • Hey Xing – so, that particular parameter controls the low level timeout between two consecutive data packets on the socket. Going into what a socket or a data packet are is a bit out of scope for this article, but if you do want to go deeper, reading about networking and – for instance – how TCP works is a good place to start, since HTTP runs over it. Hope it helps and let me know if you need anything else about this particular timeout config. Cheers,
      Eugen.

  • shellbye

    Great article. I still don’t know the meaning of connectionRequestTimeout, can you explain it?

    • The Connection Request Timeout is the timeout until a connection with the server is established. Cheers,
      Eugen.

      • shellbye

        So the different between the Connection Request Timeout and the Connection Timeout is the former means the server who send the request and the later means the “remote” server who will receive the request?

  • Kisna

    Just a bit confusing, with the pooled Keep Alive Http client assuming you, say, you always have enough connections pooled “by warm up” (not sure how you do it though) and you never go beyond, you should never be able to worry about connection time out isn’t it?

    Basically, how would you really control the time out: i.e., time to get any “response back and not to make a connection” which is the use case for most people isn’t it? i.e., stop the request if you don’t get a response back within certain time?

    • Hey Kisna,
      Having a connection available and having that connection timeout are different concerns. Yes, the connection may be available, but that doesn’t mean it won’t time out. So – yes, I roughly agree with the definition of timeout – and the pool doesn’t change that. If you, as a client, won’t get a response back within the timeout timeframe – the connection will be stopped. Hope that helps clarify things. Cheers,
      Eugen.

  • kars

    Hey, very good article.
    When we issue timeout from client, whether client will send any request to server about it.
    At the same time, whether server will get to know whether client has timed out

    • Hey Kars – I’m not sure I follow what you’re asking here. Can you go into more detail? Cheers,
      Eugen.

      • kars

        Thanks for your response.

        I have a HTTP client and app server. If I set socket timeout on client, internally what happens.
        Whether client will abort the connection when socket timeout happens
        Or
        Whether server won’t be aware that client has timed out
        Is there any difference between abort a connection and timing out a connection from http client

        Thanks

        • When the client times out, the server won’t be aware of it (unless you really implement some custom, manual mechanism to make it aware). Now – yes – there is a different between aborting a connection and letting that connection time out. But – ultimately – you still need to clean up resources, return that connection the pool (if you’re using a pool), etc – so it’s not very different.

          • kars

            Thanks for helping me to understand timeouts.

  • Ken DeLong

    I wish the documentation was this clear…

  • Kisna

    Eugen, slightly off the topic, did you talk about why HttpClient enabled staleConnectionCheck by default adding to the overhead of using pooled connections in the first place (disabled only recently in 4.4), this is besides using keep alives (assuming server supports) and a custom idle connection check handler and of course retries on socket connection errors (when server side decides to close without notifying via keep-alive headers).

    • Hey Kisna – no, I haven’t – but it definitely seems like an interesting topic to explore. Have you checked out the “Write for Baeldung” page – this one seems like an interesting potential topic for that. Cheers,
      Eugen.

  • John McAlister

    The “hard timeout” example uses “abort()”, which is part of a deprecated interface in 4.3+ The API indicates that HttpExecutionAware is the interface to use, and that seems to b tied to “cancel()” in the Cancelable interface – but the documentation in this entire area is quite thin (and missing for “cancel()”).

    Can you provide an example for 4.3+ that does not use the deprecated AbortableHttpRequest interface?

    Thanks!

    • Added it to my TODO list – I’ll update this thread when it’s ready. Cheers,
      Eugen.

    • Hey John,
      On a closer look it actually seems that nothing’s deprecated in that example (the codebase is using 4.5, so it’s definitely 4.3+).
      Let me know if you notice any deprecation that I’m missing over in the Github example. Cheers,
      Eugen.

  • Mike

    very useful! Thank you:)

  • Cory Bradshaw

    Need to update to removed deprecated APIs.

    private static final int timeout=5000;

    private static final RequestConfig requestConfig = RequestConfig.custom()
    .setSocketTimeout(timeout)
    .setConnectTimeout(timeout)
    .setConnectionRequestTimeout(timeout)
    .build();


    CloseableHttpClient httpclient = HttpClients.custom().setKeepAliveStrategy(connectionKeepAliveStrategy).setConnectionManager(cm).set.build();

    try{
    httpPost.setConfig(requestConfig); //Or your choice of Http Methods

    • Hey Cory – can you be a bit more specific as to what part of that example is deprecated? Cheers,
      Eugen.

  • Patan

    Nice article. Do you have any suggestions to handle issue mentioned at point 8

    • Hey Patan – I haven’t really looked into it, since it’s somewhat of a corner case. There may be a way to configure the timeout to consider the host, not the IP – I just have looked to see if there is or not. For these kinds of more advanced usecases, I’d suggest either the official mailing group, or StackOverflow.
      Cheers,
      Eugen.