Monday, December 26, 2011

How does servlet instances share variable instances in a servlet container

On my post about Java class loader and static variable, I was asked if a static member shared for all user of a web application?

The quick answer is Yes. A static variable in a class used in a Servlet will be shared by all users who access the same application. However, to be precisely, A static member of class used in Servlet class will be shared by all instances of that servlet class. It is not just all user (or user's request). One servlet can be configured to have multiple instances in servlet engine.

If we only want to share variable among different user access to one servlet instance, we do not need to declare it as static. We can simply put it as global variable in our servlet class. This is actually topic about thread safe servlet programming.

We can also store variable in ServletContext if we want to share variable among different instances of servlet and it does not matter for other servlets in same context to see it.

Below is code to determine how static variable act inside servlet.

Step 1, Create a dummy class having static field.
/**
 *
 * @author Yiyu Jia
 */
public class DummyClass {
    //declare a static member.
    //This variable will be used as counter.
    static int jia = 0;    
}

Step 2, Create a servlet to validate variable values.
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Hashtable;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author Yiyu Jia
 */
public class TestStaticServlet extends HttpServlet {

    static int classCount = 0;  // shared by all servlet instances
    int count = 0;              // separate for each servlet
    static Hashtable instances = new Hashtable();  // also shared

    DummyClass jia = new DummyClass();

    /** 
     * Processes requests for both HTTP GET and POST methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {

            jia.jia++;
            count++;
            out.println("Since loading, this servlet instance has been accessed "
                    + count + " times.
" );

            // Keep track of the instance count by putting a reference to this
            // instance in a Hashtable. Duplicate entries are ignored.
            // The size() method returns the number of unique instances stored.
            instances.put(this, this);
            out.println("There are currently "
                    + instances.size() + " instances.
");

            classCount++;
            out.println("Across all instances, this servlet class has been "
                    + "accessed " + classCount + " times.
");

            out.println("jia static value:  " + jia.jia + "
");

        } finally {
            out.close();
        }
    }

    // 
    /** 
     * Handles the HTTP GET method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP POST method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// 
}

Step 3: Configure two instance for one servlet in web.xml

    
        TestStaticServlet
        TestStaticServlet
    
    
        TestStaticServlet
        /TestStaticServlet
    
    
        TestStaticServlet2
        TestStaticServlet
    
    
        TestStaticServlet2
        /TestStaticServlet2
    
    
        
            30
        
    
    
        index.jsp
    


Step 4: Now, we can deploy and access two different instance throw web browser.
URL one: http://localhost:8080/ServletStatic/TestStaticServlet

URL two: http://localhost:8080/ServletStatic/TestStaticServlet2

Step 5: We see something like below as result in web browser

No comments:

Post a Comment