Skip to main content

Blarg #10: I'm confused about keeping proper web application state.

Posted by jfalkner on November 22, 2004 at 8:54 PM PST

Do you write web applications. Do you know why you should always sychronize access to the session and application scopes but not always the request scope? If not, this should help clear things up.

This is a little user support for my book. Cheers to the readers.


> Hi
>
> I have read your "Servlets and Java Server Pages - The
> j2ee technology web tier" book, by you and Kevin
> Jones.
> (ISBN 0-321-13649-7)
>
> I have a question about a particular chapter, on
> Chapter 9 "Managing State in a Web Application". You
> mentioned in 'Protecting Session and Application
> State' subtopic, Listing 9-11, that it is important to
> have synchronized block for the session object, so
> that it is unique for every client access.
>
> Does it mean for every of my httpservlet doGet()
> service method :-
>
> public class hello extends HttpServlet {
>
> public void doGet(HttpServletRequest request,
> HttpServletResponse response) throws .... {
>
> String value1 = request.getParameter("value1");
> HttpSession session =
> request.setAttribute("setValue1", value1);
> ....
>
>
> Does it mean above code is wrong, ie I have to
> sychronised session object, before setting Attribute
> to value1 ?
>
> Same for getAttribute. Let's say I setAttribute here
> in the servlet. But in another servlet, I getAttribute
> for value1. Does it mean I need to have a synchronised
> block for the session object before i getAttribute() ?
>
> In your book, listing 9-11, your synchronised block
> has the following :
>
> synchronised (session) {
> session.setAttribute("user",user);
> ...}
>
> For the 'user' variable, can I presume 'User' is a
> actual java class, or it is just to illustrate the
> need to have a unique identifier for this particular
> session ?
>
> Thanks!

You need to keep in mind what is shared and what is not shared when thinking about state. For each doGet() method invocation a new HttpServletRequest object is made, and you can access this object without fearing that any other thread is concurrently accessing it. However, this changes for the HttpSession object. Two requests from the same user might try to change the same session object. There is only one session object per a user accessing the web app.

The point is. If you are using:

request.setAttribute("setValue1", value1);

You don't need to synchronize. The "request" implicit object is the HttpServletRequest for that doGet() invocation.

But, if you are using:

session.setAttribute("setValue1", value1);

You need to synchronize to the session:

synchronized(session) {
// whatever code you like
  session.setAttribute("setValue1", value1);
// whatever other code you like
}

The HttpSession object is shared for every user request. If the user clicks a submit button twice or just makes multiple requests quickly, the web server might have two threads manipulating the HttpSession object at the same time.

Again, the difference is that each doGet() makes a new "request" object, but every doGet() for the same client uses the same "session" object. If you want to keep proper state, you need to synchronize to the shared objects, i.e. "session" but you don't have to worry about the "request" object. If you apply this to the ServletContext object, i.e. "application", you will always want to synchronize it. Every doGet() method, regardless of user, shares the same application object.

Addressing your comments.

> String value1 = request.getParameter("value1");
> HttpSession session =
> request.setAttribute("setValue1", value1);
> ....
>
> Does it mean above code is wrong, ie I have to
> sychronised session object, before setting Attribute
> to value1 ?

No. Unless I'm missing something the above code isn't doing anything to the session object -- I'm not even sure it is valid code. If you are using setAttribute()/getAttribute() on the request object you don't need to synchronize. But if you used the same methods on the session object, you should synchronize the related code.

> Same for getAttribute. Let's say I setAttribute here
> in the servlet. But in another servlet, I getAttribute
> for value1. Does it mean I need to have a synchronised
> block for the session object before i getAttribute() ?

It depends. If you are using MVC and you are just passing objects between Filters/Servlets used in the same request via the request object, you don't need to synchronize. However, if you are putting items in session scope, e.g. making a shopping cart that tracks user's items across multiple requests, you should synchronize all code that manipulates session scope.

> For the 'user' variable, can I presume 'User' is a
> actual java class, or it is just to illustrate the
> need to have a unique identifier for this particular
> session ?

Oops, this is kind of a bad example. "user" the String is just a string. It would let something like the JSP EL use ${user}. The second argument named user is a reference to a fictitious variable that could represent any Java object.

Cheers,

Jayson Falkner

jayson@jspinsider.com