Is RestTemplate thread safe?
RestTemplate
is thread safe (emphasis added):
Conceptually, it is very similar to the
JdbcTemplate
,JmsTemplate
, and the various other templates found in the Spring Framework and other portfolio projects. This means, for instance, that theRestTemplate
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, rather than being like a connection object. With no state information, there is no possibility of different threads corrupting or racing state information if they share a RestTemplate
object. This is why it is possible for threads to share these objects.
If you examine the source code of RestTemplate
you will see that it does not use synchronized
methods or volatile
fields to provide thread-safety after construction of the object. So it is not safe to modify a RestTemplate
object after construction. In particular, it is unsafe to add a message converter.
To provide it with a list of message converters you must do one of the following:
- Use the
RestTemplate(List<HttpMessageConverter<?>> messageConverters)
constructor. As the internal list ofmessageConverters
isfinal
, this safely publishes the list of message converters. - Use the
setMessageConverters(List<HttpMessageConverter<?>> messageConverters)
mutator and then safely-publish the changedRestTemplate
object. Using a Spring bean definition that has a<property name="messageConverters"><list>...
does this, as the bean will be safely published by the thread setting up the container in most practical use cases. - Use
List.add
on the reference returned bygetMessageConverters()
and then safely publish the changedRestTemplate
object. However, the documentation forRestTemplate
does not explicitly state that it returns a reference that can be used to alter the list of message converters. The current implementation does, but possibly the implementation might be changed to return aCollections.unmodifiableList
or a copy of the list. So it might be better not to change it this way.
Note that the first case is the only means of setting up the message converters when constructing the object, so it is correct to say that it "is thread safe once constructed".
The class is part of the Spring Framework, so in almost all practical cases objects of the class will be set up as part of a Spring Application Context, using the first (dependency injection using a constructor) or second (dependency injection using a setter) methods, and so would be guaranteed to be safely published to multiple threads.
How to test thread-safety of RestTemplate?
First of all it is not necessary to call the actual service. You can write your own service and call it simultaneously and stall it or whatever your plan is.
Second - it doesn't make sense to test code outside of your code base. RestTemplate
is thread-safe - no need to prove that.
That being said - you can create a bunch of threads, inside of which you invoke the same calls to your single restTemplate instance. You can sleep the threads for some seconds to be "sure" that the restTemplates call will be fired simultaneously.
Go one abstraction level higher and use ExecutorService
(e.g. Executors.newFixedThreadPool(N);
) and submit callables to it (that call the same restTemplate instance).
Some external to JDK options are JMeter and concurrent-junit.
How to efficiently use RestTemplate in multithreading application?
RestTemplate
is thread safe in Spring. So what you may want to do is create only one instance of RestTemplate
in your application and share it across multiple threads. This is of course assuming that you will use the same HTTP properties(like timeout,set alive etc) for all. In case you need to change the connection properties you can create a pool at app start of RestTemplate
objects and use this to inject the RestTemplate instance to the caller class.
How to use RestTemplate efficiently in Multithreaded environment?
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.
Is it better to keep RestTemplate in memory than creating new RestTemplate with every request?
RestTemplate
is designed to be thread-safe and reusable.
RestTemplate
is just a facade that doesn't perform actual network operations. It delegates network operations to a HTTP client implementation. This HTTP client implementation can be expensive to create and often handles network level optimizations e.g. caching of connections per origin. You usually want to reuse this HTTP client implementation and this can be achieved by reusing RestTemplate
.
Normally you would create RestTemplate
as a singleton bean within Spring context. Especially in Spring Boot this is important and you shouldn't use new RestTemplate()
syntax because it will not inject all registered customizers.
RestTemplate should be static globally declared?
It doesn't matter either way, static
or instance.
RestTemplate
's methods for making HTTP requests are thread safe so whether you have a RestTemplate
instance per Task
instance or a shared instance for all Task
instances is irrelevant (except for garbage collection).
Personally, I would create the RestTemplate
outside the Task
class and pass it as an argument to a Task
constructor. (Use Inversion of Control whenever possible.)
Related Topics
Why Are Data Transfer Objects (Dtos) an Anti-Pattern
Is the Order Guaranteed for the Return of Keys and Values from a Linkedhashmap Object
What Objects How to Inject Using the @Context Annotation
What Is the Breakdown for Java's Lambda Syntax
Docker: Combine Multiple Images
How to Customise the Jackson JSON Mapper Implicitly Used by Spring Boot
Using == Operator in Java to Compare Wrapper Objects
Convert Escaped Unicode Character Back to Actual Character
Providing Input/Subcommands to Command Executed Over Ssh with Jsch
How to Add a Maven Dependency in Eclipse