12

I am working on a project in which I need to make a HTTP URL call to my server which is running Restful Service which returns back the response as a JSON String.

Below is my main code which is using the future and callables:

public class TimeoutThreadExample {

    private ExecutorService executor = Executors.newFixedThreadPool(10);
    private RestTemplate restTemplate = new RestTemplate();

    public String getData() {
        Future<String> future = executor.submit(new Task(restTemplate));
        String response = null;

        try {
            response = future.get(500, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return response;
    }
}

Below is my Task class which implements the Callable interface and uses the RestTemplate:

class Task implements Callable<String> {

    private RestTemplate restTemplate;

    public Task(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String call() throws Exception {

        String url = "some_url";
        String response = restTemplate.getForObject(url, String.class);

        return response;
    }
}

Problem Statement:

As you can see above, I am using default way of executing the URL using RestTemplate which doesn't use any Http Request timeout so that means internally it is using -1 as the read and connection timeout.

Now what I am looking to do is, I want to set up Http Request timeout using RestTemplate in my above code efficiently. And I am not sure which class I need to use for that, I can see HttpComponentsClientHttpRequestFactory and SimpleClientHttpRequestFactory so not sure which one I need to use?

Any simple example basis on my above code will help me understand better on how to set the Http Request timeout using RestTemplate.

And also does my Http Request timeout value should be less than future timeout value?

  • HttpComponentsClientHttpRequestFactory vs SimpleClientHttpRequestFactory. Which one to use?
  • Does my Http Request timeout value should be less than future timeout value?
AKIWEB
  • 19,008
  • 67
  • 180
  • 294

2 Answers2

15

By default RestTemplate uses SimpleClientHttpRequestFactory which depends on default configuration of HttpURLConnection.

You can configure them by using below attributes:

-Dsun.net.client.defaultConnectTimeout=TimeoutInMiliSec 
-Dsun.net.client.defaultReadTimeout=TimeoutInMiliSec 

If you want to use HttpComponentsClientHttpRequestFactory - it has a connection pooling configuration which SimpleClientHttpRequestFactory does not have.

A sample code for using HttpComponentsClientHttpRequestFactory:

public class TimeoutThreadExample {

    private ExecutorService executor = Executors.newFixedThreadPool(10);
    private static final RestTemplate restTemplate = createRestTemplate();

    private static RestTemplate createRestTemplate(){
       HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
       requestFactory.setReadTimeout(READ_TIME_OUT);
       requestFactory.setConnectTimeout(CONNECTION_TIME_OUT);
       return new RestTemplate(requestFactory);
     }

    public String getData() {
        Future<String> future = executor.submit(new Task(restTemplate));
        String response = null;

        try {
            response = future.get(500, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return response;
    }
}
Jama A.
  • 15,680
  • 10
  • 55
  • 88
  • Thanks for suggestion. By any chance do you know which one we are suppose to use? Or we can use any one of those two? And also how would I use `requestFactory` in my above code base efficiently? I understand from your example how to use it but where do I fit `requestFactory` in my above code base since I am using DI to pass the RestTemplate. – AKIWEB Sep 07 '14 at 01:34
  • It is up to you, but personally in our large scale projects we have used HttpComponentsClientHttpRequestFactory. But I guess there should not be any problem with both approaches. With `HttpComponentsClientHttpRequestFactory` you can configure more options using your own `HttpClient`. For using in your codebase, just pass the `HttpComponentsClientHttpRequestFactory` instance like the code I wrote at the end of my answer – Jama A. Sep 07 '14 at 02:02
  • Sure, I am thinking of using `HttpComponentsClientHttpRequestFactory`. I didn't understand which instance you want me to pass? If you can provide an example basis on my code base then I would understand better what do you mean by that? – AKIWEB Sep 07 '14 at 02:10
  • Please see the updated answer, you need to create a singleton shared instance of `RestTemplate` since its thread-safe and heavy to be created. PS: I've not tested the code. – Jama A. Sep 07 '14 at 02:22
  • Thanks for edit. Now I understand clearly what you meant earlier. One last question, what is the difference between `READ Timeout` vs `Connection Timeout` here? – AKIWEB Sep 07 '14 at 02:23
  • connection timeout is about initial connection handshake, read timeout is = if you block the response in the middle of processing the response. ReadTimout is here - https://hc.apache.org/httpclient-3.x/apidocs/org/apache/commons/httpclient/params/HttpConnectionParams.html#getSoTimeout() – Jama A. Sep 07 '14 at 02:30
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/60767/discussion-between-akiweb-and-jama-jurayevich). – AKIWEB Sep 07 '14 at 02:36
  • I'm using `HttpComponentsClientHttpRequestFactory` after I got issue with `SimpleClientHttpRequestFactory` while extracting the 401 exception response body. Below is my sample code, I'm using defaults with `HttpComponentsClientHttpRequestFactory` and no custom configurations like timeout and custom custom `HTTPClient` `@Bean public RestTemplate restTemplate() { RestTemplate template = new RestTemplate(); template.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); return template; }` – Abhilash Jun 27 '20 at 12:08
1

SimpleClientHttpRequestFactory uses the standard JDK's HTTP library, and hence does not support methods like HttpMethod.PATCH. So it's better to use HttpComponentsClientHttpRequestFactory now than change it later when you have to.

Anushri HV
  • 51
  • 3