6.
JSP - Servlet Code
as generated by JSP Engine
Introduction
In the previous
chapter we saw how the JSP engine first creates a servlet after adding the JSP
code, compiles it and then finally executes it. As we have already laid the
foundation for servlets, we will now try to gain in-depth knowledge of
servlets, in the light of our newly acquired knowledge.
Let’s now understand
servlets. To do so, we will refer to our first script in the previous chapter.
Open it in the browser
by giving the url as
http://127.0.0.1:8080/examples/jsp/e1.jsp
You will see ‘hi’
displayed in your browser.
e1.jsp
hi
This Java file is
located in one of the subdirectories of the work directory.
We explained the
concept of servlets in one of the previous chapters. Let’s understand the
servlet code generated by the JSP engine by looking at smaller examples.
p1.java
import com.sun.jsp.runtime.*;
public class p1 extends HttpJspBase {
}
Here, there is only
one public class called p1 that extends HttpJspBase. Since the class is called
p1, you have no choice but to call the file p1.java. This program is in
c:\jswdk-1.0.1\webpages\web-inf\servlets. The name of the class is not
HttpJspBase but com.sun.jsp.runtime.HttpJspBase, therefore we have to use the
import statement.
All code can be either
in a .class file or in a .jar file. We have no choice but to point the
environmental variable named classpath to the jar file or jar subdirectory so
the compiler looks for the code there. A jar file is a collection of .class
files. We have set the CLASSPATH to servlet.jar and jspengine.jar which are in
the lib subdirectory and the current directory. To compile, we now say javac
p1.java
Set
CLASSPATH=c:\jswdk-1.0.1\lib\servlet.jar;c:\jswdk-1.0.1\lib\jspengine.jar;.;%CLASSPATH%
C:\jswdk-1.0.1\webpages\WEB-INF\servlets>javac p1.java
p1.java:2: class p1 must be declared abstract. It does not define void _jspService(javax.servlet.http.HttpServletRequest, avax.servlet.http.HttpServletResponse) from class com.sun.jsp.runtime.HttpJspBase.
public class p1 extends HttpJspBase {
^
1 error
HttpJspBase is an
abstract class and has one function named _jspService. Since p1 extends
HttpJspBase, p1 must define this class. Thus to eliminate the error, we must
add this to our next program.
p1.java
import com.sun.jsp.runtime.*;
public class p1 extends HttpJspBase {
public void _jspService(HttpServletRequest request,HttpServletResponse response) {
}
}
C:\jswdk-1.0.1\webpages\WEB-INF\servlets >javac p1.java
p1.java:2: class p1 must be declared abstract. It does not define void _jspService(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse
) from class com.sun.jsp.runtime.HttpJspBase.
public class p1 extends HttpJspBase {
^
p1.java:3: Class HttpServletResponse not found.
public void _jspService(HttpServletRequest request,HttpServletResponse response
) {
^
p1.java:3: Class HttpServletRequest not found.
public void _jspService(HttpServletRequest request,HttpServletResponse response
) {
^
3 errors
_jspService is the
same service that we have been using all this time. doGet and service both
belong to the same category. This function takes two parameters,
HttpServletRequest and HttpServletResponse. Hence we import
javax.servlet.http.* and since we will be using PrintWriter in the program, we
import java.io.* too. Now everything should work fine.
p1.java
import com.sun.jsp.runtime.*;
import javax.servlet.http.*;
import java.io.*;
public class p1 extends HttpJspBase {
public void _jspService(HttpServletRequest request,
HttpServletResponse response) {
try
{
response.setContentType(“text/html”);
PrintWriter out = response.getWriter();
out.println(“<b> Hi “);
out.close();
}
catch ( Exception e ) {System.out.println(“bye”);}
}
}
Run this program in
the browser by typing
http://127.0.0.1:8080/servlet/p1
/servlet is converted
to c:\jswdk-1.0.1\webpages\web-inf\servlets
This program now works
like a servlet. A servlet will work in the same manner whether it is derived
from Servlet or GenericServlet or HttpServlet or from HttpJspBaseServlet.
Having understood
this, let’s check out a more complex program.
p2.java
import java.io.*;
public class p2
{
public static void main(String argv[])
{
try {
char a[][] = {
{ ‘a’,’b’,’c’ },{ ‘d’,’e’,’f’ }};
FileOutputStream fos =
new FileOutputStream(“c:\\jswdk-1.0.1\\webpages\\web-inf\\servlets\\e.dat”);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(a);
oos.close();
}
catch (Exception e)
{System.out.println(“bye”);e.getMessage();
}
}
}
C:\jswdk-1.0.1\webpages\WEB-INF\servlets>javac p2.java
C:\jswdk-1.0.1\webpages\WEB-INF\servlets>java p2
C:\jswdk-1.0.1\webpages\WEB-INF\servlets>dir *.dat
Volume in drive C is SONAL
Volume Serial Number is 0661-13EE
Directory of C:\jswdk-1.0.1\webpages\WEB-INF\servlets
E DAT 73 06-13-00 8:28p e.dat
1 file(s) 73 bytes
0 dir(s) 2,651.09 MB free
C:\jswdk-1.0.1\webpages\WEB-INF\servlets>type e.dat
1/4_ -ur [[Cÿ2~+#i_- xp ur [C_&f__]ä1/4 xp a b cuq ~ d e f
Here, FileOutputStream
creates a file named e.dat in the servlets subdirectory. Then we write ‘abc’
and ‘def’ in it. These two strings are written as chars to disk.
The next program
follows up the previous one, which assumes that you have written an array of
chars to the file e.dat. So in our next program, we are merely picking them up
and displaying them. First we find out how many members are present in the file
and then we display each of them.
p3.java
import java.io.*;
public class p3
{
public static void main(String argv[])
{
try
{
char a[][];int i;
FileInputStream fos = new FileInputStream(“c:\\jswdk-1.0.1\\webpages\\web-inf\\servlets\\e.dat”);
ObjectInputStream oos = new ObjectInputStream(fos);
a = (char [][] ) oos.readObject();
System.out.println(a.length);
for ( i=0; i<a.length;i++)
System.out.println(a[i]);
}
catch (Exception e){System.out.println(“bye”);e.getMessage();}
}
}
C:\jswdk-1.0.1\webpages\WEB-INF\servlets>javac p3.java
C:\jswdk-1.0.1\webpages\WEB-INF\servlets>java p3
2
abc
def
These small programs
explain certain points required to understand the main program. So now let’s
understand the servlet written by the JSP engine.
p4.java
import javax.servlet.jsp.*;
import com.sun.jsp.runtime.*;
import javax.servlet.http.*;
import java.io.*;
import com.sun.jsp.JspException;
public class p4 extends HttpJspBase {
public void _jspService(HttpServletRequest request,
HttpServletResponse response) throws IOException,JspException {
JspFactory _jspxFactory = null;
PageContext pageContext = null;
JspWriter out = null;
try
{
_jspxFactory = JspFactory.getDefaultFactory();
pageContext = _jspxFactory.getPageContext(this, request, response,””, true, 8192, true);
out = pageContext.getOut();
response.setContentType(“text/html”);
out.print(“<b>Hie.... “);
out.print(out.getBufferSize());
} catch (Throwable t) {
if (out.getBufferSize() != 0)
out.clear();
throw new JspException(“Unknown exception: “, t);
} finally {
out.flush();
_jspxFactory.releasePageContext(pageContext);
}
}
}
Output in browser
Hie.... 8192
Run the above as
http://127.0.0.1:8080/servlet/p4
and compare the above
code with that generated by the jsp engine. They are identical.
The JSP engine calls
the _jspService function in the servlet for any task that is to be performed.
Here, we first create an object _jspFactory that looks like JspFactory.
JspFactory is a class and to use it we add two imports statements.
It is important to
know which import statements are required for the classes used in the program.
To avoid all these permutations and combinations, we have given all the imports
that we think are appropriate._jspFactory is initialized to the return value of
getDefaultFactory. JspFactory like System is a class. It has a static function
getDefaultFactory, which returns an object that looks like JspFactory.
JspFactory has a
member named getPageContext that manages a page. For the moment, we will leave
the parameters aside. This function returns a pageContext which has a member
named getOut, used for writing purposes. getOut returns an object that looks
like JspWriter, which we store in out. Here, we have JspWriter instead of
PrintWriter, but both are the same. out.println is used to write text and out
also has one more function named getBufferSize. getBufferSize returns 8192
because that is the buffer size we have given in pageContent. If an error is
encountered at any point then catch will be called.
Exception is derived
from Throwable. The base class is Throwable and all exceptions are derived from
it. We first check the buffer size and if it is not equal to 0, we clear the
buffer. Anything in the buffer will now be over-written. Then we throw the
exception jspException (we have imported com.sun.jsp.JspException.) After this
has been done, out.flush will flush the buffer and releasePageContext will
release the pageContext.
Here, JspWriter is
performing the job of PrintWriter. Effectively, they are the same; there is no
difference between them.
p5.java
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.Vector;
import com.sun.jsp.runtime.*;
import java.beans.*;
import com.sun.jsp.JspException;
public class p5 extends HttpJspBase {
static char[][] _jspx_html_data = null;
private static boolean _jspx_inited = false;
public final void _jspx_init() throws JspException {
ObjectInputStream oin = null;
int numStrings = 0;
try {
FileInputStream fin=new
FileInputStream(“c:\\jswdk-1.0.1\\webpages\\web-inf\\servlets\\e.dat”);
oin = new ObjectInputStream(fin);
_jspx_html_data = (char[][]) oin.readObject();
} catch (Exception ex) {
throw new JspException(“Unable to open data file”);
} finally {
if (oin != null)
try { oin.close(); } catch (IOException ignore) { }
}
}
public void _jspService(HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException {
JspFactory _jspxFactory = null;
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
String _value = null;
try {
if (_jspx_inited == false) {
_jspx_init();
_jspx_inited = true;
}
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType(“text/html”);
pageContext = _jspxFactory.getPageContext(this, request, response,“”, true, 8192, true);
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
out.print(_jspx_html_data[0]);
System.out.println(_jspx_html_data[0]);
} catch (Throwable t) {
if (out.getBufferSize() != 0)
out.clear();
throw new JspException(“Unknown exception: “, t);
} finally {
out.flush();
_jspxFactory.releasePageContext(pageContext);
}
}
}
In this program, all
that we have done is, within _jspService we have created 3 more objects,
session, application and config. Like
the earlier program, getPageContext returns pageContext. pageContext has a
function which will create the respective object and then initialize session,
application and config.
Before all this is
done, the if statement checks whether _jspx_inited, a static variable, holds a
true or false. The first time it holds false, so _jspx_init is called. This
function has an object that looks like ObjectInputStream. We now open a file
named e.dat which we created a little while ago. This entire file is read into
_jspx_html_data, an array of chars, using FileInputStream. In case an error is
encountered, an exception is thrown and finally, the file is closed. All this
has been explained individually earlier, so we won’t explain it again.
Once the function is
called, _jspx_inited is made true so that the function is not called
again. In the main code, there is an
out.print for _jspx_html_data[0]. This is the only new statement added. This
array had been initialized in _jspx_init with the contents of e.dat. So when
you run this servlet, it will show you abc in the browser because jspx_html_data
[0] is the first array and jspx_html_data [1] is the second array.