5.
Java Server Pages
Introduction
Based on servlet
technology, Java Server Pages (JSP) is one of the most important elements of
Java server programming.
Java Server Pages
combine HTML or XML with nuggets of Java code to produce dynamic web pages. Each
page is automatically compiled to a servlet by the JSP engine the first time it
is requested, and then executed. JSP provides a variety of ways to talk to Java
classes, servlets, applets and the web server.
NOTE: We’ll be
explaining JSP using the Java Server Development Kit or the JSWDK which can be
downloaded from Sun’s site at www.javasoft.com. All new development on
JSP/servlets has been passed on to the apache team. The reason we are teaching
you the older version is because it is easier. There are cosmetic changes from
the one we are doing to the jakarta version which we will go back to in the
last chapter.
Download the zip file
from the Sun site on the Internet and unzip it. It will create a sub directory
jswdk-1.0.1. cd into this sub directory and then move into the bin sub
directory. Here run a batch file named startserver. If you get an error in the
Java Web Server window and if you are using jdk 1.2.2 like we are, add the
following to the classpath variable.
set CLASSPATH=c:\jdk1.2.2\lib\tools.jar;%CLASSPATH%
A Simple Java Server
Page
Let us begin by
creating a simple jsp file. To do so, create a file that has a .jsp extension
and save this file to the examples\jsp subdirectory. You can save it in the
examples subdirectory or the jsp subdirectory, either is fine. We have named
the file e1.jsp and it contains only one word, ‘hi’.
e1.jsp
hi
Open this file in the browser by giving the
url as
http://127.0.0.1:8080/examples/jsp/e1.jsp
‘hi’ will now be displayed in your browser window.
Congratulations! You
have written the world’s smallest JSP program. The browser initially takes a
long time to show you the result but in future it will be very quick.
Now go to the
subdirectory named work, where you will find a subdirectory ending with the
word examples. Change to this directory.
C:\jswdk-1.0.1\work>dir
Volume in drive C is SONAL
Volume Serial Number is 0661-13EE
Directory of C:\jswdk-1.0.1\work
. <DIR> 06-05-00 7:31p .
.. <DIR> 06-05-00 7:31p ..
%3A808~1 <DIR> 06-05-00 7:31p %3A8080%2Fexamples
%3A808~2 <DIR> 06-05-00 7:31p %3A8080%2F
0 file(s) 0 bytes
4 dir(s) 2,629.67 MB free
C:\jswdk-1.0.1\work>cd %3A808~1
This is your first JSP
file. You will find 3 files there, one java file, one class file and one dat
file. If you look at their names, they are very long but they all contain e1.
C:\jswdk-1.0.1\work\%3A8080%2Fexamples>dir
Volume in drive C is SONAL
Volume Serial Number is 0661-13EE
Directory of C:\jswdk-1.0.1\work\%3A8080%2Fexamples
. <DIR> 06-05-00 7:31p .
.. <DIR> 06-05-00 7:31p ..
JSP_00~1 JAV 2,615 06-05-00 7:31p jsp_0005ce_00031_0002ejspe1_jsp_1.java
C_0003~1 DAT 59 06-05-00 7:31p C_0003a.
jswdk_0002d_00031_0005f_00030_0005f_00031.examples.jspe1.dat
C_0003A <DIR> 06-05-00 7:32p C_0003a
JSP_00~1 CLA 2,530 06-05-00 7:32p jsp_0005ce_00031_0002ejspe1.class
3 file(s) 5,204 bytes
3 dir(s) 2,629.66 MB free
C:\jswdk-1.0.1\work\%3A8080%2Fexamples>
Now open the java file
by saying edit *.java
package C_0003a.jswdk_0002d_00031_0005f_00030_
0005f_00031.examples.jsp;
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 jsp_0005ce_00031_0002ejspe1_jsp_1 extends HttpJspBase {
static char[][] _jspx_html_data = null;
public jsp_0005ce_00031_0002ejspe1_jsp_1( ) {
}
private static boolean _jspx_inited = false;
public final void _jspx_init() throws JspException {
ObjectInputStream oin = null;
int numStrings = 0;
try {
FileInputStream fin = new FileInputStream(“work\\%3A8080%2Fexamples\\C_0003a.
jswdk_0002d_00031_0005f_00030_0005f_00031.
examples.jspe1.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]);
} catch (Throwable t) {
if (out.getBufferSize() != 0)
out.clear();
throw new JspException(“Unknown exception: “, t);
} finally {
out.flush();
_jspxFactory.releasePageContext(pageContext);
}
}
}
Edit shows you a Java
program which has been created by the Java Web Server. The JSP file that you
ran from the browser was converted into a servlet. The static data in the jsp
file was stored in a new file with the .dat extension in the subdirectory work.
The JSP engine writes this code for you. All your html code is stored in the
file with the .dat extension. At first _jspx_init is called which opens the
.dat file with the static text. Then _jspService is called. Now you know why it
takes a long time for the output to show up in the browser. It takes some time
to convert the jsp file into a servlet and then compile the servlet to a .class
file and then run the servlet.
JSP Expressions
A JSP Expression is a
great tool for embedding values within your HTML code. Anything between <%=
and %> tags will be evaluated, converted to a string, and then displayed.
Now let’s create
another file where we start with hi and then send %=”bye” %.
e2.jsp
hi
<%= “bye” %>
no
Partial Output of the
servlet code generated by the jsp engine for the .jsp file is enclosed with the
dotted lines..
----------------
out.print(_jspx_html_data[0]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e2.jsp”;from=(1,3);to=(1,10)]
out.print( “bye” );
// end
out.print(_jspx_html_data[1]);
--------------------
When you view this
file in your browser, it will display hi, bye and no, all on the same line.
Note that you must
save the file as e2.jsp and not e1.jsp.
Let’s understand what
we have just done. The JSP engine takes over and it saves hi to disk in the
.dat file. Then it sees the tag ‘<%’. It understands this character and for
it anything within <% %> is JSP.
A tag is anything that starts with an angle bracket. ‘<%’ is also used in Active Server Pages. The ‘=’ sign tells
the engine to add the line ‘out.print’ in the Java program and also whatever is
given in double quotes as a parameter to print. It automatically puts the open
and close bracket and a semicolon at the end. The next line with ‘no’ is also
saved to disk as another array.
In effect, you have
saved two arrays of chars on disk. If you look at the code, it all looks the
same. The only difference is that it says print the first array, then the newly
added line, out.print(“bye”), and then it finally print the second array.
_jspx_init uses the
function readObject to read the contents of the .dat file into an array
_jspx_html_data. Thus the array member _jspx_html_data[0] will contain hi and
_jspx_html_data[1] will contain bye. out looks like JspWriter and is
initialized in _jspService. It is used to create the html file which will be
sent across.
e3.jsp
hi
<% out.println(“no”); %>
bye
------------------
out.print(_jspx_html_data[0]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e3.jsp”;from=(1,2);to=(1,22)]
out.println(“no”);
// end
out.print(_jspx_html_data[1]);
------------------
Now remove the ‘=’
sign in the JSP file and write out.println (“no”); Since there is no ‘=’ sign,
the jspengine does not add its own out.print. This jsp statement gets added in as is. The JSP engine assumes
it to be Java code. This means that if
you do not write good Java code here, you will get horrible errors. This
happens when javac compiles the Java program. They will be displayed in your
Java server window.
This implies that
whenever you put an ‘=’ sign, you must use something that will be converted to
a string in Java. This is because the out.print that is added takes only a
single string as its parameter.
Hence bye is enclosed within double quotes. Try giving it without quotes and you will be presented with an error. The bye is assumed to be a variable. If you put a semicolon then it takes the semicolon as a part of the double quotes. There is supposed to be no space between the % and =. It must be typed in like this, <%=
In a nutshell, we have
html code and then there are Java Server Pages, where we have html, and Java code within that html. The html
tags and text are saved to disk and the Java code comes as is. Thus in a jsp
program we get to mix html and java code. All the java code written so far can
be placed in a jsp program along with html but within the <% tag.
e4.jsp
hi
<%= bye %>
no
Output in Browser
Error: 500
Unable to compile class for JSP
Error message in the
java server window.
com.sun.jsp.runtime.JspServlet:
init
Scratch
dir for the JSP engine is: work\%3A8080%2Fexamples
IMPORTANT:
Do not modify the generated servlets
Unhandled
error! You might want to consider having an error page to report such
errors
more gracefully
com.sun.jsp.JspException:
Compilation failed:work\%3A8080%2Fexamples\jsp_0005ce_
00032_0002ejspe2_jsp_2.java:69:
Undefined variable: bye
out.print(
bye );
^
1 error
at
com.sun.jsp.compiler.Main.compile(Main.java:347)
at
com.sun.jsp.runtime.JspLoader.loadJSP(JspLoader.java:135)
at
com.sun.jsp.runtime.JspServlet$JspServletWrapper.loadIfNecessary(JspS
ervlet.java:77)
at
com.sun.jsp.runtime.JspServlet$JspServletWrapper.service(JspServlet.j
ava:87)
at
com.sun.jsp.runtime.JspServlet.serviceJspFile(JspServlet.java:218)
at
com.sun.jsp.runtime.JspServlet.service(JspServlet.java:294)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:840)
at
com.sun.web.core.ServletWrapper.handleRequest(ServletWrapper.java:155
)
at
com.sun.web.core.Context.handleRequest(Context.java:414)
at
com.sun.web.server.ConnectionHandler.run(ConnectionHandler.java:139)
Here it assumed that
bye was a variable and the error is detected by javac on compiling the servlet
generated by the jsp engine.
Moving on to the next
example, where we are now writing System.out.println(“no”) within the % tag.
e5.jsp
hi
<% System.out.println(“no”); %>
bye
----------------
out.print(_jspx_html_data[0]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e5.jsp”;from=(1,2);to=(1,29)]
System.out.println(“no”);
// end
out.print(_jspx_html_data[1]);
-----------------
Output in Server Window
no
There is no ‘=’
following the %, so it is included as it is in the Java file. The ‘no’ will not
be shown on your screen but in the server’s dos box. To display something on
the screen, you can’t use System.out.println, instead you must use out.println.
If you carefully study
the code, you will observe that there are seven variables created and one of
them is out. Hence in JSP you are allowed to use out and you can use any of
these seven variables in your program. These are the predefined objects
available to you. System.out.println can also be used anywhere in a jsp tag as
it is a valid java statement. Do not forget the terminating semicolon as java
code written in a tag is added verbatim to the function _jspx_service().
JSP Declarations
A JSP declaration can
be thought of as the definition of class level variables and methods that are
to be used throughout the page.
In the next example,
we have hi and then bye. The JSP code begins with int j preceded by an
exclamation, and thereafter it has int i with a semicolon.
e6.jsp
hi
<%! int j; %>
bye
<% int i; %>
--------------------
public class jsp_0005ce_00036_0002ejspe6_jsp_1 extends HttpJspBase {
static char[][] _jspx_html_data = null;
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e6.jsp”;from=(1,3);to=(1,11)]
int j;
// end
public jsp_0005ce_00036_0002ejspe6_jsp_1( ) {
}
-------------------
-------------------
out.print(_jspx_html_data[0]);
out.print(_jspx_html_data[1]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e6.jsp”;from=(3,2);to=(3,10)]
int i;
// end
out.print(_jspx_html_data[2]);
-----------------------
Whenever anything is
put in an exclamation it is called a declaration. This is done outside any
function but within the class that is public. The line int j comes up when your
class starts with {. Whenever you put any statement in <%, it is placed in
jspservice and becomes local. It is visible from then onwards. If you want to
make a variable global then use an exclamation. You can create functions and
global variables in a class. Unlike C, where ‘global’ is applicable to the file,
here it is limited to a class.
Now we will mix java
with html code.
e7.jsp
hi
<% int i = 6;
if ( i == 6 ) %>
bye
---------------
out.print(_jspx_html_data[0]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e7.jsp”;from=(1,2);to=(2,14)]
int i = 6;
if ( i == 6 )
// end
out.print(_jspx_html_data[1]);
-------------
At first, the variable
i which is of type int is initialized to the value 6. Then the if statement
checks to see if i == 6. The next line after the comments will print bye only
if i holds the value 6, otherwise it will do nothing. Since the bye is pure
html, we have to end the jsp tag and close the JSP scriptlet. The final code
looks like this, if (i == 6) out.println (“bye”); What ever is given in <%
%> is kept as it is while the html statements become part of the array of
chars.
But what is the
purpose of all this? This is a method of generating dynamic code. The Perl
family of scripting languages generates the entire page. The focus is on Perl
writing the entire html page whereas ASP, PHP, JSP opted to have an html page
where the code would be inserted. In the html page, you can put ASP, PHP or
Java code to give the page dynamism and free yourself of the tedium of trying
to create every possible page the visitor must be shown by hand. The file that
you are writing is an html file, which means you can use an existing html
editor.
For Java Server Pages,
servlets are the foundation. Normally, a web page has a static template i.e.
things which are permenant. With JSP, you separate the static and the dynamic,
and insert dynamism into a web page. We will also use beans extensively in the
Java Server Pages and one of the chapters will explain to you how you can
create your own custom tags.
A JSP page is a
text-based document that describes how to process a request and create a
response.
JSP pages in servlet
classes are what Sun calls its web components and these pages are delivered by
a JSP container. When you look at a JSP page, you will see 3 classes of
scripting elements. These are declarations, scriptlets and expressions.
The following example
has been taken from the Net from a great FAQ that we stumbled upon. We don’t
mind if you take our programs too. We have not mentioned any names here because
there were too many brains behind it.
e8.jsp
<% for (int i = 1; i<= 4 ; i++) { %>
<H<%=i%>>Hello</H<%=i%>>
<% } %>
hi
The code looks
complicated but you can easily understand it.
The for statement goes
on four times. Since the for statement is not part of html, it is enclosed
within the % and the angle brackets. The ‘{‘ bracket starts the for loop. The
set of statements to be executed within the for is a combination of HTML and
JSP. H is an html tag that stands for heading. Along with H is a number that
displays the heading in a different format. We have not used a number directly
because we want it to be the value of i. i is a variable initialized in the for
loop. The <%= is used to display the value of i which is 1 as of now. Hence
the tag becomes H1. Following this is Hello. To close the tag, the same rules
are followed, the closing tag becomes </H1>. The ‘}’ bracket within the %
and the angle brackets is used to close the for loop. When i becomes 2, the
statement will be <H2>Hello</H2> and the same follows for 3 and 4.
This is how Hello can be seen in all 4 tags.
View the actual code
in the Java file and you will realize that it is much easier to comprehend.
View Source
<H1>Hello</H1>
<H2>Hello</H2>
<H3>Hello</H3>
<H4>Hello</H4>
hi
-------------------
out.print(_jspx_html_data[0]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e8.jsp”;from=(0,2);to=(0,34)]
for (int i = 1; i<= 4 ; i++) {
// end
out.print(_jspx_html_data[1]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e8.jsp”;from=(1,5);to=(1,6)]
out.print(i);
// end
out.print(_jspx_html_data[2]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e8.jsp”;from=(1,20);to=(1,21)]
out.print(i);
// end
out.print(_jspx_html_data[3]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e8.jsp”;from=(2,2);to=(2,5)]
}
// end
out.print(_jspx_html_data[4]);
out.print(_jspx_html_data[0]);
for (int i = 1; i<= 4 ; i++) {
out.print(_jspx_html_data[1]);
out.print(i);
out.print(_jspx_html_data[2]);
out.print(i);
out.print(_jspx_html_data[3]);
}
out.print(_jspx_html_data[4]);
------------------
There are 5 sets of
html data in the JSP file. The first one is blank, the second one is <h, the
next one is >hello</h, the third set is > and then finally, there is
hi. These are the different values assigned to the variables in the for loop.
_jspx_html_data[1] = <h
i 1,2,3,4
_jspx_html_data[2] = >hello</h
i 1,2,3,4
_jspx_html_data[3] = >
_jspx_html_data[4] = hi
If you look at e.dat,
it shows data as 5.
dat file
5
—
<H
—
>Hello</H
—
>
—
—
Let’s go one step
further, give two hyphens after %. Whenever you start with a <%- and end it
with -%>, it signals a comment.
e9.jsp
hi
<%- vijay mukhi -%>
bye
The good thing about
comments is that they soon disappear. They are present only in your JSP file
and will not be seen in the servlet. That’s why we have written my name there,
it doesn’t show up. So whenever you want to include comments but hide them from
the client, this is what you use. All this happens on the server, nothing comes
over on to the client hence nobody knows of it. If you want normal comments,
use the html comments which are given as <!- .
JSP Directives
A JSP Directive is a
statement that gives the JSP engine information for the page that follows.
Anything with a <%@ sign is called a Directive. In the following program, we
have used a directive named page. The other possible directives in JSP1.0 are
include and taglib.
e10.jsp
<%@ page info=”vijay” %>
public String getServletInfo() {
return “vijay”;
}
The compiler generates
different kinds of code depending upon the directive you use. The effects are
global. Here we say page info=vijay. A page is a directive and info is an
attribute. The attribute is given a value; vijay in this case. On doing so, the
JSP engine actually creates a function named getServletinfo and this function
returns the value given to info i.e. vijay.
e11.jsp
hi
<%@ page import=”java.applet.*” %>
-----------------
package C_0003a.jswdk_0002d_00031_0005f_00030_0005f_00031.examples.jsp;
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;
import java.applet.*;
-------------
When you give import
as an attribute and then look at the Java generated file, you will see that at
the end of the imports, there is import
java.applet.*. You don’t have to put a semicolon. This means that if you are a
referring to some Java code in some classes, you don’t have to preface them
i.e. give full names, you just put imports. In case you have more than one
import, then separate them using commas, they will all be added at the end. If
there are two similar imports, it is not considered an error. A point to be
noted here is that if the match is found earlier in the file, then the import
added by you is not used.
e12.jsp
hi
<%@ page extends=”java.util.Dictionary” %>
--------------
public class jsp_0005ce_00031_00032_0002ejspe12_jsp_1 extends java.util.Dictionary {
---------------
Normally, extends is
not used because by default every class extends HttpJspBase. But if you do so
then HttpJspBase is replaced with java.util.Dictionary. At times, when you want
to write complicated code then you can have a class that is derived from
HttpJspBase, from which you can further extend your classes. You must derive
from HttpJspBase or else you will end up with a load of errors.
e13.jsp
hi
<%@ page implements=”java.util.Dictionary” %>
Implements follows the
same rules as that of extends. The JSP engine adds a line to the class with
implements. It gives an error and no java file is generated as in this case as
well, Dictionary is a class not an interface.
e14.jsp
<%@ page buffer=”1000" %>
hi
------------
pageContext = _jspxFactory.getPageContext(this, request, response,””,true,1024000, true);
---------
Since we have given
the buffer as 1000, the getPageContext function makes the buffer parameter
1000KB i.e. 1000 multiplied by 1024. This is the amount of buffering space
required. Buffering improves speed
since its better to write a larger number of characters at one go than a small
number many times.
You will have multiple
requests being sent to your web server. You may want either one instance of the
servlet or you may want 20 of them running at a time. If you want the servlet
to create multiple instances of itself then you must give isThreadsafe=false.
The default is true.
e15.jsp
<%@ page isThreadSafe=”false” %>
<b>hi
---------------
public class jsp_0005ce_00031_00035_0002ejspe15_jsp_1 extends HttpJspBase implements SingleThreadModel
-----------------
By saying
isThreadSafe=false, the JSP engine will implement SingleThreadModel and it can
load multiple instances of the servlet instead of one. This class in that sense
doesn’t have any function prototypes and hence we don’t have to add any code in
the file. It can however, check to see if we have implemented certain
interfaces.
e16.jsp
<%@ page session=”false” %>
Bye
Most of these
attributes have a default value of true or false, so you don’t need to specify
them. There is one more attribute named session. By default, session is true,
so you see the session object in _jspservice function.
The following are the
variables that are created in the _jspservice function:
JspFactory _jspxFactory = null;
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
String _value = null;
When you make the page
session false, session that looks like HttpSession, is not created at all.
The next script has
the contentType initialized to text/plain. By default, the value assigned to
this attribute is text/html.
e17.jsp
<%@ page contentType=”text/plain” %>
<b>Bye
----------
response.setContentType(“text/plain”);
----------
The tag b is not
recognized by the browser anymore and thus we see <b> Bye in the browser.
The Content type depends upon the file being sent over.
If you initialize
IsErrorPage to true, it will actually create an object called exception that
looks like Throwable. This is then initialized by the getAttribute function.
e18.jsp
<%@ page isErrorPage=”true” %>
hi
-----------
Throwable exception=(Throwable) request.getAttribute(“javax.servlet.jsp.jspException”);
------------
The request variable
is given to us as a parameter in the jspservice function. getAttribute takes
one parameter which is a variable and returns a value. Instead of a variable we
call it an attribute. This is used to initialize the new variable named
exception which looks like jspException. The concept of exceptions has already
been discussed in one of the previous chapters.
Import saves us the
trouble of typing too much. Here we have a function named abc which has been
defined in the public area. Thus the declaration or the exclamation sign has
been used. Basically, it throws an IOException. The reason why we have page
import=java.io* is because it is easier to say IOException than
java.io.IOException. The minute the function abc is called, an exception will
be thrown. Somebody has to be there to receive this exception.
e19.jsp
<%@ page errorPage=”f1.jsp” %>
<%@ page import=”java.io.*” %>
<html>
<%! void abc() throws IOException
{
throw new IOException(“hi bye”);
}
%>
<%
//try
//{
abc();
//}
//catch ( Exception e) {}
%>
</html>
If we stop here , in
the browse we get the following error .
Error: 404
No detailed message
We start by using page
directive errorPage, which is also an attribute and its value is a jsp file
f1.jsp. If you look at the code you will realize that it throws new
HandleErrorPageException, which has f1.jsp as a parameter. f1.jsp is your error
page and because of this throw, it will now go to f1.jsp. In abc we have a
throw, we throw an IOException. Since an exception is thrown, the catch in the
servlet will catch it as the try and catch around abc have been commented out.
The servlet catch has HandleErrorPageException, where the first parameter is
f1.jsp and the last one is out. out is used to display output. t is throwable
as a parameter to catch. If you look at f1.jsp, it has to start with isErrorPage=true and we use
exception.printStackTrace to print where the exception took place.
f1.jsp
<%@ page isErrorPage=”true” %>
<%
out.println(“<pre>”);
PrintWriter pw = response.getWriter();
exception.printStackTrace(pw);
out.println(“</pre>”);
%>
Output
java.io.IOException:
hi bye
at
C_0003a.jswdk_0002d_00031_0005f_00030_0005f_00031.
examples.jsp.jsp_0005ce_00031_00039_0002ejspe19_jsp_1.
abc(jsp_0005ce_00031_00039_0002ejspe19_jsp_1.java:23)
at
C_0003a.jswdk_0002d_00031_0005f_00030_0005f_00031.
examples.jsp.jsp_0005ce_00031_00039_0002ejspe19_jsp_1.
_jspService(jsp_0005ce_00031_00039_0002ejspe19_jsp_1.java:82)
at com.sun.jsp.runtime.HttpJspBase.service(HttpJspBase.java:87)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:840)
at
com.sun.jsp.runtime.JspServlet$JspServletWrapper.service(JspServlet.java:88)
at
com.sun.jsp.runtime.JspServlet.serviceJspFile(JspServlet.java:218)
at com.sun.jsp.runtime.JspServlet.service(JspServlet.java:294)
at
javax.servlet.http.HttpServlet.service(HttpServlet.java:840)
at
com.sun.web.core.ServletWrapper.handleRequest(ServletWrapper.java:155)
at
com.sun.web.core.Context.handleRequest(Context.java:414)
at com.sun.web.server.ConnectionHandler.run(ConnectionHandler.java:139)
<pre>
</pre>
------------------
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e19.jsp”;from=(3,3);to=(7,0)]
void abc() throws IOException
{
throw new IOException(“hi bye”);
}
// end
In _jspservice
out.print(_jspx_html_data[0]);
out.print(_jspx_html_data[1]);
out.print(_jspx_html_data[2]);
out.print(_jspx_html_data[3]);
// begin [file=”C:\\jswdk-.0.1\\examples\\jsp\\e19.jsp”;from=(8,2);to=(14,0)]
//try
//{
abc();
//}
//catch ( Exception e) {}
// end
out.print(_jspx_html_data[4]);
} catch (Throwable t) {
if (out.getBufferSize() != 0)
out.clear();
throw new HandleErrorPageException(“f1.jsp”, t, out);
} finally {
out.flush();
_jspxFactory.releasePageContext(pageContext);
}
------------
f1.jsp error page
-----------
out.print(_jspx_html_data[0]);
out.print(_jspx_html_data[1]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\f1.jsp”;from=(1,2);to=(6,0)]
out.println(“<pre>”);
PrintWriter pw = response.getWriter();
exception.printStackTrace(pw);
out.println(“</pre>”);
// end
out.print(_jspx_html_data[2]);
-------------
exception.printStackTrace
prints out the text. In this way you can have a separate page for error
handling. All that you should do is create a page named anything.jsp and in
every JSP page redirect the errors to it.
Within the try and
catch is abc, so the code of abc will be called. You can have a ‘try’ and ‘catch’
within another ‘try’ and ‘catch’ pair, nested as many levels deep as you want.
abc throws an IOException, so the exception will be called.
e19a.jsp
<%@ page errorPage=”f1.jsp” %>
<%@ page import=”java.io.*” %>
<html>
<%! void abc() throws IOException
{
throw new IOException(“hi bye”);
}
%>
<%
try
{
abc();
}
catch ( Exception e)
{
System.out.println(“hi in exception”);
}
%>
</html>
Now that we have
uncommented the try and catch near abc, the earlier catch was not called and
down in the web server window we see hi in exception, which proves that only
the inner try catch was activated.
e20.jsp
hi
<%@ include file=”aa.html” %>
Bye
C:\jswdk-1.0.1\examples\jsp>edit aa.html
in aa.html
-------------------
out.print(_jspx_html_data[0]);
out.print(_jspx_html_data[1]);
---------------
dat file
2
hi
Output in browser
hi in aa.html Bye
A @ in a JSP file
signals a directive. The earlier examples had ‘page’, while in the program
shown above, we use include. include takes a string which has to be filename
which is aa.html here. e20.jsp contains hi, then the include and finally a bye.
aa.html simply contains ‘In aa.html’.
As always, your entire
JSP is converted into a .dat file. Since it is on two lines, you will see only
two prints in the Java file.
The point that we are
trying to make is that the .dat file is made at the time of the creation of the
servlet. This is called the Translation Phase. You can change aa.html, add some
more text and then refresh the server. The new text within the html file will
not be displayed because the .dat file isn’t created again.
The only way to
incorporate the new changes is by either recompiling the Java file or stopping
and restarting the server.Stopserver deletes all the files in the work
directory, so all the files are created from scratch when you want to view
them.
There are two phases
in JSP. One of them is the Translation Phase, which it happens only once. Then,
the service function ‘jspservice’ is called for every request.
So far we have
included a .html file, so now let’s try it out with JSP.
e21.jsp
hi
<%@ include file=”aa.jsp” %>
Bye
aa.jsp
no
<%= new java.util.Date() %>
lously
----------------
.java file for e21.jsp
out.print(_jspx_html_data[0]);
out.print(_jspx_html_data[1]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\aa.jsp”;from=(1,3);to=(1,25)]
out.print( new java.util.Date() );
// end
out.print(_jspx_html_data[2]);
--------------------
There is no java file
for aa.jsp.
dat file
3
hi
—
no
—
lousy
Bye
With this example you
will realize that if you have JSP code in include, then all the JSP code will
be put in the service function. Thus whenever you want something dynamic,
create a JSP file and use it with the include directive. Now each time you
click on refresh the date function will be reexecuted, so you see a different
date and time every time.
Let’s go one step
further.
e22.jsp
hi
<jsp:include page=”zz.jsp” flush=”true” />
bye
zz.jsp
no
bad
We now have 2 java files
created for the 2 jsp files.
---------------------
The java file for e22.jsp
out.print(_jspx_html_data[0]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e22.jsp”;from=(1,0);to=(1,42)]
out.flush();
pageContext.include(“zz.jsp”);
// end
out.print(_jspx_html_data[1]);
-----------------
-----------------
The java file for zz.jsp
out.print(_jspx_html_data[0]);
-----------------
The first line in
e22.jsp has hi and the second line is jsp:include page=”zz.jsp” within angle
brackets. If you notice there is no % sign like we had earlier. Such a line is
called an ‘action’. Each time you refresh the file, it gets the filename and
requests the server for that file. Unlike the earlier example, this is dynamic.
When you see the
generated java code, there is no data stored anywhere, so you check the .dat
file. In the Java file, the array size is 2, for hi and bye, hence you see 0
and 1. pageContext.include is what the jsp:include is converted to in the Java
file. It is this pageContext.include
that regenerates the file each time. Now the problem with using include as an
action is that you cannot have Java code with it and in addition, you cannot
change headers and cookies.
e23.jsp
hi
<jsp:include page=”a40.html” flush=”true” />
bye
a40.html
bye
-----------------
out.print(_jspx_html_data[0]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e23.jsp”;from=(1,0);to=(1,44)]
out.flush();
pageContext.include(“a40.html”);
// end
out.print(_jspx_html_data[1]);
------------------
In e23.jsp, the first
line is hi. Then a40.html, which contains bye, is included. Now change ‘bye’ in
the html file to ‘over’ and click on refresh. This time you will see over
instead of bye. include here is an action.
In the next script, we
have a new action called forward.
e24.jsp
hi
<jsp:forward page=”cc.jsp” />
bye
cc.jsp
no
<%= new java.util.Date() %>
lousy
------------------
out.print(_jspx_html_data[0]);
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e24.jsp”;from=(1,0);to=(1,29)]
if (true) {
out.clear();
pageContext.forward(“cc.jsp”);
return;
}
// end
out.print(_jspx_html_data[1]);
------------------
This example
introduces a new action named forward. page=cc.jsp implies that we are sending
a page with it. Hence every time you try to load e23.jsp, you will be forwarded
to cc.jsp. Forward becomes pagecontext.forward in the Java file. This will
simply go to the page mentioned. A valid question to ask here would be, ‘will
it come back to e23.jsp?’ The answer is no. That’s because the last line before
the closing brace is a return. So whenever you have forward as an action, the
file passed to pagecontext.forward becomes your active html file and everything
else is forgotten.
Bear in mind that the
http protocol is a stateless protocol. Each time you connect to the web server
you are disconnected after you receive the page. So if you are on the
Amazon.com site and you buy 6 books, moving from one page to the other, it
becomes a session and this session has to be tracked. This is where the session
object comes into use.
z.htm
<html>
<form action=e26.jsp>
<input type=’text’ name=’aa’>
<input type=’submit’ value=’click’>
</form>
</html>
e26.jsp
<%= request.getParameter(“aa”) %>
------------------
out.print(_jspx_html_data[0]);
// begin [file=”C:\\jswdk-1.0.1\\webpages\\e26.jsp”;from=(0,3);to=(0,31)]
out.print( request.getParameter(“aa”) );
// end
out.print(_jspx_html_data[1]);
--------------------
Run in browse is
follows
http://127.0.0.1:8080/examples/jsp/z.html
If you write bye in
the text box and click on the button you will see bye in the browser and in the
address bar of the browser
http://127.0.0.1:8080/examples/jsp/e26.jsp?aa=bye
If you want to read
data from a form, you can say request.getParameter(“aa”) where aa is some name
that you have given in the form. This returns bye since that is what we typed
in our text box. The form has an action which will execute the JSP code on the
server when the user clicks on the submit button. This will bring up a new page
with the url containing ?aa=bye. The JSP engine then sends the value ‘bye’ to be displayed on the
screen.
When the button named
submit is clicked, the browser will look for a tag named form and within that
tag an attribute named action. It will then create a url with action and at the
end add a ?. Now it takes all the input statements, figures out what you have
written in them and converts then to a name value pair seperated by ‘=’, like
so
aa=bye
With JSP it is very
easy to extract these values, thereby making it the preferred tool for Web
programmers.
In the following
example we have created two functions, one named jspInit and the other named
jspDestroy.
e26.jsp
<%!
public void jspInit()
{
super.jspInit();
System.out.println(“jspinit”);
}
public void jspDestroy()
{
super.jspDestroy();
System.out.println(“jspdestroy”);
}
%>
hi
----------------
public class jsp_0005ce_00032_00036_0002ejspe26_jsp_1 extends HttpJspBase {
static char[][] _jspx_html_data = null;
// begin [file=”C:\\jswdk-1.0.1\\examples\\jsp\\e26.jsp”;from=(0,3);to=(11,0)]
public void jspInit()
{
super.jspInit();
System.out.println(“jspinit”);
}
public void jspDestroy()
{
super.jspDestroy();
System.out.println(“jspdestroy”);
}
// end
---------------
Whenever a class
extends HttpJspBase, the service function within HttpJspBase is called. This
service calls jspInit once and only once when the class is loaded or
initialized. It is not like _jspservice, which is called multiple times.
jspDestroy is called when the servlet is destroyed. We will need our own
jspInit if we want to initialize our
variables or if we want certain code to be executed only once and
similarly jspDestroy can be used to release the memory used by variables or do
anything at the end. But it is difficult to pin point as to when jspDestroy
will be called. Super is used to call the code in the original class.
In the next script, we
have response.sendRedirect and within the round brackets a url has been
specified. The job of this function is to take you to the site that has been
passed as a parameter. This page then becomes the active Page.
e27.jsp
<% response.sendRedirect(“http://127.0.0.1:8080/examples/jsp/e9.jsp”); %>
Normally, one is not
supposed to write anything before or after sendRedirect. But if you do write
something, it will not be displayed.
e28.jsp
hi <p> bye
<% response.sendRedirect(“http://127.0.0.1:8080/examples/jsp/e9.jsp”); %>
no <p> good
http://127.0.0.1:8080/examples/jsp/e9.jsp
The address bar in the
browser also changes its url, which means that the browser asked for a new url.
Every http page starts
with a header. Normally, it will be 200 OK. 200 is called the http status code.
There are around 20 to 30 predefined status codes, where 200 means OK, 404 is
file not found and so on. Redirection has a status code of 304. In the next
script, we have response.setStatus.
e29.jsp
<%
response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
response.setHeader(“Location”,”/examples/jsp/e9.jsp”);
%>
SC_MOVED_PERMANENTLY
is a status code informing the browser to read the next header line because the
file has been moved. The next line sets the header variable Location to a
location or a url from where the file is to be picked up. When you use
response.sendRedirect or you use setStatus
the status code is sent over to the client with more information in the
header. When this reaches the browser, the browser asks for the new file, which
in our case is e9.jsp. Finally, the user sees e9.jsp.
Now let’s take a case
where we want the user to visit a certain page, barring which he will not be
allowed to browse our site. It’s like a login page and unless the user doesn’t
go there first, he can’t browse through the rest of the site.
e30.jsp
<%@ page session=”true” %>
login
<%
HttpSession s = request.getSession(true);
if ( s.getValue(“EID”) == null )
{
String s1 = (String ) response.encodeRedirectUrl(“e31.jsp?Origin=e30.jsp”);
System.out.println(s1);
response.sendRedirect(s1);
}
else
out.println(“<h1>hi”);
%>
e31.jsp
<%
session.putValue(“EID”,”sonal”);
String s1=(String)
response.encodeRedirectURL(request.getParameter(“Origin”));
System.out.println(“e31 “ + s1);
response.sendRedirect(s1);
%>
Also see the output in
the Java Web Server. In the browser it shows.
login
hi
Here we have two
files, e30.jsp and e31.jsp. The directive, page session=”true”, is not required
but we will retain it. Then we have login as the text to be displayed. s is a
variable that looks like HttpSession and it is initialized to the return value
of request.getSession. This function returns details of the current session.
getSession will either create a new session or will return a handle to the
current session. Of all the variables, we are currently interested in the value
of the variable EID which you must put in capital letters. Since we haven’t
declared a variable named EID, it will be null for now.
response.encodeRedirectUrl
will create a url of the string given within the brackets and return a string.
This is stored in s1. response.sendRedirect will take you straight to e31.jsp
In e31.jsp,
session.putValue creates the variable EID and initializes it to ‘sonal’.
request.getParameter will return the value of Origin, which is e30.jsp, and as
previously mentioned response.encodeRedirectUrl will convert this into a url.
Finally, there is a redirection to e30.jsp again. Within e30.jsp the value of
EID is already set, which is why you will not see login again. Instead you see
hi. This proves that both s and the session are the same.
What we are trying to
say is that as long as it is the same user on the website, he will not have to
login again, but if the user shuts down the browser and starts another copy,
the entire process has to be repeated. The next program provides further
insight into sessions.
e32.jsp
<%@ page session=”true” %>
hi
<%
HttpSession s = request.getSession(true);
s.putValue(“vij”,”sonal”);
%>
e33.jsp
<%@ page session=”true” %>
Bye
<%
HttpSession s = request.getSession(true);
%>
<%= s.getValue(“vij”) %>
In e32.jsp, we first
write hi. request.getSession will return the current session handle which is
stored in s. Then s.putValue will create ‘vij’ if not present and initialize it
to ‘sonal’.
The next page where we
have bye is along the same lines as earlier. s is a handle to HttpSession.
s.getValue of vij will return ‘sonal’.
We first want you to
run e33.jsp. Here, you will see bye and null because at the moment vij has no
value. After doing so, run e32.jsp. You
will see hi on this page and now once again reload e33.jsp. You will see
‘sonal’ displayed on your screen.
The point to be noted
here is that there are two types of objects, implicit objects and explicit
objects. Session and out are examples of implicit objects; they are already
created. The explicit objects are not created by default, they have to be
created and initialized. This is what you will learn in the next chapter.
Applets are not
allowed to write data to disk but with servlets no such rules apply. The next example confirms this.
e34.jsp
<%@ page import=”java.io.*” isErrorPage=”true” %>
<%
try
{
PrintWriter p=new PrintWriter(new FileOutputStream(“pp.txt”));
p.println(“hi”);
p.close();
}
catch ( Exception e) {
e.printStackTrace();
}
%>
C:\jswdk-1.0.1>dir pp.txt
Volume in drive C is SONAL
Volume Serial Number is 0661-13EE
Directory of C:\jswdk-1.0.1
PP TXT 4 06-13-00 3:15p pp.txt
1 file(s) 4 bytes
0 dir(s) 2,652.13 MB free
C:\jswdk-1.0.1>type pp.txt
hi
FileOutputStream is
used when you want to open a particular file in output mode i.e. for writing.
Since the file named pp.txt is not present on the disk, it will first be
created. To write to this file you need a handle to it. new PrintWriter will
return a handle to this file, so p now becomes a pointer to pp.txt. We then say
p.println (“hi”) which will write the text ‘hi’ to the file. You can give the
complete path along with the filename, or use the default which is the
jswdk-1.0.1 subdirectory. If you want to read from a file then use
FileInputStream instead of FileOutputStream.
When you execute the
command ‘type pp.txt’ in c:\jswdk-1.0.1, it will print hi on the screen.
For the grand finale
of this chapter, we have one last example.
The web-inf directory
has a file named servlet.properties. This example prints the properties and
their values within this file. We had
done something similar in the servlet chapter. We have not shown you the
contents of this file as it will obviously differ on your machine.
e35.jsp
<%@ page import=”java.util.*” %>
<%!
ServletConfig cfg;
public void jspInit()
{
cfg = getServletConfig();
for ( Enumeration e = cfg.getInitParameterNames(); e.hasMoreElements();){
String name = (String) e.nextElement();
String value = cfg.getInitParameter(name);
System.out.println(name+”=”+value);
}
}
%>
keepgenerated=true
servlet.properties has
things like keepgenerated=true. This property, if it is true, will not delete
the Java code from the work directory once it has been created and compiled.
Normally, when you
have errors, you would like them to be displayed on your web page and not on
the console of the web server. To do so, you say setErrorToClient=true. The
client will now see the errors in his browser. They will now nolonger be
displayed on the server console.
In our program,
getServletConfig allows us to find the parameters that have been set by the
Java Web Server. This returns an object that looks like ServletConfig().
cfg.getInitParameterNames() returns an enumeration which in turn has a member
hasMoreElements. e.nextElement gives us the name of the element and
getInitParameter along with the name will tell us its value. Thus, they are all
stored as a name-value pair. Since we only have one property at the moment, it
will display keepgenerated and its value true and then the for loop will
terminate.
Conclusion
Java Server Pages
bring together the power of Java Servlets and HTML coding thereby give the
developers a powerful method to create Server-Side web applications. In this
chapter, we learnt the following:
A Java Server Page
file consists of HTML tags, content, JSP directives, JSP declarations, JSP
scriptlets and action tags. Initially, the JSP engine parses the JSP file which
then generates a new servlet with the desired content. If the file changes,
then a new servlet is generated; otherwise, the compiled version is used.