MSc-IT Study Material
June 2010 Edition

Computer Science Department, University of Cape Town

Servlet Life-cycle

Now that we've covered some examples and seen the interfaces and classes which make up the Servlet API, we can discuss the life-cycle of a Servlet. The Servlet life-cycle consists of the steps through which Web server places a Servlet in order to satisfy a request for a resource implemented by a Servlet. This discussion is fairly general, and applies to all Servlets, not just those extending the HttpServlet class.

When a request for a resource implemented by a Servlet is made, the Web server does the following:

When a Web server no longer requires a Servlet, it calls the Servlet's destroy() method. This is another method defined by the Servlet interface, and can be used to release any resources which the Servlet has acquired during its execution (for example, any database connections that it created when init() was called).

This Servlet life-cycle gives Servlet-based Web programmes a number of advantages over CGI programmes, which were briefly mentioned earlier in this chapter. These advantages are:

We can now rewrite the above counter example to make use of the Servlet life-cycle The Counter class now looks as follows:

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

public class Counter extends HttpServlet {

    private final String file_name = "counts.txt";
    private final String attribute_name = "visited";
    private final String attribute_value = "returnSoon";

    private int count = 0;

    public void init(ServletConfig config)
    {
	BufferedReader file = null;
	try {
	    file = new BufferedReader(new FileReader(file_name));
	    count = Integer.parseInt(file.readLine());
	}
	catch(IOException e) {
	}
	finally {
	    try {
		if (file != null)
		    file.close();
	    }
	    catch (IOException b) {}
	}
    }

    public void destroy()
    {
	PrintWriter writer = null;
	try  {
	    writer = new PrintWriter(new FileWriter(file_name));
	    writer.println(count);
	    writer.close();
	    writer = null;
	}
	catch (IOException e) {
	}
	finally {
	    if (writer != null)
		writer.close();
	}
    }

    public void doGet(HttpServletRequest request,
		      HttpServletResponse response)
    {
	HttpSession session = request.getSession();
	String value = null;
	    
	value = (String) session.getAttribute(attribute_name);
	    
	if (value == null) {
	    session.setAttribute(attribute_name, attribute_value);
	    session.setMaxInactiveInterval(60 * 60 * 24);

	    synchronized (this) {
		count += 1;
	    }
	}
	    
	try {   
	    PrintWriter out = response.getWriter();
	    out.println("<html>");
	    out.println("\t<head><title>Hello, visitor number " + count +
			".</title></head>");
	    out.println("<body>");
	    out.println("<p>Hello, visitor number " + count + ".</p>");
	    out.println("</body>");
	    out.println("</html>");
	}
	catch (IOException e) {
	}
    }
}
    

There are some important changes to notice: The previous versions of the Counter class read the counter.txt file when every request was made. This version of the class uses the init() method to read the file, and the destroy() method to overwrite the file. Recall that the init() and destroy() methods are called exactly once, which means that there is no need to synchronise any of the file access operations, as we have previously done. While all the code placed here in the init() method could be placed in the constructor, initialisation code placed in init() has certain advantages: first, it has access to the ServletConfig object, which can be used to provide configuration parameters to the Servlet. For instance, it could conceivably have contained the name of a file to store the counter information in. These configuration parameters can be set in the web.xml file. Second, ServletException objects cannot be thrown from within a constructor, but can be thrown from within init().

The doGet() method is called multiple times, whenever a service request is made. As with previous examples, doGet() may be called multiple times concurrently. The only area in the code accessing and overwriting shared data occurs where the count variable is incremented. This line is wrapped in a synchronisation statement to prevent two separate calls to doGet from interfering with each other during. It is possible that a second call to doGet could increment the count variable just before the variable is printed, but this will not cause the Servlet to misbehave.