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; } }
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.
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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With