How to use RestTemplate efficiently in Multithreaded environment?

AKIWEB picture AKIWEB · Jan 20, 2014 · Viewed 53.6k times · Source

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);

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

        try {
            response = future.get(100, 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 = new RestTemplate();

    public String call() throws Exception {

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

        return response;
    }
}

And now I have below code in another class DemoTest which calls the getData method in TimeoutThreadExample class 5000 times sequentially -

public class DemoTest { 
   public static void main(String[] args) {

        TimeoutThreadExample bc = new TimeoutThreadExample();

        for (int i = 0; i <= 5000; i++) {
        //  TimerTest timer = TimerTest.getInstance(); // line 1
            bc.getData();
        //  timer.getDuration(); // line 2
        }
    }
}       

So my question is should RestTemplate be static here in my Task class as if I see it correctly, I am recreating the whole connection pool for each request in RestTemplate which is not the right way I guess..

NOTE: If I am making RestTemplate static, then I see better performance end to end as compared to non static RestTemplate after commenting out line1 and line2 in DemoTest class which measures the performance.

In general what is the right way to use RestTemplate in Multithreading environment? Currently I am calling sequentially getData method 5000 times one by one but some customer will call it in a multithreaded way so need to know what is the best way to have RestTemplate in a multithreaded environment..

May be to use ConnectionFactory in the RestTemplate constructor? Any thoughts?

UPDATE:-

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(100, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return response;
    }
}

And below my TaskClass -

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;
    }
}

Answer

Sotirios Delimanolis picture Sotirios Delimanolis · Jan 20, 2014

Correct me if I didn't understand your question. It seems very similar to the previous one here.

There, we determined that RestTemplate is thread-safe. There is therefore no reason not to share it wherever it makes sense to, ie. wherever you are using it in the same way. Your example seems like the perfect place to do so.

As you stated, recreating a new instance of RestTemplate for each Task instance is wasteful.

I would create the RestTemplate in TimeoutThreadExample and pass it to the Task as a constructor argument.

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;
    }
}

This way you share the RestTemplate instance between all your Task objects.

Note that RestTemplate uses SimpleClientHttpRequestFactory to create its connections.