Java Servlets in detail. Servlets life cycle

A servlet is a Java class that run at the server end, it is instantiated when needed and destroyed when not needed by the Servlet container. The init() and destroy() methods of Servlet interface will allow us to know when a Servlet has been initialized or destroyed by the Servlet container, but the are more methods to know about.

The Java Servlet written in this test will print out a message in the web server's log during the following events: the class loading, the instantiation, the initialization, the service and on the destroying. Thanks to this messages, and playing with the Servlet container while looking at the server's log, we will see when each life cycle event occurs. This way, we will verify when the Servlet is loaded, when is instantiated, how the service is called for every request we make, and how the instance of the Servlet is destroyed when we undeploy the application.

Environment

Required software that has already been installed and configured on the system.

Exercise steps

Step 1 - The LifeCycleServlet Java Servlet

This is the Java source code of the Servlet. It has and static initialization block, which is executed during the class loading. The constructor, obviously called on the instantation of the object, and three publics methods inherited from the HttpServlet and the GenericHttpServlet classes.

package com.onewaytickettojava.jsid;

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

public class LifeCycleServlet extends HttpServlet {

    static {
        System.out.println("" + System.currentTimeMillis() + " LifeCycleServlet: ClassLoading...");
    }

    public LifeCycleServlet() {
        System.out.println("" + System.currentTimeMillis() + " LifeCycleServlet: Constructor...");
    }

    public void init() {
        System.out.println("" + System.currentTimeMillis() + " LifeCycleServlet: Init...");
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println("<html><body><h1>Life Cycle Servlet</h1></body></html>");
        System.out.println("" + System.currentTimeMillis() + " LifeCycleServlet: service...");
    }

    public void destroy() {
        System.out.println("" + System.currentTimeMillis() + " LifeCycleServlet: destroy...");
    }

}
LifeCycleServlet.java

The Servlet container instantiates only one object to handle all the request to a Servlet. After calling the constructor, the container will call the Servlet's init(), it is typically used to create or load objects that are used by the servlet in the handling of its requests, this method is called only once during the life time of the Servlet and must be called before the servlet can service any requests. Once the Servlet is initialized, it can start serving requests, the service() method and it's broken down methods doGet(), doPost(), etc... will be called as many times as requests are received for the Servlet, remember that a new thread is created to service each request. Finally, the destroy() method, will be called when the web application is stopped, undeployed/removed or when the Servlet container shuts down.

Step 2 - The web.xml Deployment Descriptor

Nothing special here, just mapping the LifeCycleServlet with the /test path.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
   <servlet>
      <servlet-name>LifeCycleTest</servlet-name>
      <servlet-class>com.onewaytickettojava.jsid.LifeCycleServlet</servlet-class>
   </servlet>
   <servlet-mapping>
      <servlet-name>LifeCycleTest</servlet-name>
      <url-pattern>/test</url-pattern>
   </servlet-mapping>
</web-app>
web.xml

To make it a little more interesting, we will change the Deployment Descriptor configuration to test the effects of the load-on-startup tag. The Java Servlet 2.5 Specification says the following:

The load-on-startup element indicates that this servlet should be loaded (instantiated and have its init() called) on the startup of the web application. The optional contents of these element must be an integer indicating the order in which the servlet should be loaded. If the value is a negative integer, or the element is not present, the container is free to load the servlet whenever it chooses. If the value is a positive integer or 0, the container must load and initialize the servlet as the application is deployed. The container must guarantee that servlets marked with lower integers are loaded before servlets marked with higher integers. The container may choose the order of loading of servlets with the same load-on-start-up value.

By setting the value of this tag to a positive number, we will tell the Servlet container to preload the Servlet when the web application is started.

<servlet>
   <servlet-name>LifeCycleTest</servlet-name>
   <servlet-class>com.onewaytickettojava.jsid.LifeCycleServlet</servlet-class>
   <load-on-startup>1</load-on-startup>
</servlet>
web.xml

Test

First of all, we need to keep a view of the server's log during all the test. To achieve this, nothing better an easier than the tail command with the -f parameter to have a live view of the last lines of the Servlet container log. In this case we will see the five last lines, specified by the -n5 parameter. Previous to the tail command we will start the server.

~$ tomcat start
Using CATALINA_BASE:   /home/me/lab/servers/tomcat
Using CATALINA_HOME:   /home/me/lab/servers/tomcat
Using CATALINA_TMPDIR: /home/me/lab/servers/tomcat/temp
Using JRE_HOME:       /home/me/lab/jvm/java-6-sun
Tomcat started.
~$ tail -f -n5 $CATALINA_HOME/logs/catalina.out
Terminal

Servlet class loading

As pointed before, there are two options, two Deployment Descriptors to test, which will produce two different outputs.

INFO: Server startup in 567 ms
Dec 31, 2009 7:33:54 PM org.apache.catalina.startup.HostConfig checkResources
INFO: Undeploying context [/ServletLifeCycle]
Dec 31, 2009 7:33:54 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive ServletLifeCycle.war
Terminal - Output produced by the DD without the load-on-startup element.

With the Tomcat server started, we will deploy the ServletLifeCycle web application which do not have the load-on-startup element defined with the ant deploy command. Nothing happens, because the LifeCycleServlet has not been requested, it has not been instantiated neither loaded. However, if we deploy the web application with the web.xml configuration with a positive value inside the load-on-start-up element, the Servlet is loaded, instantiated and its init() method called, just as the Java Servlet Specification defines.

Dec 31, 2009 7:27:05 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive ServletLifeCycle.war
1262284025786 LifeCycleServlet: ClassLoading...
1262284025786 LifeCycleServlet: Constructor...
1262284025787 LifeCycleServlet: Init...
Terminal - Output produced by the DD with the load-on-startup element.

Instantiation, Initialization and service()

If the Servlet has not been loaded yet, it will be loaded and an instance of this class will be created as soon as a request is received for it by the Servlet Container. Visit: http://localhost:8080/ServletLifeCycle/test.

Dec 31, 2009 7:33:54 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive ServletLifeCycle.war
1262284507405 LifeCycleServlet: ClassLoading...
1262284507405 LifeCycleServlet: Constructor...
1262284507406 LifeCycleServlet: Init...
1262284507406 LifeCycleServlet: service...
Terminal

Every time we refresh the browser (F5), a new request to the LifeCycleServlet is sent, so the service method doGet() is called.

Dec 31, 2009 7:33:54 PM org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive ServletLifeCycle.war
1262284507405 LifeCycleServlet: ClassLoading...
1262284507405 LifeCycleServlet: Constructor...
1262284507406 LifeCycleServlet: Init...
1262284507406 LifeCycleServlet: service...
1262284520587 LifeCycleServlet: service...
1262284521127 LifeCycleServlet: service...
1262284521543 LifeCycleServlet: service...
Terminal

Servlet Destruction

When the application is stopped, removed/undeployed or the Servlet container shuts down, your Servlet's destroy() method will be called. This allows to free any resources obtained inside the Servlet's init() method.

1262284520587 LifeCycleServlet: service...
1262284521127 LifeCycleServlet: service...
1262284521543 LifeCycleServlet: service...
1262284625307 LifeCycleServlet: destroy...
Dec 31, 2009 7:37:05 PM org.apache.catalina.startup.HostConfig checkResources
INFO: Undeploying context [/ServletLifeCycle]
Terminal

There are more cases to try. So if you want to find out more about the Servlet life cycle, keep playing with the Server container and the web.xml configuration file.

Test files

Files used during the test. Click on the file to download it (do not use "Save Link As...").

References

0 comments

Be the first to write a comment!

Post a Comment

Top