Steps to develop and run a JSP Code
In this section, we will learn step-by-step how to develop a JSP code and run it using the Tomcat Server.
Let us consider the following JSP code:
Counter.jsp
<html>
<body>
<center>
<%@ page language="java" %>
<%! int count = 0; %>
<% count++; %>
Welcome! You are visitor number
<%= count %>
</center>
</body>
</html>
In order to run this JSP code we have to follow these steps:
- Create a directory under %CATALINA_HOME%/webapps called MyApps.
- Write the JSP source code (with .jsp extension).
- Place the JSP code into the MyApps directory.
- Create a deployment descriptor.
- Run Tomcat Server.
- Write “http://localhost:8085/MyApps/Counter.jsp” in the address bar of the Web Browser and press ENTER.
The output is shown below:
Figure 1: Output of the JSP program
On requesting the JSP program next time the value of the count variable will be incremented by 1. So next time the value of count will be 2, then 3, then 4, ……., and so on.
Internal details of how JSP works
Inside the JSP container there is a special Servlet called the page compiler. The Servlet container is configured to forward to this page compiler all HTTP requests with URLs that match the .jsp file extension. This page compiler turns a Servlet container into a JSP container. When a .jsp page is first called, the page compiler parses and compiles the .jsp page into a Servlet class. If the compilation is successful, the jsp Servlet class is loaded into memory. On subsequent calls, the Servlet class for that .jsp page is already in memory; however, it could have been updated. Therefore, the page compiler Servlet will always compare the timestamp of the jsp Servlet with the jsp page. If the .jsp page is more current, recompilation is necessary. With this process, once deployed, JSP pages only go through the time-consuming compilation process once.
After the deployment, the first user requests for a .jsp page will experience unusually slow response due to the time spent for compiling the .jsp file into a JSP equivalent Servlet. To avoid this unpleasant situation, a mechanism in JSP allows the .jsp pages to be pre-compiled before any user request for them is received. Alternatively, we deploy our JSP application as a web archive file (WAR) in the form of a compiled Servlet.
JSP’s Servlet generated code
Now let’s consider the previous JSP code Counter.jsp. When a JSP file is invoked, the Tomcat Servlet/JSP container (or Web container) creates two files in the “C:\%CATALINA_HOME%\work\Catalina\localhost\MyApps\org\apache\jsp” directory. Those two files are Counter_jsp.java and Counter_jsp.class. When we open the Counter_jsp.java file, we will see the following:
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/8.5.37
* Generated at: 2019-11-23 04:58:11 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class Counter_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
int count = 0;
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = null;
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.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("<html>\r\n");
out.write("<body>\r\n");
out.write("<center>\r\n");
out.write("\r\n");
out.write("\t \r\n");
count++;
out.write(" \r\n");
out.write("Welcome! You are visitor number \r\n");
out.print( count );
out.write("\r\n");
out.write("</center>\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
When we study the generated code, the first thing we will see is the following:
public class Counter_jsp extends HttpJspBase
The signature of this class is as follows:
public abstract class HttpJspBase extends HttpServlet implements HttpJspPage
Now we can see that HttpJspBase is an HttpServlet and it does implement the javax.servlet.jsp.HttpJspPage interface. The HttpJspBase is more like a wrapper class so that its derived class does not have to provide implementation for the interface’s methods if the JSP page author does not override them.
Back to the generated JSP servlet class, the JSP page source code is simply the following lines of code:
<% count++; %>
<%= count %>
There are no jspInit() and jspDestroy() methods in the source code, so there are no implementations for these two methods in the resulting Servlet code. The three lines of code, however, translate into the _jspService() method.
Remember that the JSP specification defines only standards for writing JSP pages. A JSP page itself will be translated into a java file, which in turn will be compiled into a servlet class. The two processes are implementation dependent and do not affect the way a JSP page author codes. Therefore, a JSP container has the freedom and flexibility to do the page translation in its own way. The JSP servlet-generated code presented in this chapter is taken from Tomcat. We can therefore expect a different Java file to be generated by other JSP containers.