JSP LifecycleS2C Home « JSP Lifecycle

In this lesson we make a much deeper inpsection of JSPs by looking at the JSP lifecycle and the mechanics of how a JSP is translated into a full-blown servlet. We will take a look at the class/interface hierarchy involved in this process, but this is container specific, so in this lesson we will be focusing on the hierarchy as used in the Tomcat container. We will make it clear when a process or name is container specific by mentioning it in the relevant place in the lesson.

JSP Hierarchygo to top of page Top

JSPs get translated into Servlets when they are first loaded and we went into the mechanics of Servlets in the Servlet Overview and The Servlet Lifecycle lessons so we won't go over this again here. What we are interested in here are the extensions to the Servlet Hierarchy that are involved in the JSP lifecycle which varies depending on the container you are using. The diagram below illustrates the JSP hierarchy for a Tomcat container installation with the explanations of the new classes and interfaces explained after:

JSP Hierarchy

In the diagram above our first JSP would be renamed in Tomcat as firstjsp_jsp.java when it was translated into java code, more on this shortly, and would extend the org.apache.jasper.runtime.HttpJspBase class.

The org.apache.jasper.runtime.HttpJspBase class extends the javax.servlet.http.HttpServlet class, making every JSP that uses the HTTP protocol a Servlet, as well as implementing javax.servlet.jsp.HttpJspPage, which describes the interaction that a JSP Page Implementation Class must satisfy when using the HTTP protocol.

The javax.servlet.jsp.HttpJspPage interface extends the javax.servlet.jsp.JspPage interface which extends the javax.servlet.Servlet interface. So if for any reason you wanted to write non-HTTP JSP pages, you would implement the javax.servlet.jsp.JspPage interface for the protocol required and this would still get translated into a Servlet.

The Life Of A JSP Pagego to top of page Top

We can think of an object's lifecycle as the various stages that said object goes through during its existence. Because a JSP page gets translated into a JSP Servlet and has to run within the boundaries of whatever web container we are using, there are additional factors involved with the lifecycle of a JSP page.

The following slideshow shows the various stages in the JSP lifecycle. Press the button below to step through the slideshow:

jspl 1 jspl 2 jspl 3 jspl 4 jspl 5 jspl 6 jspl 7 jspl 8 jspl 9

Our client has clicked on a link that points to a resource that is a JSP page rather than a static HTML page, so the web server directs the HTTP request to our web container.

The container attempts to translate the JSP page into JSP Servlet source code.

If translation was successful the container tries to compile the JSP Servlet source code.

This JSP Servlet has not been called by the container before so will have to be loaded by the application's class loader.

Just like any other object our JSP Servlet has to be instantiated so it can be called by the container. The container calls the default no-args constructor which is best left to the compiler to generate.

Now we have a JSP Servlet object the first of the three lifecycle methods, the jspInit() method is called for the first and only time, and is where the initialisation of the JSP Servlet takes place.

The second of the three lifecycle methods, the _jspService() method is called on our initialized JSP Servlet and services the request from the client. A response is created and passed back to the client.

The JSP Servlet sits there in its initialized state happily servicing requests from clients and sending back responses.

The third and final lifecycle method, the jspDestroy() method is called on our JSP Servlet. This can happen for a number of reasons including server shutdown and an application being undeployed.

Press the button below to cycle through our JSP Lifecycle slideshow.

We will go into the different stages of the JSP lifecycle shown in the slideshow in much more detail and answer some other questions raised by it as we go through the rest of the lesson.

Translationgo to top of page Top

The first time a JSP is requested by a client the container attempts to translate the JSP page into a JSP implementation page, which is a Java class that implements the javax.servlet.jsp.HttpJspPage interface for HTTP protocol specific pages or its superinterface javax.servlet.jsp.JspPage interface for generic protocol requirements.

For the Tomcat container used in these lessons, with which we always use the HTTP protocol for our examples, the container suffixes the original name of our page with _jsp and adds the .java extension to the translated source. So for a JSP called firstjsp.jsp the translated JSP implementation page would be called firstjsp_jsp.java and would extend the org.apache.jasper.runtime.HttpJspBase class, which implements the javax.servlet.jsp.HttpJspPage interface.

Compilationgo to top of page Top

Within Tomcat if the translation to the JSP implementation page was successful then the container tries to compile the Java source code into a JSP Servlet called firstjsp_jsp.class. Regardless of the container used and the variance that may occur with renaming we don't have to worry about different naming conventions as we never invoke compiled JSP servlets directly by their class name.

Class Loadinggo to top of page Top

A container can contain many web applications and each of these has a class loader that is used to search for and load classes from the /WEB-INF/classes/ directory and JAR files from the /WEB-INF/lib/ directory. Having separate class loaders for each application allows servlets in different applications to have the same name but also means that servlets within one application can only communicate with servlets in another application via the container interface.

Because the container finds a class it doesn't necessarily load it; the default behaviour is to lazily initialise servlets on first use or when the container deems it necessary. We can also set servlets to load on deployment or server restart, via the DD. This is achieved using the <load-on-startup> sub-level element of the top-level<servlet> element, an example of which is shown below.


<servlet>
   <servlet-name>Our First JSP</servlet-name>
   <jsp-file>/WEB-INF/jsp/first.jsp</jsp-file>
   <load-on-startup>1</load-on-startup>
</servlet>

Any positive integer value placed in the <load-on-startup> sub-level element will ensure that a servlet is loaded on deployment or server restart. If you have several servlets in your web application you can also control the order in which servlets are loaded via the <load-on-startup> sub-level element. The servlets with the highest <load-on-startup> integer values get loaded first down to the lowest with a positive value.

Instantiationgo to top of page Top

Just like any other object our JSP Servlet has to be instantiated so it can be called by the container. The thing to remember here is that when creating our own JSP pages the container isn't aware of any particular protocol being used and so must instantiate the generated JSP Servlet in a generic manner. This is achieved using the default no-args constructor which is best left to the compiler to generate.

You cannot do any initialisation at this stage as our generated JSP Servlet doesn't exist in what we can think of as a servlet state until the no-args constructor has completed and the container makes it into a JSP servlet object. Any attempts to initialise the JSP Servlet using other parts of the application will fail and is the reason why we have separate instantiation and intialisation steps.

Initialisationgo to top of page Top

We now have a fully fledged JSP Servlet object waiting to be initialized to its default state. Here is a good time to talk about what value we get from a normal object being transformed into a JSP Servlet object. Well apart from the benefits we get from the container every JSP Servlet also gets access to two other objects, these being ServletConfig and ServletContext.

Each JSP Servlet gets one ServletConfig object and this is where we can put configuration information for deployment rather than in a constructor. We configure initialisation parameters for the ServletConfig object via the DD. This is achieved using the <init-param> sub-level element of the top-level <servlet> element, an example of which is shown below.


<servlet>
   <servlet-name>Our First JSP</servlet-name>
   <jsp-file>/WEB-INF/jsp/first.jsp</jsp-file>
   <init-param>
      <param-name>email</param-name>
      <param-value>mailto:alf@jsptutor.com</param-value>
   </init-param>
</servlet>

We can have multiple entries of the <init-param> sub-element.

The ServletConfig object also allows us to access the other object we get with a JSP Servlet, the ServletContext object.

Each web application gets one ServletContext object and we can get information about the versions of the container and API being used from this object. We can also configure application wide parameters for the ServletContext object via the DD. This is achieved using the <<param-name> and <param-value> sub-level elements of the <context-param> top-level element, an example of which is shown below.


<context-param>
   <param-name>disclaimer</param-name>
   <param-value>legaldoc.txt</param-value>
</context-param>

We go into much more detail about the ServletConfig and ServletContext objects in the ServletConfig & ServletContext lesson, but a point of note is that we can have multiple entries of the <context-param> element within the DD.

The jspInit() Lifecycle Methodgo to top of page Top

The jspInit() lifecycle method is the first of the three lifecycle methods associated with a JSP Servlet and is run only once during the life of a JSP Servlet. You can override this method and put initialisation code required by your JSP Servlet that cannot be placed declaratively within the DD in this method, such as Java code for referencing and database connections.

Request Servicinggo to top of page Top

So our one time initialisation has completed and our JSP Servlet is now ready to process requests. When a request from a client comes in the _jspService(HttpServletRequest req, HttpServletResponse resp) method is invoked.

The _jspService() Lifecycle Methodgo to top of page Top

The _jspService() lifecycle method is the second of the three lifecycle methods associated with a JSP Servlet and is run when a client requests a service. For subsequent requests for the JSP Servlet, the container will check to see if the original JSP page has been modified since the last translation and if this is the case it will go through the translation and compile stages again before being executed.

The _jspService() lifecycle method is where the translated entries from a JSP page go and cannot be overridden.

The _jspService() methods can throw a ServletException or a subclass thereof and if this happens and the exception is permanent the container returns a 404('Not Found') HTTP status code and removes the JSP Servlet from service. If the exception is temporary the container returns a 503('Service Unavailable') HTTP status code and makes the servlet temporarily unavailable. After a period of time the container will put the JSP Servlet back into service, making it available to service more requests. The _jspService() methods can also throw an IOException as we are accessing writers which can cause exceptions.

Destructiongo to top of page Top

The final phase of a JSP servlets lifecycle is its destruction and can happen for a number of reasons including server shutdown and an application being undeployed. When such an event happens the container will call the JSP Servlets jspDestroy() method which gives us an opportunity to free resources and tidy up before the servlet is garbage collected.

The jspDestroy() Lifecycle Methodgo to top of page Top

The jspDestroy() lifecycle method is the last of the three lifecycle methods associated with a JSP Servlet and is run only once during the life of a JSP Servlet. This method is invoked by the container when a JSP Servlet is going to be destroyed and gives us a chance to clean up and housekeep before the JSP Servlet is garbage collected. Dependant upon resources being used you may want to override this method in your own JSP Servlet code.

JSP Implementation Codego to top of page Top

Now we have seen the various stages in the JSP lifecycle it's a good time to look at some translated JSP implementation source code so we can see what the container does with our original JSP page. To illustrate this we will be using the first.jsp JSP page we coded in the Coding first.jsp section and this is shown again below so you can see the code before and after translation.


<!DOCTYPE html>
<html>
  <head><title>Our First JSP</title></head> 
  <body>
    <p>We just wrote our first JSP!</p>
  </body>
</html>

The translation of the first.jsp JSP page is shown below and is done using the Tomcat container and will differ for other containers. The translated code for Tomcat can be found within a subdirectory of the work directory within your Tomcat installation. On my machine the full path is:

C:\apache-tomcat-6.0.37\work\Catalina\localhost\firstjsp\org\apache\jsp\


package org.apache.jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;

public final class first_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent {

  private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();

  private static java.util.List _jspx_dependants;

  private javax.el.ExpressionFactory _el_expressionfactory;
  private org.apache.AnnotationProcessor _jsp_annotationprocessor;

  public Object getDependants() {
    return _jspx_dependants;
  }

  public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());
  }

  public void _jspDestroy() {
  }

  public void _jspService(HttpServletRequest request, HttpServletResponse response)
        throws java.io.IOException, ServletException {

    PageContext pageContext = null;
    HttpSession session = null;
    ServletContext application = null;
    ServletConfig config = null;
    JspWriter out = null;
    Object page = this;
    JspWriter _jspx_out = null;
    PageContext _jspx_page_context = null;


    try {
      response.setContentType("text/html");
      pageContext = _jspxFactory.getPageContext(this, request, response,
      			null, true, 8192, true);
      _jspx_page_context = pageContext;
      application = pageContext.getServletContext();
      config = pageContext.getServletConfig();
      session = pageContext.getSession();
      out = pageContext.getOut();
      _jspx_out = out;

      out.write("<!DOCTYPE html>\r\n");
      out.write("<html>\r\n");
      out.write("  <head><title>Our First JSP</title></head> \r\n");
      out.write("  <body>\r\n");
      out.write("    <p>We just wrote our first JSP!</p>\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
    } catch (Throwable t) {
      if (!(t instanceof SkipPageException)){
        out = _jspx_out;
        if (out != null && out.getBufferSize() != 0)
          try { out.clearBuffer(); } catch (java.io.IOException e) {}
        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
        else log(t.getMessage(), t);
      }
    } finally {
      _jspxFactory.releasePageContext(_jspx_page_context);
    }
  }
}

Hopefully you are able to follow the flow of the translated source code and can see how our JSP source has been translated and added to the _jspService() method, which is final. As we are using Tomcat as our container of choice, the _jspService() method is called from the org.apache.jasper.runtime.HttpJspBase superclass via its overridden service() method, which is also final, ensuring we cant override any service lifecycle methods.

If you remember from the JSP Hierarchy diagram org.apache.jasper.runtime.HttpJspBase also extends the javax.servlet.http.HttpServlet class and the init() and destroy() lifecycle methods are also overridden and made final. Of course in these cases we can override the called jspInit() and jspDestroy() methods which do the same thing.

Don't worry too much about the rest of the code for now as we will expand on this in later lessons.

Lesson 2 Complete

In this lesson we made a much deeper inpsection of JSPs by looking at the JSP lifecycle.

What's Next?

In the next lesson we look at the anatomy of JSP by investigating the various elements that can be used within a JSP page.

go to home page Homepage go to top of page Top