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.
|