Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is javax.servlet.ServletContext set/getAttribute thread safe?

Having to use setAttribute() and getAttribute(String) in javax.servlet.ServletContext, I cannot find any information on the intended behavoir with concurrent access. However, these operations may very well be called by different threads.

The servlet specification 3.0 states:

A servlet can bind an object attribute into the context by name. Any attribute bound into a context is available to any other servlet that is part of the same Web application.

However, there is no information on concurrency behavior of these operations. A look into the source code of Apache Tomcat reveals that it is implemented as a ConcurrentHashMap, thus making it effectively thread-safe.

My question is, should I always treat these operations as not thread-safe and have the application handle the synchronisation, or is there a piece of information that I am missing?

like image 420
Benni Avatar asked Jul 23 '15 13:07

Benni


1 Answers

You can safely assume you can call getAttribute and setAttribute without synchronizing on anything, but you should make the objects you store there threadsafe (the easiest way being to store things that are immutable). The question linked in the comments is about storing a mutable object in the servletContext, in which case threads using it need to acquire its lock first (which the accepted answer explains).

There's not a spelled-out requirement. This is covered in Java Concurrency in Practice, section 4.5.1 Interpreting Vague Documentation:

You are going to have to guess. One way to improve the quality of your guess is to interpret the specification from the perspective of someone who will implement it (such as a container or database vendor), as opposed to someone who will merely use it. Servlets are always called from a container-managed thread, and it is safe to assume that if there is more than one such thread, the container knows this. The servlet container makes available certain objects that provide service to multiple servlets, such as HttpSession or ServletContext. So the servlet container should expect to have these objects accessed concurrently, since it has created multiple threads and called methods like Servlet.service from them that could reasonably be expected to access the ServletContext.

Since it is impossible to imagine a single-threaded context in which these objects would be useful, one has to assume that they have been made thread-safe, even though the specification does not explicitly require this. Besides, if they required client-side locking, on what lock should the client code synchronize? The documentation doesn't say, and it seems absurd to guess. This “reasonable assumption” is further bolstered by the examples in the specification and official tutorials that show how to access ServletContext or HttpSession and do not use any client-side synchronization.

On the other hand, the objects placed in the ServletContext or HttpSession with setAttribute are owned by the web application, not the servlet container. The servlet specification does not suggest any mechanism for coordinating concurrent access to shared attributes. So attributes stored by the container on behalf of the web application should be thread-safe or effectively immutable. If all the container did was store these attributes on behalf of the web application, another option would be to ensure that they are consistently guarded by a lock when accessed from servlet application code. But because the container may want to serialize objects in the HttpSession for replication or passivation purposes, and the servlet container can't possibly know your locking protocol, you should make them thread-safe.

like image 99
Nathan Hughes Avatar answered Oct 03 '22 08:10

Nathan Hughes