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 HierarchyTop
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:
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 PageTop
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:
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.
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.
TranslationTop
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.
CompilationTop
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 LoadingTop
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
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. 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. 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 Each JSP Servlet gets one We can have multiple entries of the <init-param> sub-element. The Each web application gets one We go into much more detail about the The 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 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 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 The 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 The translation of the 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 If you remember from the JSP Hierarchy diagram Don't worry too much about the rest of the code for now as we will expand on this in later lessons. In this lesson we made a much deeper inpsection of JSPs by looking at the JSP lifecycle. In the next lesson we look at the anatomy of JSP by investigating the various elements that can be used within a JSP page.
<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>
InstantiationTop
InitialisationTop
ServletConfig
and ServletContext
.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>
ServletConfig
object also allows us to access the other object we get with a JSP Servlet, the ServletContext
object.
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>
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 MethodTopjspInit()
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 ServicingTop
_jspService(HttpServletRequest req, HttpServletResponse resp)
method is invoked.The
_jspService()
Lifecycle MethodTop_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.DestructionTop
jspDestroy()
method which gives us an opportunity to free resources and tidy up before the servlet is garbage collected.
The
jspDestroy()
Lifecycle MethodTopjspDestroy()
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 CodeTop
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>
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);
}
}
}
_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.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.Lesson 2 Complete
What's Next?