0

Assume, we have a web app whose servlets make certain decisions based on the value from some status variable existing on the application level. The servlets themselves may change (update) the status value while processing users requests. Also, there is an interceptor filter, who reads current status upon each request and redirects users to the maintenance page thus temporarily blocking access to the application when it's needed.

The first obvious solution could be using context scoped status attribute, but as far as I understand, context scoped attributes are rarely updated and typically serve as a storage on the application level for the stuff that is loaded once (for example, by ServletContextListener) and then can be shared by servlets mostly for the reading. The classic example of that is DataSoruce object (like JNDI DataSource in Tomcat who allows connection pooling).

However, in a situation described above where the application variable is updated on the relatively regular basis, such strategy seem to be not very good really, since it would inevitably involve a lot of messing up with synchronized blocks or methods to guarantee that no two (or more) servltes may update the status simultaneously at the same moment because, as we know, each servlet runs in a separate thread. To make matters worse, I don't fully understand how to control synchronization in JSP while using EL/JSTL (or should I write a custom tag class for synchronized context scoped attributes reading and setting in JSP).

So, again, the question is: what could be an alternative to context scoped updatable attributes? Maybe using synchronized collections or concurrent maps, database transactions with proper isolation level for storing attributes values?

P.S.

The systematic short overview of the possible strategies with brief pros and cons would be much appreciated.

escudero380
  • 536
  • 2
  • 7
  • 25

1 Answers1

0

You can set/get the status as an attribute in the ServletContext. ServletContext os already thread safe. See Thread Safety of ServletContext objects

For example

In Servlet1 ServletContext context=getServletContext();
context.setAttribute("status","xxx");

In Servlet2 ServletContext context=getServletContext();
String status = (String)context.getAttribute("status");

and Iniside the Filter you can still get a reference to the ServletContext object using the FilterConfig object (This is according to the javadocs)

Rasha Elsayed
  • 660
  • 1
  • 7
  • 22
  • What do you mean by **thread-safe**? When multiple threads (remember, every user request to the servlet starts its own thread) read and write to the same attribute in _ServletContext_, we must **synchronize** the code (let's say, ON the _ServletContext_ object itself) in every servlet and filter who reads and updates the value of such attribute. Then, yes, this will make our attribute _safe_, but only from any other code that ALSO synchronizes on the same object (_ServletContext_)... and that is what I was trying to avoid hoping to get some other working strategy as an alternative. – escudero380 Sep 01 '19 at 06:23
  • 1
    @escudero380 No, since the ServletContext object itself already does that for you. That's what is meant by "thread-safe" here: if one thread writes a new value to the attribute, the other threads are guaranteed to see the new value. But of course, You might hav several servers in a cluster, so an in-memory flag won't work. How about storing data in your database? – JB Nizet Sep 01 '19 at 07:07
  • @JBNizet, You got me mixed up completely. This is an extract from "Head First Servlets and JSP" book (page 197): _"The typical way to protect the context attribute is to synchronize ON the context object itself. If everyone accessing the context has to first get the lock on the context object, then you're guaranteed that only one thread at a time can be getting or setting the context attribute. But... there's still an if there. It only works if all of the other code that manipulates the same context attributes ALSO synchronizes on the ServletContext."_ Is this information obsolete? – escudero380 Sep 01 '19 at 07:25
  • I don't have enough context to know what the author means by "protect the context attribute". But just setting or getting an attribute should be thread-safe. It's te responsibility of the container to guarantee the correctness of its own data structures. And I don't think anything prevents the container from exposing a different proxy of the context to every request, so synchronizing on the context looks like an awful idea to me. – JB Nizet Sep 01 '19 at 07:32
  • @JBNizet, Actually, author of the book by word "protect" means exactly what it implies - "make context attributes thread-safe") – escudero380 Sep 01 '19 at 08:11
  • Anyway, this is the description of what "protect" should mean in my web app: from the very moment one thread (servlet) begins updating the _status_ data on the application level, all other threads (servelts and filters) that might intervene in the process must retreat and wait until the first thread is finished with updating, so that not to read the old version of the _status_ that is currently being updated... – escudero380 Sep 01 '19 at 08:16
  • 1
    I checked an example Implementation of the ServletContext provided by the Tomcat server. It used a ConcurrentHashMap for the attributes which is thread safe. I think the author of the book is also right to say that, as the ServletContext is not implemented inside the jdk, but from the different Servlet Containers e.g. Tomcat. So he may have meant that the implementors should care about the synchronization. In any case you don't need to care about it in your code as your Servlet Container did it for you. – Rasha Elsayed Sep 01 '19 at 11:05
  • @RashaElsayed, Thank you for the explanation. It sounds pretty convincing. Though, I've decided to switch to database for retrieving and storing status data. – escudero380 Sep 01 '19 at 11:20
  • Here is the most clear explanation of the issue: "ServletContext provides a Map-like object container service to servlets where they can register and retrieve application objects by name with _setAttribute_ and _getAttribute_... Servlets **need not use synchronization when calling setAttribute and getAttribute**, but they may have to use synchronization when using the objects stored in the ServletContext... (Java Concurrency in Practice, B. Goetz) – escudero380 Sep 22 '19 at 09:26
  • So, to avoid further ambiguity, publishing objects in _ServletContext_ is indeed thread-safe, but if there is a chance we may want to update their state from the servlet, then the objects themselves should either be thread-safe or explicitly guarded by the lock. – escudero380 Sep 22 '19 at 09:33