views:

345

answers:

4

How do I make sure my java servlets web application is thread safe? What do I need to do in regards to session variables, static variables of a class, or anything else that could be a thread-safety problem?

A: 

Do you mean in a context as opposed to any other java application? There really isn't much difference. Each request to a servlet causes the container to issue a new thread to handle it, so instance variables within the servlet must be thread-safe. It's better to handle all your biz with local variables in the doGet / doPost() methods. There is one gotcha that I can think of. With session variables, it may be the case that the user has two browser windows open, both pointing to your application. In this case you would need to watch out for thread safety with the session scope as well.

darren
+1  A: 

Wow, that's a loaded question.

To put it simply, you need to ensure that access to any shared data is carefully synchronized. E.g., you may want to synchronize access to a static variable with a mutex or a synchronized function.

Note that you may also need to synchronize at higher levels if you need atomic transactions that modify multiple shared resources at the same time.

Designing a concurrent application is not simple, and there is no magic bullet (unfortunately). I highly recommend the book "Java Concurrency in Practice" for more information on writing safe concurrent code.

0xfe
+8  A: 
Bozho
I think item 4 pretty much supercedes (covers) 1-3. :)
Jack Leow
well, there is a need for some basic knowledge before you can make some good thinking
Bozho
+1 for item 4 :)
BalusC
+4  A: 

Fact: there's only 1 instance of a servlet in webapp's lifetime. It get created on webapp's startup and it get destroyed on webapp's shutdown. Also see this answer for a rough interpretation.

Thus, it's been shared among all requests (threads). If you assign request or session scoped data as instance (or even worse, as static) variable, then it is definitely not threadsafe, because it's then been shared among all requests (threads) from all users (sessions) applicationwide. You just need to assign them as method local variables to keep them threadsafe. So:

public class MyServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

That's basically all you need to take into account when developing servlets with threadsafety in mind.

Then there are session (HttpSession) attributes which can be shared among multiple requests from the same user, but in real world you actually don't need to worry about synchronizing session access. You normally put only user-specific data there, such as the logged-in user, user-specific preferences, the shopping basket, etcetera. You just need to ensure that you don't put pure request scoped data in the session scope. It would get reflected in multiple browser windows/tabs inside the same session.

Then there are application (ServletContext) attributes which are shared among all users applicationwide, but you normally put only constants and other static data there, like the webapp configuration, DAO factory, dropdownlist contents, etcetera. This all can by the way be done with a ServletContextListener, also see this answer for a basic example. You just need to ensure that you don't put pure request- or session scoped data in the application scope.

BalusC
One question regarding "one servlet in web app's lifetime" - I thought that was a pooled object, so there *could* be more than one at the servlet engine's discretion depending on load. Is that not true?
duffymo
Only if it implements (as per Servlet 2.4 deprecated) `SingleThreadModel`.
BalusC