Java Server Pages

 

ANT – Another Neat Tool

Working with Java Server Pages or J2EE demands understanding the tool Ant. Ant is part of the Jakarta Tomcat project and the tool basically replaces the Make tool.

 

The Make tool was used to build applications, however due to it having a cryptic syntax it was difficult to use. Also it lacks a lot of useful features and remained unportable to other operating systems like Windows. The developers of Tomcat required a build tool other than the make utility to build Tomcat so they createad their own tool called Ant. Since the tool is written in Java portability was not an issue anymore. Also the file containing the build instructions for Ant was placed in an XML file.

 

Now lets understand how to use ant. If you have installed the binaries of J2EE properly, there is a batch file called ant.bat in the bin subdirectory that calls Ant. If we run it, we will get the following error.

 

C:\Sun\AppServer\lib\ant\bin>Ant

Buildfile: build.xml does not exist!

Build failed

 

Make sure the environmental variables are set for eg:

 

Set JAVA_HOME= C:\Sun\AppServer\jdk

 

Thus the ant program by default looks for its build instructions in a file called build.xml by default. This is to the make or nmake program that looks at the file Makefile.

 

Lets first try and run the Ant program without the bat file.

 

>java org.apache.tools.ant.Main

 

As Ant is a Java program with a Main function , the java program is used to execute it along with the class file name and namespace of the class that contains the Main function. The only problem is we forgot to specify the  classpath or the jar file where the above the class resides.

 

C:\Sun\AppServer\lib\ant\bin>set CLASSPATH=%JAVA_HOME%\lib\classes.zip;%JAVA_HOME%\lib\tools.jar;C:\Sun\AppServer\lib\ant\lib\ant.jar

 

>java org.apache.tools.ant.Main

 

The above command now displays the same error as seen earlier.

 

The ant utiltiy requires a file by the name of build.xml. Since the file is not present in the current directory, the error is reported. So lets create this file.

 

C:\Sun\AppServer\lib\ant\bin>notepad build.xml

(empty)

 

C:\Sun\AppServer\lib\ant\bin>ant

Buildfile: build.xml

 

BUILD FAILED

file:C:/Sun/AppServer/lib/ant/bin/build.xml:1: Premature end of file.

 

Total time: 5 seconds

 

Due to the presence of build.xml file, the error displayed is very different from the earlier one. Since the file has no contents, it is assumed that it does not follow the rules of a build file . Key in the following lines in the file.

 

Build.xml

<project >

</project >

 

C:\Sun\AppServer\lib\ant\bin>ant

Buildfile: build.xml

 

BUILD FAILED

file:C:/Sun/AppServer/lib/ant/bin/build.xml:1: The default attribute of project

is required

 

Total time: 4 seconds

 

Every build.xml file must start with a tag project. Besides, these tags have attributes of which some are mandatory. The project tag requires the default attribute.

 

Build.xml

<project default="vijay">

</project >

 

C:\Sun\AppServer\lib\ant\bin>ant

Buildfile: build.xml

 

BUILD FAILED

Target `vijay' does not exist in this project.

 

Total time: 4 seconds

 

We have added an attribute default to the project with its value as vijay. This word is taken to be the name of a target, which is not yet specified. Hence the error.

 

Build.xml

<project default="vijay">

<target name="vijay" >

</target>

</project >

 

C:\Sun\AppServer\lib\ant\bin>ant

Buildfile: build.xml

 

vijay:

 

BUILD SUCCESSFUL

Total time: 4 seconds

 

Finally no errors at all. The target name gets displayed on the screen along with a build successful message. This goes to prove that the ant program opens the file build.xml and looks out for the project tag first. It then reads the default attributes value and thereupon it looks for a target tag with the same name. Once it finds everything in proper order it executes all the tags within this tag. Since we have none, nothing great happens.

 

Build.xml

<project default="vijay">

<target name="vijay" >

<echo message="hi" />

</target>

</project >

 

vijay:

     [echo] hi

 

The above xml file has a tag called echo. These tags are called tasks by the Ant documentation. It has an attribute called message which gets displayed in the dos box. The echo task is like the println function, it displays messages for the user. This also proves that the task vijay did actually get called.

 

The echo task can do many more things like writing to a file on disk.

 

Build.xml

<project default="vijay">

<target name="vijay" >

<property name="mukhi" value="great man" />

<echo message="hi ${mukhi}" />

</target>

</project >

 

vijay:

     [echo] hi great man

 

We use the task property to create an entity called property. A property has a name and a value. In the above file, the property is given the name of mukhi  with a value of great man. To use a property, it must be placed in curly braces with a dollar sign in front of it.

 

Thus wherever a word is seen in curly braces and a dollar sign in front, it is considered to be a property. A property is like a variable and is used extensively in ant build files. There are five built in properties.

 

Build.xml

<project default="vijay">

<target name="vijay" >

<property environment ="zzz"/>

<echo message="ANT_HOME ${zzz.ANT_HOME}"/>

</target>

</project >

 

vijay:

     [echo] ANT_HOME C:\Sun\AppServer\lib\ant\bin\..

 

An operating system has a large number of environmental variables. These variables can be accessed using the property attribute environment. The value of zzz is given to it, which now will carry all these environmental variables. Now to display any environmental variables, it must begin with zzz followed by a dot and the name of the environmental variable, in our case ANT_HOME.

 

These environmental variables can be read from a file on disk too.

 

ggg.aaa

name=vijay

password=mukhi

 

build.xml

<project default="vijay">

<target name="vijay" >

<property file="ggg.aaa"/>

<echo message="${name} ${password}"/>

</target>

</project >

 

vijay:

     [echo] vijay mukhi

 

A file called ggg.aaa is created with two name-value pairs. The name-value pair start with the name of the property, an equal to sign followed by the value of the property. The echo displays these two properties of name and password task.

 

Build.xml

<project default="vijay">

<target name="vijay" >

<property name="fname" value="ggg" />

<property file="${fname}.aaa"/>

<echo message="${name} ${password}"/>

</target>

</project >

 

vijay:

     [echo] vijay mukhi

 

We go a step further. A property called fname is created and given a value of ggg. A property name can be specified anywhere. In the file attribute for the property task, we specify the file name partly as a value of a property and partly as the actual value. A perfect example displaying the use of properties in Ant extensively. The name of file can contain a path also which can be specified using a property value.

 

Build.xml

<project default="vijay">

<target name="vijay" depends="mukhi,sonal">

<echo message="task vijay"/>

</target>

<target name="mukhi" >

<echo message="task mukhi"/>

</target>

<target name="sonal" >

<echo message="task sonal"/>

</target>

</project >

 

Buildfile: build.xml

 

mukhi:

     [echo] task mukhi

 

sonal:

     [echo] task sonal

 

vijay:

     [echo] task vijay

 

The above example illustrates the real power of  ant. The depends attribute is put to use to specify the other targets that must be completed before the target mukhi can be executed. Thus ant first executes the target mukhi and then sonal before it comes to executing the default target vijay.

 

This is the heart and soul of build. It first finds out all the dependencies and then executes them in a certain order.

 

Build.xml

<project default="vijay">

<target name="vijay" depends="mukhi">

<echo message="task vijay"/>

</target>

<target name="mukhi" depends="sonal">

<echo message="task mukhi"/>

</target>

<target name="sonal" >

<echo message="task sonal"/>

</target>

</project >

 

sonal:

     [echo] task sonal

 

mukhi:

     [echo] task mukhi

 

vijay:

     [echo] task vijay

 

In the next example, target vijay only depends on target mukhi. When ant tries to execute the target mukhi, it realizes that it depends upon target sonal. As a result, it first executes target sonal, then mukhi and then vijay.

 

Build.xml

<project default="vijay">

<target name="vijay" depends="mukhi">

<echo message="task vijay"/>

</target>

<target name="mukhi" depends="sonal">

<echo message="task mukhi"/>

</target>

<target name="sonal" depends="mukhi">

<echo message="task sonal"/>

</target>

</project >

 

BUILD FAILED

Circular dependency: mukhi <- sonal <- mukhi

 

You cannot beat the ant system. In the above example, the default target vijay depends upon target mukhi. When the ant system goes to the target mukhi, it realizes that it depends upon the target sonal. This target sonal now depends upon the target mukhi. This becomes a circular reference. The error reported proves that by no means you can send ant into an indefinite loop.

 

Build.xml

<project default="vijay">

<target name="vijay">

<echo message="task vijay"/>

</target>

<target name="mukhi">

<echo message="task mukhi"/>

</target>

</project>

 

C:\Sun\AppServer\lib\ant\bin>ant

Buildfile: build.xml

 

vijay:

     [echo] task vijay

 

BUILD SUCCESSFUL

Total time: 5 seconds

C:\Sun\AppServer\lib\ant\bin>ant mukhi

Buildfile: build.xml

 

mukhi:

     [echo] task mukhi

 

BUILD SUCCESSFUL

Total time: 4 seconds

 

The default behavior of executing the target with the default attribute can be changed. To override this default behavior, we simply pass the name of the target as a parameter to the bat file. The task associated with the target will be executed.

 

Thus in the above build.xml file, instead of the task vijay getting called, the task mukhi gets executed.

 

Build.xml

<project default="vijay">

<target name="vijay">

<copy file="ggg.aaa" tofile="ggg.bbb"/>

</target>

</project>

 

vijay:

     [copy] Copying 1 file to C:\Sun\AppServer\lib\ant\bin

 

One of the major tasks that ant must perform is copying files to various directories. This is called the deploy task. Thus the simplest use of the copy task is to copy a source file specified by the file attribute to the destination file name that is specified by the tofile attribute.

 

Build.xml

<project default="vijay">

<target name="vijay">

<copy file="ggg.aaa" todir=".."/>

</target>

</project>

 

vijay:

     [copy] Copying 1 file to C:\Sun\AppServer\lib\ant

 

By now you must have realized that we are running our build.xml in the ant\bin sub-directory. We would like to copy the same file, to our parent directory. For this purpose, the todir attribute is made to point to our parent directory, thereupon leaving it to the copy task to do its job. The copy task has some more complex options that will be touched upon a little later.

 

Now lets copy an entire subdirectory at a time. For this purpose, the task to be used is copydir. But first we create two sub-directories called a1 and a2 under the bin subdirectory. We then create three files, a.java, b.java and c.txt within sub-directory a1 and then run the below given build.xml file.

 

Build.xml

<project default="vijay">

<target name="vijay">

<copydir src="./a1" dest="./a2" />

</target>

</project>

 

Buildfile: build.xml

 

vijay:

  [copydir] DEPRECATED - The copydir task is deprecated.  Use copy instead.

  [copydir] Copying 3 files to C:\Sun\AppServer\lib\ant\bin\a2

 

BUILD SUCCESSFUL

 

The src attribute specifies the source directory and a single dot, if you have forgotten, denotes the current position. Normally these values are set using properties. The dest attribute obviously specifies the destination directory.

 

The ant output tells us that the copydir task is deprecated and we should have used the earlier copy task instead. What deprecation means in the java world is that the previously distributed task copydir in the sdk has now been recognized to be a bad idea. However, they cannot throw it away as lots of build files would be using this task copydir. Thus the ant people would like to remove this task copydir, but they cannot as older build files will stop working. So by deprecating it, they are issuing notices that they will remove it in the future, but cannot say when. By our experience, the next century is when deprecate items finally get knocked off.

 

Run ant again and the files do not get copied as the source files have not changed, thus it makes no sense to copy them again.

 

vijay:

  [copydir] DEPRECATED - The copydir task is deprecated.  Use copy instead.

  [copydir] Copying 1 file to C:\Sun\AppServer\lib\ant\bin\a2

 

Change the contents of one file only a.java in directory a1 and ant is smart enough to copy only this file. Change the file b.java in the sub-directory a2, and no file gets copied. 

 

Thus to try out the next set of build files, always delete all files in the sub-directory a2.

 

Build.xml

<project default="vijay">

<target name="vijay">

<copydir src="./a1" dest="./a2" includes="*.java"/>

</target>

</project>

 

vijay:

  [copydir] DEPRECATED - The copydir task is deprecated.  Use copy instead.

  [copydir] Copying 2 files to C:\Sun\AppServer\lib\ant\bin\a2

 

The includes attribute restricts the copy of only those files that meet a condition. In this case we only want the files with a java extension to be copied. Thus only files a.java and b.java get copied and the file c.txt gets left behind.

 

Build.xml

<project default="vijay">

<target name="vijay">

<copydir src="./a1" dest="./a2" includes="*.java" excludes="b*.*" />

</target>

</project>

 

vijay:

  [copydir] DEPRECATED - The copydir task is deprecated.  Use copy instead.

  [copydir] Copying 1 file to C:\Sun\AppServer\lib\ant\bin\a2

 

The excludes option does the reverse, it excludes all those files that meet the condition. In our case, all files that start with the character b are to be ignored, thus only one file gets copied.

 

We now create a sub-directory z1 under a1 and copy two files to it, d.java and e.java. Mind you we do not create a sub-directory z1 under a2.

 

<project default="vijay">

<target name="vijay">

<copydir src="./a1" dest="./a2" />

</target>

</project>

 

vijay:

  [copydir] DEPRECATED - The copydir task is deprecated.  Use copy instead.

  [copydir] Copying 5 files to C:\Sun\AppServer\lib\ant\bin\a2

 

When we run ant it tells us that it copies 5 files and also creates the sub-directory z1 within a2. Thus the includes and excludes should start with ** to denote all subdirectories as include=”**/*.java”. Thus we can start these attributes with a subdirectory name like /a1/z1.

 

After copy the next task is to delete what we have copied.

 

Build.xml

<project default="vijay">

<target name="vijay">

<delete file="./a1/a.java"/>

</target>

</project>

 

vijay:

   [delete] Deleting: C:\Sun\AppServer\lib\ant\bin\a1\a.java

 

We simply use the delete task and set the file attribute to the name of the file that is to be deleted.

 

Build.xml

<project default="vijay">

<target name="vijay">

<delete dir="./a1"/>

</target>

</project>

 

vijay:

   [delete] Deleting directory C:\Sun\AppServer\lib\ant\bin\a1

 

To delete a sub-directory and all the directories below it, the dir attribute is used instead of the file attribute.

 

<project default="vijay">

<target name="vijay" depends="a1,a2">

<echo message="in vijay" />

</target>

<target name="a1" if="mukhi">

<echo message="in a1" />

</target>

<target name="a2" unless="mukhi">

<echo message="in a2" />

</target>

</project>

 

a1:

 

a2:

     [echo] in a2

 

vijay:

     [echo] in vijay

 

In the above build.xml, the target vijay depends upon two targets a1 and a2. Ant goes to the first target a1, but before executing it, it sees the if attribute. This attribute asserts that the target should only be executed if the property mukhi has been created. Since this is not the case, the target does not get executed.

 

The second target a2 uses an unless that is the reverse of the if. In this case the property mukhi should not be set for the target to be executed thus, it leads to executing target a2 and not a1.

 

Build.xml

<project default="vijay">

<property name="mukhi" value="hi" />

<target name="vijay" depends="a1,a2">

<echo message="in vijay" />

</target>

<target name="a1" if="mukhi">

<echo message="in a1" />

</target>

<target name="a2" unless="mukhi">

<echo message="in a2" />

</target>

</project>

 

 

a1:

     [echo] in a1

 

a2:

 

vijay:

     [echo] in vijay

 

The only change in the file is the newly created property called mukhi. The if attribute becomes true and target a1 gets executed. The unless is now false and thus the target a2 does not get executed.

 

Build.xml

<project default="vijay">

<target name="vijay">

<mkdir dir="a3" />

</target>

</project>

 

vijay:

    [mkdir] Created dir: C:\Sun\AppServer\lib\ant\bin\a3

 

The task mkdir has only one attribute dir which creates a directory. In the above case the sub-directory is called a3.

 

Build.xml

<project default="vijay">

<target name="vijay">

<sun-appserv-input message="User Name" addproperty="zzz" />

<echo message="You typed ${zzz}" />

</target>

</project>

 

You typed mukhi

 

>Asant

 

Many a times, some interaction is required with the user, some input is taken from the user. The task sun-appserv-input takes two attributes, the message to display something for the user and the attribute addproperty for name of the property that will contain the user input.

 

The system prompts the message. Since we have keyed in Mukhi, the value gets stored in the property zzz which eventually is displayed using the echo task. For reasons to be explained later the ant batch file does not work here. There is another batch file asant with the J2EE distribution, which is to be used.

 

Build.xml

<project default="vijay">

<target name="vijay">

<zip destfile="a.zip" basedir="./a3" />

</target>

</project>

 

vijay:

      [zip] Building zip: C:\Sun\AppServer\lib\ant\bin\a.zip

 

Java does not like working with individual files and prefers working with one file that contains loads of other files. This file is normally a compressed archive file. The Zip file format is the most popular archive, thus we have a task just to create a zip file.

 

This task requires the name of the zip file as the value of the destfile attribute and the directory containing files to be zipped as the basedir attribute. In our case our directory is a3, the current location or basedir and the name of the zip file is a.zip. Also, with the Ant tool, you can also use the includes and excludes attributes to filter out the files required.

 

Java Server Pages

 

Lets us now take a practical application to showcase the power of the ant tool. We would like to deploy a Java Server pages or JSP file. The concept of Java Server Pages is similar to ASP.Net, which is nothing but code in a html page. We cannot simply place a jsp page somewhere and expect the J2EE server to execute it.

 

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.

 

The jsp page normally contains all the presentation logic whereas the business logic is stored in Enterprise Java Beans or EJB’s.

 

First of all start the default domain server

Start-Programs- Sun Microsystems- J2ee 1.4 SDK – Start Default Server

 

First within the root create a new subdirectory called myprg.

Make sure the path is set

 

C:\myprg>set path=c:\sun\appserver\lib\ant\bin;%PATH%

 

For sake of convenience we have created a batch file in myprg

 

aa.bat

Set JAVA_HOME= C:\Sun\AppServer\jdk

set CLASSPATH=%JAVA_HOME%\lib\classes.zip;%JAVA_HOME%\lib\tools.jar;

C:\Sun\AppServer\lib\ant\lib\ant.jar

set path=c:\sun\appserver\lib\ant\bin;%PATH%

 

Then create a sub-directory a1 below myprg and write the following in a file a.jsp.

 

C:\myprg\a1>edit e1.jsp

e1.jsp

Hi

 

The server obviously needs more information on how to deploy this jsp file.

 

For the newbie, the jsp file is converted into java code and then into a java servlet and then executed by the server. Thus we have other entities that we may want to package together like images, graphic or sound files, EJB’s etc. We have a war file or a Web Application Archive that puts multiplies entities together.

 

A war file is nothing but a zip file. To create a war file, we need a file web.xml that configures our web application.  Create this file in the myprg subdirectory.

 

C:\myprg>edit web.xml

 

Web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app>

</web-app>

 

This file being a xml file should start with the mandatory ?xml element. It has only one element the root element called web-app. As of now it contains no other element. Then create the build file.

 

Build.xml

<project default="vijay">

<target name="vijay">

<property name="fname"  value="zzz.war" />

<war destfile="${fname}" webxml="web.xml" basedir="./a1" >

</war>

</target>

</project>

 

Our build.xml will now build the war file using the task war. We have also created a property fname that specifies the name of the war file to be created. Most samples use properties instead of actual values. In the war task, we first use the attribute destfile to specify the name of the war file zzz.war.

 

The mandatory webxml attribute is used to specify the name of the Web Application Descriptor file which is normally web.xml. The basedir attribute tells the war task which directory contains the jsp and other files to be packaged or archived. In our case we would like all files in the a1 sub-directory to be put together.

 

When we run ant, a file zzz.war gets created in the directory myprg. Use the winzip program to uncompress the file in the dummy4 directory. The following is the directory structure in dummy4.

 

Directory of C:\dummy4

 

02/22/2004  11:29a      <DIR>          .

02/22/2004  11:29a      <DIR>          ..

02/22/2004  11:29a      <DIR>          META-INF

02/21/2004  11:24a                   6 e1.jsp

02/22/2004  11:29a      <DIR>          WEB-INF

02/22/2004  11:29a                   0 z

 

 Directory of C:\dummy4\META-INF

02/22/2004  11:29a      <DIR>          .

02/22/2004  11:29a      <DIR>          ..

02/22/2004  11:29a                 107 MANIFEST.MF

 

Directory of C:\dummy4\WEB-INF

02/22/2004  11:29a      <DIR>          .

02/22/2004  11:29a      <DIR>          ..

02/22/2004  10:41a                 142 web.xml

 

Our only file a.jsp in the a1 directory gets placed in the root directory. Two other directories Meta-Inf and Web-Inf get created which were not there in our directory structure. The file web.xml gets placed in the web-inf directory and a new file Manifest.mf gets placed in the meta-inf directory. The contents of this file are as.

 

Manifest.mf

Manifest-Version: 1.0

Ant-Version: Apache Ant 1.5.4

Created-By: 1.4.2_04-b04 (Sun Microsystems Inc.)

 

Nothing really useful. The above directory structure gets created and the JSP and Servlet specifications specify the above format. The war task does the job of placing things in the right place.

 

Once the war file is created, we have to deploy it to the server. For this we have to run a bat file called asadmin.bat that like all bat files is present in the bin directory under appserver of the J2ee distribution.  This file does nothing but call the java program on some class file.

 

We have to run this batch file with the following options.

 

C:\myprg> C:/Sun/AppServer/bin/asadmin deploy --user admin --password vijay712 --host office --port 4848 zzz.war

 

Command deploy executed successfully.

 

The deploy option tells the asadmin utility to deploy a web application file which in our case is the last parameter zzz.war. There are four parameters that need to supplied to the deploy option.

 

The first is the user name admin, the second is our password vijay712, the third is the name of the host machine running the j2ee server office and lastly the port number the admin server is listening on 4848.

 

Then start the web browser to test the installation of the application. We write the URL http://localhost:8080/zzz. There are no errors and on the screen we see a list of files present in the war file. In our case as we have only one file a.jsp, we see only one file.

 

When we click on this file e1.jsp, the J2EE server first converts it into a java servlet program, compiles it and then runs it. This is why we get a slight delay in seeing the output.

 

Web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app>

<welcome-file-list>

<welcome-file>a.jsp</welcome-file>

</welcome-file-list>

</web-app>

 

Modify the web.xml file to add one more element, welcome-file-list. Within it bring in  another element welcome-file, and specify the file a.jsp. Thus whenever we do not specify a servlet or jsp file name, the file a.jsp will get displayed instead of a list of files.

 

 

The next change is in the build.xml file.

 

Build.xml

<project default="vijay">

<target name="vijay">

<property name="fname"  value="zzz.war" />

<war destfile="${fname}" webxml="web.xml" basedir="./a1" >

</war>

<exec executable="cmd.exe" >

<arg line=" /c C:/Sun/AppServer/bin/asadmin" />

<arg line=" deploy"/>

<arg line=" --user admin"/>

<arg line=" --password vijay712"/>

<arg line=" --host office"/>

<arg line=" --port 4848"/>

<arg line="${fname}"/>

</exec>  

</target>

</project>

 

In the build file, we combine the building of the war file and deployment in one step. Instead of calling the batch file separately, we use the task exec to run the asadmin batch file. The exec task requires the name of the executable in the executable attribute.

 

The cmd.exe is the program that creates the dos box for us. Then we specify all the parameters using the arg element and the line attribute. For the sake of clarity we specify them on multiple lines. Thus on running ant, we are building the war file and deploying it with a minimum of fuss.

 

Further on, these values could be picked up from a file ‘common.properties’ too.  The following file demonstrates the same

 

Build.xml

<project default="vijay">

<target name="vijay">

<property name="fname"  value="zzz.war" />

<property file=" c:/sun/appserver/samples/common.properties " />

<war destfile="${fname}" webxml="web.xml" basedir="./a1" >

</war>

<exec executable="cmd.exe" >

<arg line=" /c C:/Sun/AppServer/bin/asadmin" />

<arg line=" deploy"/>

<arg line=" --user ${admin.user}"/>

<arg line=" --password ${admin.password}"/>

<arg line=" --host ${admin.host}"/>

<arg line=" --port ${admin.port}"/>

<arg line="${fname}"/>

</exec>  

</target>

</project>

 

There is a file called common.properties in the directory c:/sun/appserver/samples/ that contains the user name, password, port number and host name. Thus instead of specifying these names ourselves, we use the file attribute as shown earlier to read this file and all the properties in it.

 

We then use these properties names instead of hard coding them. We are also displaying the contents of this file as per our machine.

 

Common.properties

#Sat Jan 17 11:50:02 GMT+05:30 2004

domain.name=domain1

com.sun.aas.javaRoot=C\:/Sun/AppServer/jdk

admin.host=office

admin.port=4848

com.sun.aas.installRoot=C\:/Sun/AppServer

appserver.instance=server

appserver.instance.port=8080

admin.user=admin

admin.password=vijay712

 

Reload e1.jsp file in the browser. The browser initially takes a long time to show you the result, however it is faster when the file is reloaded.

 

And Congratulations! You have written the world's smallest JSP program.

 

Now switch over to the command box and change to the directory

 

C:\Sun\AppServer\domains\domain1\generated\jsp\j2ee-modules>

 

A dir command here displays a subdirectory zzz with the other files and directories. Move into zzz and further into org\apache\jsp. Listing the directory contents here will show a file e1_jsp.java. The contents of this file are shown below.

 

e1_jsp.java

package org.apache.jsp;

 

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

 

public final class e1_jsp extends org.apache.jasper.runtime.HttpJspBase

    implements org.apache.jasper.runtime.JspSourceDependent {

 

  private static java.util.Vector _jspx_dependants;

 

  public java.util.List getDependants() {

    return _jspx_dependants;

  }

 

  public void _jspService(HttpServletRequest request, HttpServletResponse response)

        throws java.io.IOException, ServletException {

 

    JspFactory _jspxFactory = null;

    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 {

      _jspxFactory = JspFactory.getDefaultFactory();

      response.setContentType("text/html");

      response.addHeader("X-Powered-By", "JSP/2.0");

      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("hi\r\n");

    } catch (Throwable t) {

      if (!(t instanceof SkipPageException)){

        out = _jspx_out;

        if (out != null && out.getBufferSize() != 0)

          out.clearBuffer();

        if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);

      }

    } finally {

      if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);

    }

  }

}

 

Open this Java file in notepad, keeping in mind that it has been created by the Java Web Server.

 

The JSP file that you ran from the browser was converted into a servlet. 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" %. Just a reminder, always run ant and then asadmin command.

 

Also, make sure that you are not within the zzz directory as the asadmin command renames this directory to zzz_old. The error reported at such moments is

 

CLI171 Command deploy failed : Deployment Error -- Could not rename C:\Sun\

AppServer\domains\domain1\generated\jsp\j2ee-modules\zzz to C:\Sun\AppServer\domains\domain1\generated\jsp\j2ee-modules\zzz_old

 

Follow the steps as given below once the jsp file is ready to be deployed (server should be running)

 

C:\myprg>del zzz.war

C:\myprg>ant

C:\myprg>C:/Sun/AppServer/bin/asadmin deploy --user admin --password vijay712 --host office --port 4848 zzz.war

 

 

e2.jsp

hi

<%= "bye" %>

no

 

The browser window shows hi, bye, no on a single line.

Let's understand what we have just done. When the browser is requested to open e2.jsp, the JSP engine takes over charge. It sees the tag '<%' whereby 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 with the string given in double quotes as a parameter to print. It automatically brings in the open and close bracket and a semicolon at the end.

---------------

 

      out.write("hi\r\n");

      out.print( "bye" );

      out.write("\r\n");

      out.write("no\r\n");

 

---------------------

Now in place of the '=' sign in the JSP file and enter out.println ("no");

 

e3.jsp

hi

<% out.println("no"); %>

bye

------------------------

 

      out.write("hi\r\n");

      out.println("no");

      out.write("\r\n");

      out.write("bye\r\n");

---------------------

 

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 is introduced in the file as is for 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

 

No Output in Browser

The server log shows the following:

 

[#|2004-10-18T15:16:38.239+0530|SEVERE|sun-appserver-pe8.0|org.apache.jasper.compiler.Compiler|_ThreadID=11;|Env: Compile: javaFileName=/C:/Sun/AppServer/domains/domain1/generated/jsp/j2ee-modules/zzz//org/apache/jsp\e4_jsp.java

    classpath=/C:/Sun/AppServer/domains/domain1/applications/j2ee-modules/zzz/WEB-INF/classes/;C:\Sun\AppServer\domains\domain1\generated\jsp\j2ee-modules\zzz;/C:/Sun/AppServer/domains/domain1/applications/j2ee-modules/zzz/WEB-INF/classes/;

    cp=C:\Sun\AppServer\lib\commons-launcher.jar;C:\Sun\AppServer\lib\activation.jar;C:\Sun\AppServer\lib\appserv-cmp.jar;C:\Sun\AppServer\lib\j2ee-svc.jar;C:\Sun\AppServer\lib\jaxr-api.jar;C:\Sun\AppServer\lib\admin-cli.jar;C:\Sun\AppServer\lib\appserv-admin.jar;C:\Sun\AppServer\lib\appserv-jstl.jar;C:\Sun\AppServer\lib\commons-logging.jar;C:\Sun\AppServer\lib\jax-qname.jar;C:\Sun\AppServer\lib\jaxr-impl.jar;C:\Sun\AppServer\lib\jaxrpc-api.jar;C:\Sun\AppServer\lib\jaxrpc-impl.jar;C:\Sun\AppServer\lib\mail.jar;C:\Sun\AppServer\lib\relaxngDatatype.jar;C:\Sun\AppServer\lib\saaj-api.jar;C:\Sun\AppServer\lib\saaj-impl.jar;C:\Sun\AppServer\lib\xsdlib.jar;C:\Sun\AppServer\lib\appserv-rt.jar;C:\Sun\AppServer\lib\jsf-api.jar;C:\Sun\AppServer\lib\jsf-impl.jar;C:\Sun\AppServer\lib\appserv-upgrade.jar;C:\Sun\AppServer\lib\appserv-ext.jar;C:\Sun\AppServer\lib\j2ee.jar;C:/Sun/AppServer/jdk/lib/tools.jar;C:/Sun/AppServer/lib/install/applications/jmsra/imqjmsra.jar;C:/Sun/AppServer/imq/lib/jaxm-api.jar;C:/Sun/AppServer/imq/lib/fscontext.jar;C:/Sun/AppServer/lib/ant/lib/ant.jar;C:/Sun/AppServer/pointbase/lib/pbclient.jar;C:/Sun/AppServer/pointbase/lib/pbembedded.jar

    cp=C:\Sun\AppServer\domains\domain1\applications\j2ee-modules\zzz\WEB-INF\classes

    cp=C:\Sun\AppServer\domains\domain1\generated\jsp\j2ee-modules\zzz

    cp=C:\Sun\AppServer\domains\domain1\applications\j2ee-modules\zzz\WEB-INF\classes

    work dir=C:\Sun\AppServer\domains\domain1\generated\jsp\j2ee-modules\zzz

    extension dir=C:/Sun/AppServer/jdk/jre/lib/ext;C:/Sun/AppServer/domains/domain1/lib/ext

    srcDir=C:\Sun\AppServer\domains\domain1\generated\jsp\j2ee-modules\zzz

    include=org/apache/jsp/e4_jsp.java

|#]

 

[#|2004-10-18T15:16:38.239+0530|SEVERE|sun-appserver-pe8.0|org.apache.jasper.compiler.Compiler|_ThreadID=11;|Error compiling file: /C:/Sun/AppServer/domains/domain1/generated/jsp/j2ee-modules/zzz//org/apache/jsp\e4_jsp.java     [javac] Compiling 1 source file

    [javac] C:\Sun\AppServer\domains\domain1\generated\jsp\j2ee-modules\zzz\org\apache\jsp\e4_jsp.java:44: cannot resolve symbol

    [javac] symbol  : variable bye

    [javac] location: class org.apache.jsp.e4_jsp

    [javac]       out.print( bye );

    [javac]                  ^

    [javac] 1 error

 

|#]

 

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

 

Output in Server log

[#|2004-10-18T17:23:58.625+0530|INFO|sun-appserver-pe8.0|javax.enterprise.system.stream.out|_ThreadID=12;|

no|#]

---------

      out.write("hi\r\n");

 System.out.println("no");

      out.write("\r\n");

      out.write("bye\r\n");

-------

 

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 log. 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 nine 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().

 

    JspFactory _jspxFactory = null;

    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;

 

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; %>

 

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

-----------

public final class e6_jsp extends org.apache.jasper.runtime.HttpJspBase

    implements org.apache.jasper.runtime.JspSourceDependent {

 

 int j;

-----------

Whenever you put any statement in <%, it is placed in jspservice and becomes local.

----------

      out.write("hi\r\n");

      out.write("\r\n");

      out.write("bye\r\n");

 int i;

      out.write('\r');

      out.write('\n');

--------------

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.write("hi\r\n");

 int i = 6;

if ( i == 6 )

      out.write("\r\n");

      out.write("bye\r\n");

-------------------

 

 

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.

 

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

---------

for (int i = 1; i<= 4 ; i++) {

      out.write("\r\n");

      out.write("<H");

      out.print(i);

      out.write(">Hello</H");

      out.print(i);

      out.write('>');

      out.write('\r');

      out.write('\n');

 }

      out.write("\r\n");

      out.write("hi\r\n");

----------------

 

View Source

 

<H1>Hello</H1>

 

<H2>Hello</H2>

 

<H3>Hello</H3>

 

<H4>Hello</H4>

 

hi

 

 

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

 

Comments are not visible hence they can be safely ignored. They are present only in the JSP file and will not be seen in the servlet. Comments given in the jsp file get hidden from the client as it is on the server. In case you do want comments, then use of html comments <!-  would be more appropriate.

 

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.*" %>

 

-------

import javax.servlet.*;

import javax.servlet.http.*;

import javax.servlet.jsp.*;

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 final class e12_jsp extends java.util.Dictionary

    implements org.apache.jasper.runtime.JspSourceDependent {

-------------

 

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" %>

 

------

[#|2004-10-19T14:40:44.873+0530|SEVERE|sun-appserver-pe8.0|javax.enterprise.system.container.web|_ThreadID=13;|StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception

org.apache.jasper.JasperException: /e13.jsp(2,0) Page directive has invalid attribute: implements

----------

 

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

 

--------------

[#|2004-10-19T14:47:45.118+0530|SEVERE|sun-appserver-pe8.0|javax.enterprise.system.container.web|_ThreadID=11;|StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception

org.apache.jasper.JasperException: /e14.jsp(1,1) Page directive: invalid value for buffer

--------------

 

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 final class e15_jsp extends org.apache.jasper.runtime.HttpJspBase

    implements org.apache.jasper.runtime.JspSourceDependent,

                 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,

 

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;

    JspWriter _jspx_out = null;

    PageContext _jspx_page_context = 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

 

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.

 

      response.setContentType("text/plain");

 

If you initialize IsErrorPage to true, it will actually create an object called exception that looks like Throwable. This is then initialized by the getThrowable function.

 

e18.jsp

<%@ page isErrorPage="true" %>

hi

 

----------

Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);

-----------

 

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.

 

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 , we get the following error in the browser window.

 

Error: 404

File not found

 

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.

 

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.

 

------------------

 void abc() throws IOException

{

throw new IOException("hi bye");

}

 

      pageContext = _jspxFactory.getPageContext(this, request, response,

                               "f1.jsp", true, 8192, true);

--------------

---------

Server log

[#|2004-10-19T15:18:49.028+0530|SEVERE|sun-appserver-pe8.0|javax.enterprise.system.container.web|_ThreadID=12;|StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception

---------

 

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>");

java.io.PrintWriter pw = response.getWriter();

exception.printStackTrace(pw);

out.println("</pre>");

%>

 

Output in browser window

java.io.IOException: hi bye at org.apache.jsp.e19_jsp.abc(e19_jsp.java:13) at org.apache.jsp.e19_jsp._jspService(e19_jsp.java:57) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:141) at javax.servlet.http.HttpServlet.service(HttpServlet.java:861) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:325) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:306) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:253) at javax.servlet.http.HttpServlet.service(HttpServlet.java:861) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:324) at org.apache.catalina.security.SecurityUtil$1.run(SecurityUtil.java:289) at java.security.AccessController.doPrivileged(Native Method) at javax.security.auth.Subject.doAsPrivileged(Subject.java:500) at org.apache.catalina.security.SecurityUtil.execute(SecurityUtil.java:311) at org.apache.catalina.security.SecurityUtil.doAsPrivilege(SecurityUtil.java:205) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:283) at org.apache.catalina.core.ApplicationFilterChain.access$000(ApplicationFilterChain.java:102) at org.apache.catalina.core.ApplicationFilterChain$1.run(ApplicationFilterChain.java:192) at java.security.AccessController.doPrivileged(Native Method) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:263) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:156) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:569) at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:261) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:215) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:156) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:569) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:200) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:156) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:180) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:154) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:582) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:154) at com.sun.enterprise.webservice.EjbWebServiceValve.invoke(EjbWebServiceValve.java:134) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:154) at com.sun.enterprise.security.web.SingleSignOn.invoke(SingleSignOn.java:254) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:154) at com.sun.enterprise.web.VirtualServerValve.invoke(VirtualServerValve.java:209) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:154) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:569) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:161) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:156) at com.sun.enterprise.web.VirtualServerMappingValve.invoke(VirtualServerMappingValve.java:166) at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:154) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:569) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:979) at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:211) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:692) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:647) at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:589) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:691) at java.lang.Thread.run(Thread.java:534)

 

------------------

In _jspservice

 

      out.write("\r\n");

      out.write("\r\n");

      out.write("<html>\r\n");

      out.write("\r\n");

      out.write("\r\n");

 

//try

//{

abc();

//}

//catch ( Exception e) {}

 

      out.write("\r\n");

      out.write("</html>\r\n");

 

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 in the web server log we see hi in exception, which proves that only the inner try catch was activated.

------------

[#|2004-10-19T15:54:27.463+0530|INFO|sun-appserver-pe8.0|javax.enterprise.system.stream.out|_ThreadID=12;|

hi in exception|#]

-----------

 

e20.jsp

hi

<%@ include file="aa.html" %>

Bye

 

C:\jswdk-1.0.1\examples\jsp>edit aa.html

in aa.html

 

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

 

      out.write("hi\r\n");

      out.write("in aa.html");

      out.write("\r\n");

      out.write("Bye\r\n");

 

The phase while creating a servlet 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 servlet is not regenerated.

 

The only way to incorporate changes is by either recompiling the Java file or restarting the server. When the server shuts down ,it deletes all the generated files in the domain, so also all 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() %>

lousy

 

There is no java file generated for aa.jsp.

-------------

      out.write("hi\r\n");

      out.write("no\r\n");

      out.print( new java.util.Date() );

      out.write("\r\n");

      out.write("lousy\r\n");

      out.write("\r\n");

      out.write("Bye\r\n");

---------------

With this example you will realize that if you have JSP code with the include directory, then it gets inserted in the service function. For dynamism, create a JSP file and use it with the include directive. Now each time you click on refresh the date function will be reexecuted, thus displaying a different date and time.

 

Let's go one step further.

 

e22.jsp

hi

<jsp:include page="zz.jsp" flush="true" />

bye

 

zz.jsp

no

bad

 

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. This is termed as 'action'. Each time you refresh the file, the server is requested for that file.

 

-----------------

      out.write("hi\r\n");

      org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "zz.jsp", out, true);

      out.write("\r\n");

      out.write("bye\r\n");

----------------

 

However, the glitch here is that with include as an action, you cannot have Java code nor can you change the headers and cookies.

 

e23.jsp

hi

<jsp:include page="a40.html" flush="true" />

bye

 

a40.html

bye

 

In e23.jsp, the first line is hi. Then a40.html, which contains bye, is included.

----------

      out.write("hi\r\n");

      org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "a40.html", out, true);

      out.write("\r\n");

      out.write("bye\r\n");

----------

 

Replace 'bye' in the html file with '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

 

This example introduces a new action named forward. page=cc.jsp implies that a page is sent with the file. Hence every time you try to load e24.jsp, you will be forwarded to cc.jsp. Forward becomes _jspx_page_context.forward in the Java file.

 

A valid question to ask here would be, 'will it come back to e24.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 given to _jspx_page_context.forward becomes your active html file, everything else is forgotten.

 

e24_jsp.java

-----------------------------

  out.write("hi\r\n");

      if (true) {

        _jspx_page_context.forward("cc.jsp");

        return;

      }

      out.write("\r\n");

      out.write("bye\r\n");

--------------------

 

 

cc_jsp.java

----------------

      out.write("no\r\n");

      out.print( new java.util.Date() );

      out.write("\r\n");

      out.write("lousy\r\n");

------------------

 

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=e25.jsp>

<input type='text' name='aa'>

<input type='submit' value='click'>

</form>

</html>

 

e25.jsp

<%= request.getParameter("aa") %>

 

Open the htm file in browser

 

http://localhost:8080/zzz/z.htm

 

Enter abc in the text box and click on the button. The net result is that abc is displayed in the browser and in the address bar of the browser changes to:

 

http://localhost:8080/zzz/e25.jsp?aa=abc

 

Further, to read data from a form, the request object is used, therefore request.getParameter("aa").  Here aa is some name associated with a control in the form.

This returns abc as the text box was filled with abc.

 

The form has an action attribute which is initialized to a .jsp file. As a result, the JSP code on the server is executed when the user clicks on the submit button. The net effect is that a new page comes up with the appendage of ?aa=abc to the url and the value 'abc' is displayed on the screen.

 

-----------------

      out.print( request.getParameter("aa") );

-----------------

 

In CGI programming, when the button named submit is clicked, the browser looks for a tag named form with an attribute named action. It then creates a url with action and add a ?. Thereafter it takes all the input statements, figures out the value given to each of them and converts then to a name value pair seperated by '=', as in

aa=abc. The benefit of using JSP is that it becomes 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

 

server log

[#|2004-10-20T14:24:05.790+0530|INFO|sun-appserver-pe8.0|javax.enterprise.system.stream.out|_ThreadID=13;|

jspinit|#]

 

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 have ot create our own jspInit when variables are to be initialized or when a certain chunk of code is to be executed in a one time job. Similarly jspDestroy can be used to release the memory used by variables or do end processing task. It is but 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 with a url. The job of this function is to redirect the user to the site that has been passed as a parameter. The redirected page then becomes the active Page.

 

e27.jsp

<% response.sendRedirect("http://127.0.0.1:8080/zzz/e1.jsp"); %>

 

Generally there should be no text before or after sendRedirect as it does not get displayed.

------------

response.sendRedirect("http://127.0.0.1:8080/zzz/e1.jsp");

------------

 

e28.jsp

hi <p> bye

<% response.sendRedirect("http://127.0.0.1:8080/zzz/e1.jsp"); %>

no <p> good

 

http://127.0.0.1:8080/zzz/e1.jsp

 

The address bar in the browser displays the new url, thus implying that the browser requested for a new file from the given url.

 

------------------------

      out.write("hi <p> bye\r\n");

 response.sendRedirect("http://127.0.0.1:8080/zzz/e1.jsp");

      out.write("\r\n");

      out.write("no <p> good\r\n");

-------------------------

 

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","/zzz/e1.jsp");

%>

 

-----------------

response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);

response.setHeader("Location","/zzz/e1.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. With response.sendRedirect or setStatus, the status code is sent over to the client with more information in the header, whereupon the browser asks for the new file. As a result, the user sees e1.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. Something similar to a login page, unless the user doesn't sign in, 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);

%>

 

The browser shows.

login

hi

 

server log

[#|2004-10-20T14:48:32.699+0530|INFO|sun-appserver-pe8.0|javax.enterprise.system.stream.out|_ThreadID=13;|

e31.jsp?Origin=e30.jsp|#]

 

[#|2004-10-20T14:48:58.806+0530|INFO|sun-appserver-pe8.0|javax.enterprise.system.stream.out|_ThreadID=13;|

e31 e30.jsp|#]

 

Here we have two files, e30.jsp and e31.jsp. The directive, page session="true", is not required but is retained. Then is the text login. Following this is s, 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. It may be noted that 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 (given in caps). As of now since the variable is not declared, it will be null.

 

The next line of response.encodeRedirectUrl creates a url of the string given within the brackets and stores it in s1. It is response.sendRedirect that calss for e31.jsp

 

In e31.jsp, session.putValue creates the variable EID and initializes it to 'sonal'. request.getParameter then returns the value of Origin, which is e30.jsp, and as before response.encodeRedirectUrl convert it into a url. Finally, there is a redirection to e30.jsp again.

 

Now, within e30.jsp, the variable EID has a value, thus the else block is called and hi is displayed. This further goes to prove that both s and the session are the same.

 

Thus, as long as it is the same user on the website, he will not have to login twice. But, when 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, request.getSession returns the current session handle which is stored in s. Then s.putValue creates 'vij' if not present and initializes it to 'sonal'.

 

In e33.jsp, s is a handle to HttpSession. Since the session is the same, s.getValue of vij will return 'sonal'.

 

Start with executing e33.jsp. The output will be bye and null because at the moment vij has no value. Thereafter, run e32.jsp and it will display hi on the screen. Now once again reload e33.jsp. You will see 'Bye 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.

 

We move on to the next example. 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();

}

%>

 

FileOutputStream is used when a file is opened in output mode i.e. for writing. However if the file is not present on the disk, it gets created. Thus file pp.txt is created on the hard disk. Now, to write to this file, a file handle is required. This is achieved using the PrintWriter which return a handle to the open file.

 

p thus becomes a handle to pp.txt. Then p.println with ("hi") as a paramter write the text to the file. You have an option of giving the complete path along with the filename, or use the default, which is the C:\Sun\AppServer\domains\domain1\config.

 

Similarly, to read from a file, FileInputStream is used instead of FileOutputStream.

 

‘type pp.txt' in C:\Sun\AppServer\domains\domain1\config, and it will display hi on the screen.

 

For the grand finale of this chapter, we have one last example.

 

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);

}

}

%>

 

[#|2004-10-20T14:59:43.534+0530|INFO|sun-appserver-pe8.0|javax.enterprise.system.stream.out|_ThreadID=15;|

xpoweredBy=..true|#]

 

[#|2004-10-20T14:59:43.554+0530|INFO|sun-appserver-pe8.0|javax.enterprise.system.stream.out|_ThreadID=15;|

logVerbosityLevel=..warning|#]

 

getServletConfig enables us to preview the parameters set by the Java Web Server. This function returns an object that looks like ServletConfig(). Further, cfg.getInitParameterNames() returns an enumeration which in turn has a member hasMoreElements. e.nextElement then gives the name of the element and getInitParameter along with the name will emit its value. They are all stored as a name-value pair.

 

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