70

Is a Spring RestTemplate thread-safe? That is

  • Is a RestTemplate a Strategy object that multiple connections can safely share. or
  • Is a RestTemplate a connection object (like a data-base connection), which can not be shared while in use, and requires creation afresh, or pooling, for each connection.
Raedwald
  • 40,290
  • 35
  • 127
  • 207
  • 3
    I am answering my own question, [as is encouraged](http://stackoverflow.com/help/self-answer). – Raedwald Apr 10 '14 at 13:31
  • See also http://stackoverflow.com/questions/21242812/how-to-use-resttemplate-efficiently-in-multithreaded-environment – Raedwald Apr 10 '14 at 13:33
  • See also http://stackoverflow.com/questions/21145558/resttemplate-should-be-static-globally-declared – Raedwald Apr 10 '14 at 13:34
  • See also http://stackoverflow.com/questions/6747478/is-the-spring-transactiontemplate-and-simplejdbctemplate-thread-safe – Raedwald Apr 10 '14 at 16:43

4 Answers4

97

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 the 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, 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 of messageConverters is final, this safely publishes the list of message converters.
  • Use the setMessageConverters(List<HttpMessageConverter<?>> messageConverters) mutator and then safely-publish the changed RestTemplate 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 by getMessageConverters() and then safely publish the changed RestTemplate object. However, the documentation for RestTemplate 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 a Collections.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.

Raedwald
  • 40,290
  • 35
  • 127
  • 207
  • 7
    Not only it's thread safe, but its creation seems to be expensive. I recently run on major performance problems on the tomcat because initialization of RestTemplate caused classloader lock contention. – Boris Treukhov Mar 10 '15 at 17:28
  • 3
    I don't think its thread safe. It uses messageconverters and you can add messageconverters at runtime from two different threads. And it will throw you concurrentmodificationexception while performing restTemplate.exchange() call, as it iterates through this messageconverters. – sakura Jun 09 '15 at 10:35
  • @sakura the "once constructed" condition covers that case. – Raedwald Jun 09 '15 at 11:29
  • 1
    @BorisTreukhov I also noticed that performance hit while I was debugging so I googled it and found this. – Alfredo Osorio Jul 07 '15 at 23:25
  • I have experienced problem with restemplate. I have spring bean default(singleton) which call .NET REST WS using rest template. With heavy load I have noticed in log mixins of requests and responses from different threads. I am not sure what is the cause, maybe messageConverters, but putting relevant code in synchronized block solved my problem. I am using spring version 3.2.2.RELEASE – gandra404 Mar 09 '16 at 17:32
  • @gandra404 That *you* have experience problems shows nothing, without further evidence. Perhaps *you* made a mistake, which shows up in a manner that you incorrectly interpret as being the result of a `RestTemplate` not being thread-safe. – Raedwald Mar 09 '16 at 17:37
  • @Raedwald It is true. But when I find time I will post it as a separate question with more info for context. I have tried to put synchronized block and it solved problem. Then I have removed synchronized block and make restTemplate bean to be prototype scope and again I have reproduced same error. – gandra404 Mar 10 '16 at 22:20
  • @Raedwald, Please see this: http://tiemensfamily.com/TimOnCS/2017/08/06/is-spring-resttemplate-thread-safe/ The writer doesn't agree with you. – damjad Dec 26 '17 at 13:28
  • So much discussion just confuses the end reader if at all the marked answer is correct or not :( I plan to call same restTemplate object from multiple threads. Can I consider it safe? – comiventor Dec 26 '17 at 14:51
  • 2
    @comiventor If you don't use custom messageConverters then its ok to use one instance of RestTemplate. Otherwise, inject messageConverters via constructor - also thread safe. – user1697575 Jun 11 '18 at 17:35
  • The setInterceptors() method is not thread safe. One thread may be sorting the internal interceptors list, while another clears it. You can't categorically state that an object with mutable state is thread safe. Certain operations are thread safe. – Mzzl Feb 08 '19 at 17:35
  • 3
    "Thread safe once constructed" seems to mean "thread safe as long as you don't change its state", which is true in the sense that _any_ object is thread safe as long as its state doesn't change. – Mzzl Feb 08 '19 at 18:31
2

It is thread safe from the library's point of view. For instance, the getMessageConverters() is public Which means that if someone gets hold on the list and modifies it outside of the purpose of the library then it will cause issues (and even the setter method, if it's called at any moment after RestTemplate instantiation - and while being used by other threads obviously, boom!). Which probably is what happened to Ross (not enough reputation to reply to the answer, but I'm backing up both the thread-safe and not thread-safe arguments)

0

Alright, though I might dig the old code out from source control that caused these issues.

I think it would be fair to say that even synchronizing on creation there exist circumstances where another thread can modify the internal collections. So best be careful. Looking at the old code, yes it was actually using a message converter. But only when synchronized on creation.

restTemplate = new RestTemplate();

restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

After that the only interaction with RestTemplate was with this:

return restTemplate.postForObject(url, object, clazz);

This is also the line that eventually throws the exception.

There is of course no interaction with the message converter (we have no local reference to it).

Looking at the stacktrace, and the spring source code, the error occurred at this line:

for (HttpMessageConverter<?> converter : getMessageConverters()) {

So what do we have?

  1. We have concurrent access to the messageConverters
  2. If our code didn't do it, then which code did? I don't have an answer. My solution at the time was to create a new RestTemplate every time as performance was not a concern in this app.

So in summary, there are circumstances where things may not be thread safe, certainly if you were to play around with message converters directly. This case though is a strange one, but I thought it would be useful to publish it.

Ross
  • 17
  • 1
  • My guess: after you run `restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());` but do not safely publish the change made to `restTemplate`. – Raedwald Apr 08 '16 at 12:00
  • That is to say, I think **your** call to `restTemplate.getMessageConverters().add(...` is not done in a thread safe manner. – Raedwald Apr 08 '16 at 12:07
-3

Hate to disagree with the accepted answer above (emphasis added), but no it is not Thread safe. Even after creation. Internally it is playing around with ArrayLists, I have not dug into the source. I have seen too many of these:

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at org.springframework.web.client.RestTemplate$AcceptHeaderRequestCallback.doWithRequest(RestTemplate.java:677)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:567)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:253)
Ross
  • 17
  • 1
  • 1
    The quote and link in the accepted answer is from Spring themselves. So it is safe to assume that RestTemplate is intended to be thread-safe, and failure to be thread safe would be a bug. So until your claim is backed up with a reference to an accepted Spring bug report, I am inclined to think you have made a mistake. For example, by adding message converters after set up. – Raedwald Jan 29 '16 at 17:14
  • Hmmm, interesting approach, if not raised as a bug, it must be incorrect. This is the world of software my friend, there are all sorts of things that can go wrong, and there are indeed bugs in many accepted systems and libraries. – Ross Jan 30 '16 at 19:54
  • Lets have a close look at that stack trace. getForObject, a standard call via Rest. Next have a look at the use of the ArrayList and a concurrentModificationException. Pretty self explanatory really. In the case of useful discussion I decided to add to this thread what I have seen. Let people make what they want from it. – Ross Jan 30 '16 at 20:01
  • 1
    No, not self explanatory as a bug in `RestTemplate`. That the exception is a `ConcurrentModificationException` does not indicate that `RestTemplate` is not thread-safe **once constructed**. It is consistent with your code having altered the `RestTemplate` object, or one of its contained `ArrayList` objects (such as the list of message converters) after construction of the object. – Raedwald Mar 09 '16 at 17:43
  • [There is more to thread safety than use of the `synchonized` keyword](http://stackoverflow.com/questions/801993/java-multi-threading-safe-publication). – Raedwald Mar 09 '16 at 17:50
  • Whatever is messing around with those internal collections has nothing to do with our code. No message converters. 1) Create RestTemplate. new RestTemplate() 2) use the same template for a while 3) Exception This is just the way it is I am sorry. Nothing fancy. – Ross Apr 07 '16 at 22:11
  • @Raedwald yes there is more to thread safety than use of the synchronized keyword, such as immutability. If your object has mutable state, and the mutation methods are not thread safe, don't state categorically that the entire object is thread safe. Some operations are, others are not. – Mzzl Feb 08 '19 at 17:49