Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use RestTemplate efficiently in Multithreaded environment?

Tags:

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;     } } 
like image 271
AKIWEB Avatar asked Jan 20 '14 19:01

AKIWEB


People also ask

Is RestTemplate thread-safe?

RestTemplate is thread-safe once constructed. Objects of the RestTemplate class do not change any of their state information to process HTTP: the class is an instance of the Strategy design pattern.

Is RestTemplate outdated?

RestTemplate provides a synchronous way of consuming Rest services, which means it will block the thread until it receives a response. RestTemplate is deprecated since Spring 5 which means it's not really that future proof.

What can I use instead of RestTemplate?

WebClient is part of Spring WebFlux and is intended to replace the classic RestTemplate. Compared to RestTemplate , WebClient has a more functional feel and is fully reactive. Since Spring 5.0, RestTemplate is deprecated.

Is RestTemplate asynchronous?

RestTemplate uses Java Servlet API and is therefore synchronous and blocking. Conversely, WebClient is asynchronous and will not block the executing thread while waiting for the response to come back.


2 Answers

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.

like image 154
Sotirios Delimanolis Avatar answered Oct 11 '22 10:10

Sotirios Delimanolis


I have my multi-thread-safe singleton REST template wired like this in spring:

<bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams" id="httpConnectionManagerParams">     <property name="connectionTimeout" value="10000"/> </bean> <bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager" id="httpConnectionManager">     <property name="params" ref="httpConnectionManagerParams"/> </bean> <bean class="org.apache.commons.httpclient.params.HttpClientParams" id="httpClientParams">     <property name="authenticationPreemptive" value="true"/>     <property name="soTimeout" value="10000"/> </bean> <bean class="org.apache.commons.httpclient.HttpClient" id="httpClient">     <constructor-arg ref="httpClientParams"/>     <constructor-arg ref="httpConnectionManager"/> </bean> <bean class="org.springframework.http.client.CommonsClientHttpRequestFactory" id="httpClientFactory">     <constructor-arg ref="httpClient"/> </bean> <bean class="org.springframework.security.oauth.consumer.client.OAuthRestTemplate" id="restTemplate">     <constructor-arg ref="httpClientFactory"/>     <constructor-arg ref="myResource"/>     <property name="messageConverters">         <list>             <ref bean="marshallingHttpMessageConverter"/>         </list>     </property> </bean> 

Please note I'm using an OAuthRestTemplate, and myResource refers to the oauth resource stuff which I've omitted as it's not relevant. Instead of an OAuthRestTemplate you could just as easily use a org.springframework.web.client.RestTemplate http://docs.spring.io/spring/docs/3.2.4.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

like image 29
Taylor Avatar answered Oct 11 '22 10:10

Taylor