Java Servlet is a platform-independent, container-based Web component used to generate dynamic content in a Web page. It is one of the stable technologies to share server-side resources in client-server programming. Because Servlet runs in a multi-threaded environment provided by the container, the life cycle events are completely dependent upon its efficient implementation. Understanding the life cycle of a servlet is the key to understand the intricacies of the low-level functionalities of servlet programming. This article provides a glimpse of this process in a concise manner.
The container, sometimes referred to as a servlet engine, is provided by a Web or an application server within which servlets run. Similar to simple Java programming, servlets are Java classes compiled to bytecode. These bytecodes are loaded dynamically into a Java technology-enabled Web server. A servlet container is often built into the server by default or sometimes provided as an add-on component via the server's native extension. The servlet classes generally interact with the server via an HTTP request/response mechanism implemented by the servlet engine. The primary function of the container is to contain servlet classes and manage their life cycle. Apart from supporting HTTP protocol, the servlet container also supports request/response based protocols, such as HTTPS, for a more secure network interaction.
Typically, a servlet goes through the following sequence of events:
- A client makes an HTTP request to the Web server via a Web browser.
- The Web server delegates the request to the servlet container. The container may be running as the same process as the network services or a different process on the same host.
- Depending upon the configuration of the servlet, the container invokes the appropriate servlet class with the response/request object.
- The request object provides information about the remote user, HTTP POST parameters, and other details. Once these details are known, the servlet processes the data according to the program logic and then sends back to the client via a response object.
- The servlet container returns the control back to the Web server after request processing is finished.
Figure 1: Control passing between the client and server
The Life Cycle
The life cycle begins as soon as it is called by the Web sever to load into the container. Grossly, it has a three-phase life: instantiation and initialization, service, and destruction.
Figure 2: The life cycle
Instantiation and Initialization Phase
In the initialization phase, the servlet container starts by locating servlet classes either in the local file system or from a remote location. The classes that are critical to start the application must be located at startup. Other classes may be loaded upon service request. The container uses a normal Java class-loader facility to load the classes located either in the local file system or from a remote location.
The initialization process begins after servlet objects are instantiated. It includes reading persistent configuration data, JDBC connection parameters if the application uses a back-end database, and other ancillary activities. The container invokes the init() method of the Servlet interface for the purpose of initialization. All servlet classes must implement javax.servlet.Servlet interface or one of the sub-implementations.
Figure 3: The initialization process
A basic servlet knows nothing about HTTP. Be3cause this is most commonly used in Web interaction at the application layer, a Java servlet offers a special implementation of the servlet, especially designed for this protocol. As a result, it has almost become normal to extend the abstract class called HttpServlet to implement the Web application layer. It contains methods such as:
- doGet: The server calls this method to handle HTTP GET requests.
- doPost: The server calls this method to handle HTTP POST requests.
- doPut: The server calls this method to handle HTTP PUT requests.
- doDelete: The server calls this method to handle HTTP DELETE requests.
Other almost-never used methods are service, doTrace, and doOptions. These methods delegate the handle to the doXXX() methods.
Typically, the abstract class GenericServlet is extended if we want to handle another protocol, including HTTP. Because it helps to define a protocol independent servlet, it makes writing the servlet easier. It provides the simpler version of the init and destroy methods. If we are to write a generic servlet, the only abstract method we need to override is the service.
The Servlet interface defines methods that are implemented by its sub classes. This interface is directly implemented by a Java class that wants to do every thing itself, like writing one's own container.
Only the invocation of the init method of the servlet by the container ensures that the servlet object is in the active container runtime; otherwise, not.
The service phase represents the interaction with the request until the duration of the service is actually destroyed. It may, however, happen that a servlet instance placed for service by the container actually never handled any request during its lifetime. The request and response are mapped to the service method, which in turn delegates the handle to the doXXX() methods. The request and responses are mapped to the objects of ServletRequest and ServletResponse, respectively. The objects are sent as the parameters of the service method. If the request and response type are of HTTP, the object types of HttpServletRequest and HttpServletResponse are used.
The service method implementation must take adequate measures to handle multiple concurrent requests fired by the container.
In this phase, the servlet is removed from the container. The container invokes the destroy method of the Servlet interface. This method ensures that the servlet is terminated gracefully and cleans up all the resources used or created during its life cycle.
The proper use of life cycle phases—initialization, service, and destruction—ensure that the servlet manages the application resources efficiently. During initialization, the servlet loads up all resources it needs to process requests in the later phase. The service phase uses these resources to respond as per requests made and then, in the destruction phase, the memory is freed up with the cleanup process. These three phases are in fact a gross representation of the servlet life cycle. In practice, a Web developer has more things to worry about as one dives deeper. However, they can only be realized once one get one's hands dirty and resorts to implementation, beginning with this basic concept.