RSS Feed for This PostCurrent Article

Java – Back to Basic, Understand Servlet Behavior

I am not against the use of frameworks in developing your Java web application. There are a lot of Java web application frameworks like Spring, Struts, JSF, Tapestry, etc which actually make life easier for developers. In fact, I do use Spring framework for most of my web application development.

What I perceived is that beginner Java developers sometimes are so getting used to those frameworks until the basic is forgotten. This may not be a problem as those frameworks actually hide a lot of programming complexities for us. However, when there is a bug or problem, it will be tough to troubleshoot if you do not understand the basic.

Consider the following code block.

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class Count extends HttpServlet {

int count = 0;

public void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res.setContentType(“text/plain”);
PrintWriter out = res.getWriter();
count++;
out.println(“Counter: ” +
count);
}
}

At first glance, the code may look perfectly okay for a beginner Java developer. To understand the problem, you must first understand servlet lifecycle.

In short, servlet persists between requests as object instances. In other words, at the time the code for a servlet is loaded, the server creates a single class instance. That single instance handles every request made of the servlet.

Not only do servlets persist between requests, but so do any threads created by servlets. If your servlets only read from the request, write to the response, and save information in local variables (that is, variables declared within a method), you needn’t worry about the interaction among these threads. Once any information is saved in nonlocal variables (that is, variables declared within a class but outside any specific method), however, you must be aware that each of these client threads has the ability to manipulate a servlet’s nonlocal variables. Without precautions, this may result in data corruption and inconsistencies.

In the above code block, count is a nonlocal variable. It’s possible that if two requests are made to Counter around the same time, each will print the same value for count. The order of execution will be

count++ // Thread 1
count++ // Thread 2
out.println // Thread 1
out.println // Thread 2

To resolved this, you can either

  • Make the method synchronized
  • Synchronize only the lines that need to executed atomically
  • Change count to a local variable


Trackback URL


RSS Feed for This Post2 Comment(s)

  1. Riccardo | Oct 16, 2007 | Reply

    Good post!
    I’ve seen tragical concurrency error from Hibernate (or the one you prefer) experienced programmers!
    In general I think that one should learn to walk before trying to run; so first jsp, servlet, jdbc and then jsf, struts, hibernate…

  2. alan c | Oct 16, 2007 | Reply

    This is a good lesson, but I think the example is poor. count is meant to indicate the number of times doGet has been called, correct? In that case having two separate requests both output 2 would be an acceptable outcome imo.

    If you really want to drive home the point that servlets are singleton, change it to a username field. (which I’ve seen before… yikes!)

1 Trackback(s)

  1. From napyfab:blog» Blog Archive » links for 2007-10-16 | Oct 16, 2007

Sorry, comments for this entry are closed at this time.