The JSP Files – Parts 1 to 8: Tagged and Bagged

Welcome to the JSP Files!

If you’re interested in learning JSP, you’ve come to the right place! Over the coming weeks you’ll find the following comprehensive tutorials available here — so be sure to check back each week to get the latest installment.

And if you need a little help getting started, don’t forget to give Kevin Yank’s JSP Quick Start Guide for Windows.

The JSP Files — Part 1: Purple Pigs In A Fruitbasket
Get to grips with Java Server Pages with this introductory tutorial, which covers variables, includes and the String object.

The JSP Files — Part 2: Attack Of The Killer Fortune Cookies
Conditional expressions, logical and comparsion operators, and a basket full of fortune cookies. What more could you ask for?

The JSP Files — Part 3: Black Light And White Rabbits
More String object methods, and a tour of the various control structures available in JSP.

The JSP Files — Part 4: The Red Pill
Find out JSP can be used to process form data, and learn about the Request object.

The JSP Files — Part 5: No Forwarding Address
Build dynamic, data-driven Web pages with JSP.

The JSP Files — Part 6: State Of Grace
Learn how to "maintain state" on a JSP-based Website with the Cookie and Session objects.

The JSP Files — Part 7: Bugs, Beans And Banks
Squash bugs, heat beans and learn a little more about JSP.

The JSP Files — Part 8: Tagged And Bagged
Learn how to speed up JSP code development with custom tag libraries.

Enjoy!

The JSP Files — Part 1: Purple Pigs in a Fruitbasket

The JSP Story

Ever since Sun Microsystems (aka "the dot in dot-com") came up with Java, the geeks have been screaming themselves hoarse about the wonders of this technology. Terms like "platform-independent code" and "write once, run anywhere" have been given so much airplay that even novice Java developers are aware of them, and the language is also popular with talk-show pundits and Internet consultants, who tout it as the solution to almost all problems of cross-platform compatibility.

Now, we’re big fans of Java – we’ve used it in the past, and will do so again in the future – but this series of tutorials isn’t about Java. It’s actually about an offshoot of Java, the innocuously-named Java Server Pages, or JSP, which attempts to offer Web developers a compelling alternative to traditional server-side scripting languages like Perl, PHP and ASP.

How? First, a little history…

During the early days of the Web, it was the sheer amount of (free!) content that encouraged people to use it. Using the easy-to-learn HTML language, any one and their deaf grandma could set up a Web page and reach out to other like-minded souls online. As the infrastructure improved, content was no longer restricted to text; you could now view pictures or watch videos on the Web. And as more and more people began adding interactivity to their Web sites, a bunch of programming languages were born in order to meet increasingly complex requirements.

The best-known of these is, of course, Perl, although PHP and ASP are also popular favourites. The problem with these languages, however, is that every request to the Web server for a Web page generates a new process on the server, leading to performance problems as visitor traffic increases.

Java offers a solution to this problem, by using so-called "servlets" to create interactive Web sites (a Java servlet is like a Java applet, except that it runs on the Web server, not the client Web browser – and if you’re confused now, wait till we get to scriptlets). Java also makes it possible for brick-and-mortar companies to interface their legacy systems with the new technologies available on the Web, and rapidly develop and link back-office automation systems together via the Internet.

However, servlets have a problem of their own – a simple interface or logic modification could often result in far-reaching changes to the servlet. And so, JSP was developed to separate application logic from the interface, so that changes to one would not affect the other. Working closely with developers like The Apache Group, JSP uses a tag-based approach (similar to PHP and ASP) which allows designers to make changes to the user interface without affecting application logic.

If you’re wondering about scalability, JSP supports component-based architectures using JavaBeans or Enterprise JavaBeans; this allows a developer to create reusable code modules and thereby speed up development time. And since this is Java, you can seamlessly connect Web applications to legacy systems, thereby reducing the costs of moving a real-world business into cyberspace. Say it with us – platform independence rocks!

Studying The Foundations

JSP is based on a multi-tier architecture, which can best be explained by comparing it to the architecture seen on non-JSP sites (read: PHP- or ASP-driven sites). In the typical Apache/PHP/mySQL architecture, you have a Web server and a database server at one level, with a scripting language like PHP taking care of the communication between the two to churn out dynamic content. While this kind of architecture is fine for sites that attract a middling amount of traffic, it begins to display its warts when traffic increases and the load on the database and Web servers goes up.

The JSP architecture, on the other hand, involves more than one level, immediately making it more scalable and maintainable.

In case you’re wondering what the long words mean, scalable implies that you can easily increase, or "scale up", your systems as traffic increases, while maintainable implies that it is possible to simply modify one part of the system – changing over from one database to another, for example – without affecting other areas.

In the context of JSP, a multi-tier architecture involves the Web server for static HTML content, the application server for JavaBeans and servlets, and the database server for database connectivity. Additionally, you can combine JSP with JavaBeans and Java servlets to create complex Web applications which build upon previously-released and tested code modules, thereby simplifying code maintenance and increasing reusability.

It is important to note here that JSP code is not read line-by-line, as with PHP; it is first converted into a servlet (a bytecode version of the program) and then invoked by a servlet engine (such as Tomcat) to perform the required actions. Once the servlet is executed, the results are sent back to the client. Since the servlet engine has to compile the servlet the first time around, displaying a JSP page can take a little while the first time you access it; however, the next time around, response time will be dramatically reduced, since the servlet will have already been compiled and therefore ready for immediate use.
Copyright Melonfire, 2000. All rights reserved.

Java In A Teacup

In order to begin working on JSP, you need to get yourself copies of Sun’s Java Development Kit, Apache’s httpd Web server and mod_jserv module, and the Tomcat servlet engine, and configure them so that they’re all working together. This tutorial assumes that you’ve got a JSP development environment set up — in case you don’t, take a look at "Slapping Together A JSP Development Environment", a tutorial which will guide you through the process.

With that out of the way, let’s get down to the nitty-gritty of actually creating a JSP page. Open up a new file in your favourite text editor and type in the following lines of code:

<html>   
<head>  
</head>  
<body>  
<%  
// asking for it!  
 
out.println("Waiter, can I have a cup of Java, please?");  
 
%>  
</body>  
</html>

Save this file with the extension .jsp – for example, "coffee.jsp" – in an appropriate location and then view it by pointing your browser to it – for example, http://localhost/jsp/coffee.jsp . You should see something like this:

<html>   
<head>  
</head>  
<body>  
 
Waiter, can I have a cup of Java, please?  
 
</body>  
</html>

And that, grasshopper, is your first scriptlet!

In JSP-lingo, a "scriptlet" is a block of code executed by the JSP engine when the user requests a JSP page. All scriptlets are enclosed within <%…%> tags (similar to ASP and PHP code), like this:

<%   
... JSP code ...  
 
out.println("Waiter, can I have a cup of Java, please?");  
 
... JSP code ...  
%>

Every JSP statement ends in a semi-colon – this convention is identical to that used in Perl, and omitting the semi-colon is one of the most common mistakes newbies make. Just as an example, here’s what happens when you omit the semi-colon from the example above:

Error: 500   
Location: /jsp/coffee.jsp  
Internal Servlet Error:  
org.apache.jasper.JasperException: Unable to compile class:    
Invalid type expression.  
out.println("Waiter, can I have a cup of Java, please?")  
^  
: Invalid declaration.  
out.write("rnrnrn");  
^  
2 errors  
at org.apache.jasper.compiler.Compiler.compile  
(Compiler.java, Compiled Code)  
at org.apache.jasper.servlet.JspServlet.doLoadJSP  
(JspServlet.java:462)  
at  
org.apache.jasper.servlet.JasperLoader12.loadJSP  
(JasperLoader12.java:146)  
at org.apache.jasper.servlet.JspServlet.loadJSP  
(JspServlet.java:433)  
at org.apache.jasper.servlet.JspServlet$JspServletWrapper.  
loadIfNecessary(JspServlet.java:152)  
at org.apache.jasper.servlet.JspServlet$JspServletWrapper.  
service(JspServlet.java:164)  
at org.apache.jasper.servlet.JspServlet.serviceJspFile  
(JspServlet.java:318)  
at org.apache.jasper.servlet.JspServlet.service  
(JspServlet.java, CompiledCode)  
at    
javax.servlet.http.HttpServlet.service(HttpServlet.java:853)  
at org.apache.tomcat.core.ServletWrapper.doService  
(ServletWrapper.java:404)  
at org.apache.tomcat.core.Handler.service(Handler.java:286)  
at org.apache.tomcat.core.ServletWrapper.service  
(ServletWrapper.java:372)  
at org.apache.tomcat.core.ContextManager.internalService  
(ContextManager.java:797)  
at org.apache.tomcat.core.ContextManager.service  
(ContextManager.java:743)  
at org.apache.tomcat.service.connector.Ajp12Connection  
Handler.processConnection(Ajp12ConnectionHandler.java:166)  
at org.apache.tomcat.service.TcpWorkerThread.runIt  
(PoolTcpEndpoint.java, Compiled Code)  
at org.apache.tomcat.util.ThreadPool$ControlRunnable.run  
(ThreadPool.java, Compiled Code)  
at java.lang.Thread.run(Thread.java, Compiled Code)

Whoops!

It’s also possible to add comments to your JSP code, as in the example above. JSP supports both single-line and multi-line comment blocks – take a look:

<%   
 
// this is a single-line comment  
/* and this is a  
multi-line  
comment */  
 
%>

Like PHP and Perl, white space is ignored in JSP.

Finally, the statement which actually prints output to the browser – as you’ll see, this is done using the "out" object. Since JSP is based on Java, and Java is an object-oriented language, most of your JSP statements will include object references such as this one.
Copyright Melonfire, 2000. All rights reserved.

Enter John Doe

Variables are the bread and butter of every programming language…and JSP has them too. A variable can be thought of as a programming construct used to store both numeric and non-numeric data; this data can then be used in different places in your JSP scriptlets.

JSP supports a number of different variable types: integers, floating point numbers, strings and arrays. Unlike PHP, which can automagically determine variable type based on the data it holds, JSP requires you to explicitly define the type of each variable before using it.

Every variable has a name – in JSP, a variable name is preceded by a keyword indicating the variable type, and must begin with a letter, optionally followed by more letters and numbers. Variable names are case-sensitive, and reserved keywords cannot be used as variable names.

For example, "popeye", "one_two_three" and "bigPirateShip" are all valid variable names, while "byte" and "123" are invalid variable names.

The following example demonstrates how variables can be used in a JSP document.

<html>    
<head>    
</head>    
<body>    
<%!    
// define variables here    
String name = "John Doe";    
%>    
   
<%    
// code comes here    
out.println("My name is " + name );    
%>    
</body>    
</html>

As you can see, we’ve first defined a variable named "name", set things up so that it will hold string, or character, data, and assigned a value ("John Doe") to it. This value is then used by the println() function to display a message in the HTML page.

My name is John Doe

If you’re sharp-eyed, you’ll have noticed a slight difference between the two JSP blocks in the example above – the first looks like this:

<%!    
...    
%>

…while the second looks like this:

<%    
...    
%>

The first block, within which the variables are defined, is referred to as the "declaration block"; variables declared within this block are available globally, to each and every scriptlet within that JSP document.

You can also define a variable without assigning a value to it, or assign a value to it at a later stage – for example, the following code snippets are equivalent.

<%    
String name;    
name = "John Doe";    
%>    
   
<%    
String name = "John Doe";    
%>
Putting Two And Two Together

Just as you can create a variable to hold strings, you can create variables of other types too:

  • int – used to store integers
  • char - used to store a single character in Unicode format
  • float and long – used to store floating-point numbers
  • boolean – used to store "true" and "false" values (note that unlike languages like C and PHP, JSP does not recognize 1 => true and 0 => false)

Let’s take a simple example that adds two numbers and displays the result.

<html>    
<head>    
</head>    
<body>    
<%!    
int alpha = 45;    
int beta = 34;    
int Sum;    
%>    
<%    
// add the two numbers    
Sum = alpha + beta;    
   
// display the result    
out.println("The sum of " + alpha + " and " + beta + " is " + Sum); %>    
</body>    
</html>

And the output is:

The sum of 45 and 34 is 79

In this case, we’ve simply defined two variables as integer values, assigned values to them, and added them up to obtain the sum.

In a similar vein, the next example demonstrates adding strings together:

<html>    
<head>    
</head>    
<body>    
<%!    
// define the variables    
String apples = "The lion ";    
String oranges = "roars in anger";    
String fruitBasket;    
%>    
<%    
// print the first two strings    
out.println("<b>The first string is</b>:    
" + apples + "<br>"); out.println("<b>The second string    
is</b>: " + oranges + "<br>");    
   
// concatentate the strings    
fruitBasket = apples + oranges;    
   
// display    
out.println("<b>And the combination is</b>: " + fruitBasket + "<br>Who    
says you can't add apples and oranges?!");    
%> </body> </html>

And the output is:

The first string is: The lion    
The second string is: roars in anger    
And the combination is: The lion roars in anger    
Who says you can't add apples and oranges?!

In this case, the + operator is used to concatenate two strings together, which is then displayed via println().
Copyright Melonfire, 2000. All rights reserved.

Basket Case

The String object comes with a bunch of useful methods, which can come in handy when performing string manipulation.

The first of these is the length() method, used to obtain the (you guessed it!) length of a specific string. Let’s modify the example you just saw to demonstrate how this works:

<html>     
<head>    
</head>    
<body>    
<%!    
// define the variables    
String apples = "Purple pigs ";    
String oranges = "riding orange pumpkins";    
String fruitBasket;    
%>    
<%    
// print the first two strings    
out.println("<b>The first string is</b>: " + apples + "<br>"); out.println    
("<b>The second string is</b>: " + oranges + "<br>");    
   
// concatentate the strings    
fruitBasket = apples + oranges;    
   
// display    
out.println("<b>And the combination is</b>: " + fruitBasket + "(" +    
fruitBasket.length() + " characters)<br>Who says you can't add      
apples and oranges?!"); %> </body> </html>

And the output is:

The first string is: Purple pigs     
   
The second string is: riding orange pumpkins    
   
And the combination is: Purple pigs riding orange pumpkins(34 characters)    
Who says you can't add apples and oranges?!

You can extract a specific character from the string with the charAt() method, which accepts an offset as parameter. For example, the following code snippet would return the character "o":

<%     
String name = "Bozo The Clown";    
out.println(name.charAt(3));    
%>

Note that the offset 0 indicates the first character, since Java, like many of its counterparts, uses zero-based indexing.

You can also extract a segment of a string with the substring() method, which allows you to specify the start and end points of the string segment to be extracted. Take a look at this sentence and see if you can spot the hidden message within it:

<%!     
String me = "I am a highly-skilled and hardworking developer!"; %>

No? How about now?
   
<%!    
String me = "I am a highly-skilled and hardworking developer!";      
String message; %> <% message = me.substring(0,2) +      
me.substring(15,22) + me.substring(26,27) +      
me.substring(45,48); out.println(message); %>

And here’s the output:

I killed her!

Alphabet Soup For The Soul

If you’ve used C before, you’re probably already familiar with the "include" directive that appears near the beginning of every C program. JSP supports an equivalent include() function, which does much the same thing. Take a look at this simple example:

<html>      
<head>      
<title> Thought For The Day</title>      
</head>      
<body>      
     
Thought For The Day:      
<br>      
<%@ include file="thought.html" %>      
     
</body>      
</html>

[thought.html]

Ever wonder if illiterate people get the full effect of alphabet soup?

In this case, JSP will automatically read the contents of the file "thoughts.html", and display a composite page which looks like this:

<html>      
<head>      
<title>Thought For The Day</title>      
</head>      
<body>      
     
Thought For The Day:      
<br>      
Ever wonder if illiterate people get the full effect of alphabet soup?      
     
</body>      
</html>

A very useful and practical application of the include() function is to use it to include a standard footer or copyright notice across all the pages of a Web site, like this:

<html>      
<head>      
</head>      
     
<body>      
     
...your HTML page...      
     
<br>      
     
<%@ include file="footer.html" %>      
     
</body>      
</html>

where "footer.html" contains:

<font size=-1 face=Arial>This material copyright Melonfire, 2001.       
All rights reserved.</font>

Now, this footer will appear on each and every page that contains the include() statement above – and, if you need to change the message, you only need to edit the single file named "footer.html"!

And that’s about it for this week. We’ve shown you the basic building blocks of JSP, and next time, we’ll be using those fundamental concepts to demonstrate JSP’s control structures. Don’t miss it!

Note: All examples in this article have been tested on Linux/i586 with Tomcat 3.2 and JServ 1.1. Examples are illustrative only, and are not meant for a production environment. YMMV!
Copyright Melonfire, 2000. All rights reserved.

The JSP Files — Part 2: Attack of the Killer Fortune Cookies

Overdrive

With a little bit of luck, our introductory article on JSP left you so excited that you spent the last few days eagerly practicing variable names and letting your friends know how much smarter you are than them. And this week, we’re going to help you cement your reputation still further, by giving you a crash course in JSP’s conditional statements and loops.

Make sure you’re strapped in tight – this is gonna be one hell of a ride!

Adding It All Up

You’ll remember how, in the first part of this tutorial, we used the + operator to add numbers and strings together. And just as you have the + operator for addition, JSP comes with a bunch of other arithmetic operators designed to simplify the task of performing mathematical operations.

The following example demonstrates the important arithmetic operators available in JSP:

<html>       
<head>      
</head>      
<body>      
     
<%!      
// declare variables      
int alpha = 25;      
int beta = 5;      
int sum, difference, product, quotient, remainder;      
%>      
     
<%      
// perform operations      
out.println("The sum of " + alpha + " and "        
+ beta + " is " + (alpha + beta) + "<br>");      
     
out.println("The difference of " + alpha + " and "        
+ beta + " is " + (alpha - beta) + "<br>");      
     
out.println("The product of " + alpha + " and "        
+ beta + " is " + (alpha *      
beta) + "<br>");      
     
out.println("The quotient after division of " + alpha        
+ " and " + beta + " is " + (alpha / beta) + "<br>");        
out.println("The remainder after division of " + alpha        
+ " and " + beta + " is " + (alpha % beta) + "<br>"); %>      
     
</body>      
</html>

And here’s the output:

The sum of 25 and 5 is 30       
The difference of 25 and 5 is 20      
The product of 25 and 5 is 125      
The quotient after division of 25 and 5 is 5      
The remainder after division of 25 and 5 is 0

As with all other programming languages, division and multiplication take precedence over addition and subtraction, although parentheses can be used to give a particular operation greater precedence. For example,

<%       
out.println(10 + 2 * 4);      
%>

returns 18, while:

<%       
out.println((10 + 2) * 4);      
%>

returns 48.

In addition to these operators, JSP comes with the very useful auto-increment [++] and auto-decrement [--] operators, which you’ll see a lot of in the next article. The auto-increment operator increments the value of the variable to which it is applied by 1, while the auto-decrement operator does the opposite. Here’s an example:

<%!       
int x = 99;      
%>      
     
<%      
// x = 99      
out.println("Before increment, x = " + x + "<br>");      
x++;      
// x = 100      
out.println("After increment, x = " + x);      
%>

JSP also comes with a bunch of comparison operators, whose sole raison d’etre is to evaluate expressions and determine if they are true or false. The following table should make this clearer.

Assume x=4 and y=10

Operator What It Means Expression Result
== is equal to x == y False
!= is not equal to x != y True
> is greater than x > y False
< is less than x < y True
>= is greater than or equal to x >= y False
<= is less than or equal to x <= y True

Copyright Melonfire, 2000. All rights reserved.

Flavour Of The Month

And just as you can compare numbers, JSP also allows you to compare strings, with a couple of very useful String object methods.

First, the equals() method allows you to check whether the value of a particular string variable matches another. The following example should demonstrate this.

<%        
// define variables        
String myFavourite = "chocolate";        
String yourFavourite = "strawberry";        
       
// compare strings        
if (myFavourite.equals(yourFavourite))        
{        
out.println("A match made in heaven!");        
}        
else        
{        
out.println("Naw - try again!");        
}        
%>

Try changing the values of the variables to match each other, and gasp in awe as the output changes.

In case the equals() method doesn’t appeal to you, JSP offers you a choice in the form of the compareTo() method, which returns a value indicating which of the two strings is greater. Take a look:

<%        
// define variables        
String alpha = "abcdef";        
String beta = "zyxwvu";        
       
// compare strings        
out.println(alpha.compareTo(beta));        
%>

In this case, if the value of the variable "beta" is greater than that of the variable "alpha", the compareTo() method will return a negative integer; if it’s the other way around, the comparison will return a positive integer. And if the two strings are identical, the comparison will return 0.

Incidentally, the comparison is based on both the first character of the string, and the number of characters in the string. One string is considered "greater" than another if the numeric value of its first character is greater, or if its length is greater. In the example above, "z" has a greater numeric code than "a", and so the comparison will return a negative integer. But don’t take our word for it — try it yourself and see!

Turning Up The Heat

Why do you need to know all this? Well, comparison operators come in very useful when building conditional expressions — and conditional expressions come in very useful when adding control routines to your code. Control routines check for the existence of certain conditions, and execute appropriate program code depending on what they find.

The first — and simplest — decision-making routine is the "if" statement, which looks like this:

if (condition)        
{        
do this!        
}

The "condition" here refers to a conditional expression, which evaluates to either true or false. For example,

if (hard drive crashes)        
{        
get down on knees and pray for redemption        
}

or, in JSP-lingo:

<%        
if (hdd == 0)        
{        
pray();        
}        
%>

If the conditional expression evaluates as true, all statements within the curly braces are executed. If the conditional expression evaluates as false, all statements within the curly braces will be ignored, and the lines of code following the "if" block will be executed.

Here’s a simple program that illustrates the basics of the "if" statement.

<%!        
// declare temperature variable        
int temp = 50;        
%>        
       
<%        
// check temperature and display output        
if (temp > 30)        
{        
out.println("Man, it's hot out there!");        
}        
%>

In this case, a variable named "temp" has been defined, and initialized to the value 50. Next, an "if" statement has been used to check the value of the "temp" variable and display a message if it’s over 30. Note our usage of the greater-than (>) conditional operator in the conditional expression.

An important point to note — and one which many novice programmers fall foul of — is the difference between the assignment operator [=] and the equality operator [==]. The former is used to assign a value to a variable, while the latter is used to test for equality in a conditional expression.

So:

a = 47;

assigns the value 47 to the variable a, while

a == 47

tests whether the value of a is equal to 47.
Copyright Melonfire, 2000. All rights reserved.

Do It, Or Else…

In addition to the "if" statement, JSP also offers the "if-else" statement, which allows you to execute different blocks of code depending on whether the expression is evaluated as true or false.

The structure of an "if-else" statement looks like this:

if (condition)         
{        
do this!        
}        
else        
{        
do this!        
}

In this case, if the conditional expression evaluates as false, all statements within the curly braces of the "else" block will be executed. Modifying the example above, we have:

<%!         
// declare temperature variable        
int temp = 50;        
%>        
       
<%        
// check temperature and display output        
if (temp > 30)        
{        
out.println("Man, it's hot out there!");        
}        
else        
{        
out.println("Well, at least it isn't as hot as it could be!"); } %>

In this case, if the first past of the construct fails (temperature is *not* greater than 30), control is transferred to the second part — the "else" statement — and the code within the "else" block is executed instead. You can test both possibilities by adjusting the value of the "temp" variable, and viewing the resulting output in your browser.

Cookie-Cutter Code

The "if-else" construct certainly offers a smidgen more flexibility than the basic "if" construct, but still limits you to only two possible courses of action. If your script needs to be capable of handling more than two possibilities, you should reach for the "if-else if-else" construct, which is a happy combination of the two constructs you’ve just been reading about.

if (first condition is true)         
{        
do this!        
}        
else if (second condition is true)        
{        
do this!        
}        
else if (third condition is true)        
{        
do this!        
}        
       
... and so on ...        
       
else        
{        
do this!        
}

Take a look at it in action:

<%!         
// declare temperature variable        
int temp = 20;        
%>        
       
<%        
// check temperature and display output        
// what happens if temp is less than 25 degrees        
if (temp >= 25)        
{        
out.println("Man, it's hot out there!");        
}        
// what happens if temp is between 25 and 10 degrees        
else if (temp < 25 && temp > 10)        
{        
out.println("Great weather, huh?!");        
}        
// what happens if temp is less than ten degrees        
else if (temp <= 10)        
{        
out.println("Man, it's freezing out there!");        
}        
// this is redundant, included for illustrative purposes        
else        
{        
out.println("Huh? Somebody screwed up out there!");        
}        
%>

In this case, depending on the value of the "temp" variable, the appropriate code branch is executed, thereby making it possible to write scripts which allow for multiple possibilities.

One important point to be noted here: control is transferred to successive "if" branches only if the preceding condition(s) turn out to be false. Or, in English, once a specific conditional expression is satisfied, all subsequent conditional expressions are ignored.

Here’s another example, this one using the day of the week to decide which fortune cookie to display. Alter the "day" variable to see a different cookie each time.

<%!         
String day = "Monday";        
String fortune;        
%>        
<%        
// check day and set fortune        
if (day.equals("Monday"))        
{        
fortune = "Adam met Eve and turned over a new leaf.";        
}        
else if (day.equals("Tuesday"))        
{        
fortune = "Always go to other people's funerals, otherwise          
they won't come to yours."; } else if (day.equals("Wednesday"))        
{ fortune = "An unbreakable toy is useful for breaking other toys."; }        
else if (day.equals("Thursday")) { fortune = "Be alert - the          
world needs more lerts."; } else if (day.equals("Friday"))        
{ fortune = "Crime doesn't pay, but the hours are good."; }          
else { fortune = "Sorry, closed on the weekend"; }          
// print output out.println(fortune); %        
>

Copyright Melonfire, 2000. All rights reserved.

Lunch In Milan

If you take a close look at the last-but-one example above, you'll notice that the conditional expression

(temp < 25 && temp > 10)

is slightly different from the ones you've been used to thus far. This is because JSP also allows you to combine multiple conditions into a single expression, with the help of an animal called a "logical operator".

The following table should make this clearer.

Assume delta = 12, gamma = 12 and omega = 9

Operator What It Means Example Translation Evaluates To
&& AND delta == gamma && delta > omega delta equals gamma AND delta is greater than omega True
&& AND delta == gamma && delta < omega delta equals gamma AND delta is less than omega False
|| OR delta == gamma || delta < omega delta equals gamma OR
delta is less than omega
True
|| OR delta > gamma || delta < omega delta is greater than gamma OR
delta is less than omega
False
! NOT !delta delta isn't true False

So, instead of something as ugly as this:

<%          
if (day == "Thursday")          
{          
if (time == "12")          
{          
if (place == "Italy")          
{          
lunch = "pasta";          
}          
}          
}          
         
%>

you could have something as elegant as this:

<%          
if (day == "Thursday" && time == "12" && place == "Italy")          
{          
lunch = "pasta";          
}          
         
%>
Switching Things Around

Finally, JSP rounds out its conditional expressions with the "switch" statement, which offers an alternative method of transferring control from one program block to another. Here's what it looks like:

switch (decision-variable)          
{          
case first_condition_is true:          
do this!          
         
case second_condition_is true:          
do this!          
         
case third_condition_is true:          
do this!          
         
... and so on...          
         
default:          
do this by default!          
         
}

The "switch" statement can best be demonstrated by rewriting the previous example using "switch" instead of "if-else if-else".

<%!          
int dayOfWeek = 3;          
String fortune;          
%>          
<%          
// the decision variable here is the day chosen by the          
user switch (dayOfWeek)          
{          
         
// first case          
case 1:          
fortune = "Adam met Eve and turned over a new leaf.";          
break;          
         
// second case          
case 2:          
fortune = "Always go to other people's funerals, otherwise          
they won't come to yours.";          
break;          
         
case 3:          
fortune = "An unbreakable toy is useful for breaking other toys.";          
break;          
         
case 4:          
fortune = "Be alert - the world needs more lerts.";          
break;          
         
case 5:          
fortune = "Crime doesn't pay, but the hours are good.";          
break;          
         
// if none of them match...          
default:          
fortune = "Sorry, closed on the weekend";          
break;          
         
}          
// print output          
out.println(fortune);          
%>

The first thing you'll notice is that the "day" variable from the previous example has been converted to a numeric "dayOfWeek" variable -- this is because the "switch" construct only works when the decision variable is an integer.

There are also a couple of important keywords here: the "break" keyword is used to break out of the "switch" statement block and move immediately to the lines following it, while the "default" keyword is used to execute a default set of statements when the variable passed to "switch" does not satisfy any of the conditions listed within the block.

And that's about it. You now know enough about JSP's conditional statements to begin writing simple programs - so go practice! And come back for the next issue, when we'll be talking about loops, demonstrating other String object methods, and even taking a quick look at the new Response object.

Note: All examples in this article have been tested on Linux/i586 with Tomcat 3.2 and JServ 1.1. Examples are illustrative only, and are not meant for a production environment. YMMV!
Copyright Melonfire, 2000. All rights reserved.

The JSP Files -- Part 3: Black Light And White Rabbits

Counting Down

Last time out, you learned a little bit about the various conditional statements and operators available in JSP. This week, we'll expand on those basics by teaching you a little bit about the different types of loops available in JSP, discuss a few more String object methods, and take a quick tour of the new Response object.

First up, loops.

As you may already know, a "loop" is a programming construct that allows you to execute a set of statements over and over again, until a pre-defined condition is met.

The most basic loop available in JSP is the "while" loop, and it looks like this:

while (condition)           
{          
do this!          
}

Or, to make the concept clearer,

while (temperature is below freezing)           
{          
wear a sweater          
}

The "condition" here is a standard conditional expression, which evaluates to either true or false. So, were we to write the above example in JSP, it would look like this:

while (temp <= 0)           
{          
sweater = true;          
}

Here's an example:

<html>           
<head>          
</head>          
<body>          
<%!          
int countdown=30;          
%>          
<%          
while (countdown > 0)          
{          
out.println(countdown + "&nbsp;");          
countdown--;          
}          
out.println("<b>Kaboom!</b>");          
%>          
</body>          
</html>

Here, the variable "countdown" is initialized to 30, and a "while" loop is used to decrement the value of the variable until it reaches 0. Once the value of the variable is 0, the conditional expression evaluates as false, and the lines following the loop are executed.

Here's the output:

30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13            
12 11 10 9 8 7 6 5 4 3 2 1 Kaboom!
Doing More With Loops

There's one caveat with the "while" loop. If the conditional expression evaluates as false the first time, the code within the curly braces will never be executed. If this is not what you want, take a look at the "do-while" loop, which comes in handy in situations where you need to execute a set of statements *at least* once.

Here's what it looks like:

do           
{          
do this!          
} while (condition)

For example, the following lines of code would generate no output whatsoever, since the conditional expression in the "while" loop would always evaluate as false.

<%           
int bingo = 366;          
         
while (bingo == 699)          
{          
out.println ("Bingo!");          
break;          
}          
%>

However, the construction of the "do-while" loop is such that the statements within the loop are executed first, and the condition to be tested is checked after. Using a "do-while" loop implies that the code within the curly braces will be executed at least once - regardless of whether or not the conditional expression evaluates as true.

<%           
int bingo = 366;          
         
do          
{          
out.println ("Bingo!");          
break;          
} while (bingo == 699);          
%>

Try it yourself and see the difference.
Copyright Melonfire, 2000. All rights reserved.

For-Gone Conclusion

Both the "while" and "do-while" loops continue to iterate for so long as the specified conditional expression remains true. But there often arises a need to execute a certain set of statements a specific number of times - for example, printing a series of thirteen sequential numbers, or repeating a particular set of <TD> cells five times. In such cases, clever programmers reach for the "for" loop...

The "for" loop typically looks like this:

for (initial value of counter; condition; update counter)            
{            
do this!            
}

Looks like gibberish? Well, hang in there a minute... the "counter" here is a JSP variable that is initialized to a numeric value, and keeps track of the number of times the loop is executed. Before each execution of the loop, the "condition" is tested -- if it evaluates to true, the loop will execute once more and the counter will be appropriately incremented; if it evaluates to false, the loop will be broken and the lines following it will be executed instead.

And here's a simple example that demonstrates how this loop can be used:

<html>            
<head>            
<basefont face="Arial">            
</head>            
           
<body>            
<center>Turning The Tables, JSP-Style!</center>            
<br>            
<%!            
// define the number            
int number = 7;            
int x;            
%>            
<%            
// use a for loop to calculate tables for that number            
for (x=1; x<=15; x++)            
{            
out.println(number + " X " + x + " = " + (number*x) + "<br>");            
}            
%>            
           
</body>            
</html>

And here's the output:

Turning The Tables, JSP-Style!            
           
7 X 1 = 7            
7 X 2 = 14            
7 X 3 = 21            
7 X 4 = 28            
7 X 5 = 35            
7 X 6 = 42            
7 X 7 = 49            
7 X 8 = 56            
7 X 9 = 63            
7 X 10 = 70            
7 X 11 = 77            
7 X 12 = 84            
7 X 13 = 91            
7 X 14 = 98            
7 X 15 = 105

Let's dissect this a little bit:

Right up front, a variable is defined, containing the number to be used for the multiplication table; we've used 7 here - you might prefer to use another number.

Next, a "for" loop has been constructed, with "x" as the counter variable. If you take a look at the first line of the loop, you'll see that "x" has been initialized to 1, and is set to run no more than 15 times.

Finally, the println() function is used to take the specified number, multiply it by the current value of the counter, and display the result on the page.

The Sound Of Breaking Loops

When dealing with loops, there are two important keywords you should be aware of: "break" and "continue".

The "break" keyword is used to exit a loop when it encounters an unexpected situation. A good example of this is the dreaded "division by zero" error - when dividing one number by another one (which keeps decreasing), it is advisable to check the divisor and use the "break" statement to exit the loop as soon as it becomes equal to zero.

As you've already seen, the "continue" keyword is used to skip a particular iteration of the loop and move to the next iteration immediately - it's demonstrated in the following example:

<%            
int x;            
for (x=1; x<=10; x++)            
{            
if (x == 7)            
{            
continue;            
}            
else            
{            
out.println(x + "&nbsp;");            
}            
}            
%>

In this case, JSP will print a string of numbers from 1 to 10 - however, when it hits 7, the "continue" statement will cause it to skip that particular iteration and go back to the top of the loop. So your string of numbers will not include 7 - try it and see for yourself.
<font size=1 color="#aaaaaa" face="Verdana,Arial,Helvetica">Copyright <a href="http://www.melonfire.com/">Melonfire</a>, 2000. All rights reserved.</font>

Paying The Piper

You've already seen a few of the String object's capabilities in the first part of this tutorial. But as we progress further, you're going to need to know a little bit more to make full use of its power.

First, there's the indexOf() method, which is used to locate the first occurrence of a character or substring in a larger string. If you ran the following code snippet,

<%             
// define variable            
String storyName = "The Pied Piper Of Hamlin";            
           
// find index            
int i = storyName.indexOf("i");            
           
// print index            
out.println("The letter i first occurs at " + i + "              
in the string " + storyName); %>

this is what you would see:

The letter i first occurs at 5 in the string The              
Pied Piper Of Hamlin

Yes, the first character is treated as index 0, the second as index 1, and so on. These programmers...

The opposite of this is the lastIndexOf() function, used to identify the last occurrence of a character or substring in a larger string. Take a look:

<%             
// define variable            
String storyName = "The Pied Piper Of Hamlin";            
           
// find index            
int i = storyName.lastIndexOf("Pi");            
           
// print index            
out.println("The string Pi last occurs at " + i + "              
in the string " + storyName); %>

And the output is:

The string Pi last occurs at 9 in the string The              
Pied Piper Of Hamlin

In case the character or substring is not located, the function will return an error code of -1.

Screaming Out Loud

Next, the trim() function comes in handy when you need to remove white space from the ends of a string.

<%             
// define variable            
String whatIWant = " gimme my space ";            
           
// trim!            
// returns "gimme my space"            
whatIWant.trim();            
%>

The toUpperCase() and toLowerCase() methods come in handy to alter the case of a string.

<%             
// define variable            
String someString = "don't SCREam, help is oN the WAy!";            
           
// uppercase - returns "DON'T SCREAM, HELP IS ON THE WAY!"              
someString.toUpperCase();            
           
// lowercase - returns "don't scream, help is on the way!"              
someString.toLowerCase(); %>

The startsWith() and endsWith() functions are used to verify whether a string starts or ends with a specified character or sequence of characters. The following example should illustrate this clearly.

<%             
// define variables            
String alpha = "black light";            
String beta = "white rabbit";            
String prefix = "bl";            
String suffix = "it";            
           
// check each string for prefixes and suffixes            
           
if (alpha.startsWith(prefix))            
{            
out.println("The string " + alpha + " starts with              
" + prefix + "<br>"); }            
           
if (beta.startsWith(prefix))            
{            
out.println("The string " + beta + " starts with              
" + prefix + "<br>"); }            
           
if (alpha.endsWith(suffix))            
{            
out.println("The string " + alpha + " ends with " +              
suffix + "<br>"); }            
           
if (beta.endsWith(suffix))            
{            
out.println("The string " + beta + " ends with " +              
suffix + "<br>"); }            
           
%>

And the output is:

The string black light starts with bl             
The string white rabbit ends with it

Copyright Melonfire, 2000. All rights reserved.

You Say Seven, I Say 7

And finally, in case you've ever wanted to convert strings to numbers, the following example should tell you everything you need to know.

<%              
// converting a string to a number              
             
// define variables              
String someString = "97";              
int aRandomNumber = 3;              
             
// at this stage, someString is still treated as a string              
out.println(someString + " plus " + aRandomNumber              
+ " equals " + (someString+aRandomNumber) + "<p>");              
             
// now convert someString to a number              
int someNumber              
= Integer.parseInt(someString);              
             
// at this stage, someString has been converted to a              
number, stored in someNumber out.println(someNumber +              
" plus " + aRandomNumber + " equals " + (someNumber+aRandomNumber));              
             
%>

And here's the output.

97 plus 3 equals 973              
97 plus 3 equals 100

If you'd prefer to do things the other way around, the next example bears careful consideration.

<%              
// define variables              
int someNumber = 97;              
int aRandomNumber = 3;              
             
// at this stage, someNumber is still treated as a number              
out.println(someNumber + " plus " + aRandomNumber + "              
equals " + (someNumber+aRandomNumber) + "<p>");              
             
// now convert someNumber to a string              
String someString = Integer.toString(someNumber);              
             
// at this stage, someNumber has been converted to a              
string, stored in someString out.println(someString +              
" plus " + aRandomNumber + " equals " + (someString+aRandomNumber));              
             
%>

And here's the output.

97 plus 3 equals 100              
97 plus 3 equals 973

The upshot? parseInt() and toString() are your best friends when converting between string and numeric data types in JSP.

A Positive Response

Another interesting object, and one that comes in handy in the oddest places, is the Response object. As opposed to the Request object, which is used to retrieve information (come back next time for more on this), the Response object is typically used to send information to the browser; this information could include HTTP headers, redirection URLs, cookies and a variety of other items.

Since the Response object is an "implicit" object (so called because you do not need to explicitly create an instance of the object when you want to use it), you can begin using it immediately in a JSP document. The following example demonstrates using it to turn off caching via the "Cache-Control" header.

<%              
response.setHeader("Cache-Control","no-cache");              
%>              
[/code]              
You can also use it to redirect the client to another URL.              
             
%              
response.setHeader("Location", "error.html");              
%>

You can use the sendRedirect() method to accomplish something similar - remember to use an absolute URL here.

<%              
response.sendRedirect("http://my.server.com/error.html");              
%>

You can set the MIME type of a document with the setContentType() method.

<%              
response.setContentType("image/jpeg");              
%>

and even set a cookie with the addCookie() method - more on this as we progress through this series.

That's about all we have time for. Next time, we'll be exploring the JSP Response object, used to process data from HTML forms... so you don't want to miss that one!

Note: All examples in this article have been tested on Linux/i586 with Tomcat 3.2 and JServ 1.1. Examples are illustrative only, and are not meant for a production environment. YMMV!
Copyright Melonfire, 2000. All rights reserved.

The JSP Files - Part 4: The Red Pill

Applying The Theory

Last time out, we gave you a crash course in the numerous controls structures available to you in JSP - operators, conditional statements, and loops. But there's a big difference between learning theory in a classroom and actually practicing it in the real world - which is why this issue of The JSP Files is devoted to a discussion of how JSP can be used to extract and use data from HTML forms.

Over the next few pages, we're going to show you how JSP can be used to process the data entered into a Web form - everything from simple text boxes to lists and checkboxes - and we're also going to demonstrate how to use array variables in JSP.

The Last Action Hero

HTML forms are typically used to obtain information from visitors to a Web site - things like their name, mailing address, phone number, and the like - and this information is then processed in a variety of different ways. Some sites store it in a database; others email it to the webmaster; and still other simply redirect it to the trash basket. By using JSP to process a form, you can write simple code snippets that accomplish all of these actions.

Let's begin with a simple example.

<html>               
             
<head>              
<basefont face="Arial">              
</head>              
             
<body>              
             
<center>              
<form method="GET" action="matrix.jsp">              
<table cellspacing="5" cellpadding="5" border="0">              
             
<tr>              
<td>              
<font size="-1">Name, rank and serial, number, soldier!</font>                
</td> <td align="left"> <input type="text" name="name" size="10">                
</td> </tr>              
             
             
<tr>              
<td colspan="2" align="center">              
<input type="submit">              
</td>              
</tr>              
             
</table>              
</form>              
             
</center>              
</body>              
             
</html>

The most critical line in this entire page is the <form> tag:

<form method="GET" action="matrix.jsp">               
             
...              
             
</form>

As you probably already know, the ACTION attribute of the <FORM> tag specifies the name of the server-side script - "matrix.jsp" in this case - that will process the information entered into the form, while the METHOD attribute specifies the manner in which the information will be passed.

Copyright Melonfire, 2000. All rights reserved.

Entering The Matrix

Once the form has been submitted, the script "matrix.jsp" is called upon to parse the date entered into the form. At this point, the script simply reads the name entered into the form, and displays a message containing that name; however, at a later point, it will be modified to grant or deny access based on the name entered.

<html>                
<head>                
<basefont face="Arial">                
</head>                
               
<body>                
<center>                
<%                
// matrix.jsp                
               
// define the variables used in the scriptlet                
String fname;                
               
// assign values                
fname = request.getParameter("name");                
               
// print the details                
out.println("Welcome to The Matrix, " + fname + "!");                
               
%>                
</center>                
</body>                
</html>

And now, if you enter some data into the form (say, "joe"), this is what you should see:

Welcome to The Matrix, joe!

An explanation is in order here. As always, the first step is to define the variables that will be used throughout the script - in this case, the variable "fname".

<%                
// define the variables used in the scriptlet                
String fname;                
%>

Next, the value of the form variable "name" has to be assigned to the JSP variable "fname" - this is accomplished with the getParameter() method, which accepts a variable name as parameter and returns the variable value.

The getParameter() method actually belongs to a JSP object called the Request object; unlike many other objects in JSP, the Request object is an "implicit" object, so called because you do not need to explicitly create an instance of the object when you want to use it. The getParameter() method is just one of many methods available in this object, and we'll be exploring some of the others as well in this tutorial.

Once the value of a form variable has been assigned to a JSP variable, it can be treated in exactly the same manner as other JSP variables. In the example above, a println() function call takes care of printing the welcome string, with the name incorporated into it.

You can also use the POST method (which offers greater security and reliability) to process form data - simply alter the HTML form so that the METHOD used is POST.

<form method="POST" action="matrix.jsp">                
               
...                
               
</form>

The script "matrix.jsp" will continue to function as advertised without requiring any changes. Thus, the getParameters() method can be used to access form variables regardless of the method used to post the data.

And you can add a simple conditional statement to deny access to all but the most favoured:

<html>                
<head>                
<basefont face="Arial">                
</head>                
               
<body>                
<center>                
<%                
// matrix.jsp                
               
// define the variables used in the scriptlet                
String fname;                
               
// assign values                
fname = request.getParameter("name");                
               
// print the details                
if (fname.equals("neo"))                
{                
out.println("Welcome to The Matrix, Neo!");                
}                
else                
{                
out.println("Leave immediately, Agent!");                
}                
%>                
</center>                
</body>                
</html>

Copyright Melonfire, 2000. All rights reserved.

Requesting More

The Request object also comes with a bunch of other useful methods - the following example demonstrates some of them

<html>                 
<head>                
<basefont face="Arial">                
</head>                
<body>                
               
<table border="1" cellspacing="5" cellpadding="5">                
<tr>                
<td><b>Variable</b></td>                
<td><b>Value</b></td>                
</tr>                
               
<tr>                
<td>Request protocol</td>                
<td>                
<%                
// protocol                
out.println(request.getProtocol());                
%>                
</td>                
</tr>                
               
<tr>                
<td>Hostname</td>                
<td>                
<%                
// server name                
out.println(request.getServerName());                
%>                
</td>                
</tr>                
               
<tr>                
<td>Port</td>                
<td>                
<%                
// server port                
out.println(request.getServerPort());                
%>                
</td>                
</tr>                
               
<tr>                
<td>Remote username</td>                
<td>                
<%                
// username if using HTTP authentication                
// null if no authentication out.println(request.getRemoteUser());                
%>                
</td>                
</tr>                
               
<tr>                
<td>Remote address</td>                
<td>                
<%                
// get IP address of client out.println(request.getRemoteAddr());                
%>                
</td>                
</tr>                
               
<tr>                
<td>Client browser</td>                
<td>                
<%                
// client browser identification out.println                
(request.getHeader("User-Agent"));                
%>                
</td>                
</tr>                
               
</table>                
</body>                
</html>

And when you view the file in your browser, you'll probably see something like this:

Variable     Value                 
Request protocol    HTTP/1.0                
Hostname    localhost                
Port      80                
Remote username  null                
Remote address    192.168.0.143                
Client browser    Mozilla/4.0 (compatible; MSIE 5.5; Windows 95)

All these variables come in handy if you need to make decisions on the basis of remote variables - as the following example demonstrates:

<%                 
String browser = request.getHeader("User-Agent");                
if(browser.indexOf("MSIE") >= 0)                
{                
 // IE-specific code                
}                
else if(browser.indexOf("Mozilla") >= 0)                
{                
 // Mozilla-specific code                
}                
else                
{                
 // any other browser                
}                
%>

Note our usage of the indexOf() method - you may remember this from previous articles in this series.

Copyright Melonfire, 2000. All rights reserved.

Taking Some Medication

Just as you can access data from text fields, you can also use the
getParameter() method to evaluate the state of radio buttons and list boxes. Suppose you modify the form above to something a little more complex.

<html>                  
                 
<head>                  
<basefont face="Arial">                  
</head>                  
                 
<body>                  
                 
<center>                  
<form method="GET" action="pills.jsp">                  
                 
<font size="-1" face="Arial">                  
Gimme                  
<select name="quantity">                  
<option value="10">10</option>                  
<option value="25">25</option>                  
<option value="50">50</option>                  
<option value="100">100</option>                  
</select>                  
of those little                  
<input type="Radio" name="colour" value="red" checked>red                  
<input type="Radio" name="colour" value="blue">blue                    
pills, willya? </font>                  
                 
<p>                  
                 
<input type="Submit">                  
</form>                  
                 
</center>                  
</body>                  
                 
</html>

And here's "pills.jsp".

<html>                  
<head>                  
<basefont face="Arial">                  
</head>                  
                 
<body>                  
<center>                  
<%                  
// pills.jsp                  
                 
// define the variables and assign values                  
String colour = request.getParameter("colour");                  
String quantity_string = request.getParameter("quantity");                  
                 
// convert string to number                  
int quantity = Integer.parseInt(quantity_string);                  
                 
                 
// process and display                  
                 
// who needs green pills?                  
if (colour.equals("blue"))                  
{                  
out.println("Sorry, we don't carry blue pills here.");                  
}                  
else                  
{                  
 if (quantity >= 50)                  
 {                  
 out.println("Stocking up, are we?");                  
 }                  
 else                  
 {                  
 out.println("Here you go. And would you like fries with that?");                  
 }                  
}                  
%>                  
</center>                  
</body>                  
</html>

Depending on the combination of pill type and quantity, an appropriate message will be displayed.

As you can see, evaluating radio buttons and list boxes is almost exactly the same as evaluating regular text fields.

Before moving on to the other form constructs - namely, checkboxes and multiple-select list boxes - you need to understand a new type of variable: the JSP array.

Copyright Melonfire, 2000. All rights reserved.

What's For Dessert?

Thus far, the variables you've used contain only a single value - for example,

int i = 0

However, array variables are a different kettle of fish altogether. An array variable can best be thought of as a "container" variable, which can contain one or more values. For example,

String[] desserts = {"chocolate mousse", "tiramisu",                    
"apple pie", "chocolate fudge cake"};

Here, "desserts" is an array variable, which contains the values "chocolate mousse", "tiramisu", "apple pie", and "chocolate fudge cake".

Array variables are particularly useful for grouping related values together - names, dates, phone numbers of ex-girlfriends et al.

The various elements of the array are accessed via an index number, with the first element starting at zero. So, to access the element

"chocolate mousse"

you would use the notation

desserts[0]

while

"chocolate fudge cake"

would be

desserts[3]

- essentially, the array variable name followed by the index number enclosed within square braces. Geeks refer to this as "zero-based indexing".

Defining an array variable in JSP is somewhat convoluted, as compared to languages like PHP and Perl; you need to first declare the variable and its type, and then actually create the array.

<%                   
// declare type of array                  
String[] desserts;                  
                 
// initialize array                  
// the number indicates the number of elements the array will                    
hold desserts = new String[4];                  
                 
// assign values to array elements                  
desserts[0] = "chocolate mousse";                  
desserts[1] = "tiramisu";                  
desserts[2] = "apple pie";                  
desserts[3] = "chocolate fudge cake";                  
%>

Or you can use the simpler version:

<%                   
String[] desserts = {"chocolate mousse", "tiramisu",                    
"apple pie", "chocolate fudge cake"}; %>

Note that if you try to add more elements than the number specified when creating the array, JSP will barf with a series of strange error message.

A Chocolate Addiction

In order to modify an element of an array, you would simply assign a new value to the corresponding variable. If you wanted to replace "chocolate fudge cake" with "chocolate chip cookies", you'd simply use

<%                   
desserts[3] = "chocolate chip cookies";                  
%>

and the array would now read

String[] desserts = {"chocolate mousse", "tiramisu",                    
"apple pie", "chocolate chip cookies"};

JSP arrays can only store the type of data specified at the time of declaring the array variable; a string array cannot hold numbers, or vice-versa.

And finally, you can obtain the number of items in an array with the "length" property - the following example demonstrates this:

<html>                   
<head>                  
<basefont face="Arial">                  
</head>                  
                 
<body>                  
<%                  
// define an array                  
String[] desserts = {"chocolate mousse", "tiramisu",                    
"apple pie", "chocolate fudge cake"};                  
                 
// display array length                  
out.println("The dessert menu                    
contains " + desserts.length + " items.");  %>  </body> </html>

And the output is:

The dessert menu contains 4 items.

You can use a "for" loop to iterate through the elements of an array, as the following example demonstrates.

<html>                   
<head>                  
<basefont face="Arial">                  
</head>                  
                 
<body>                  
Desserts available:                  
<ul>                  
                 
<%                  
// define counter                  
int counter;                  
                 
// define an array                  
String[] desserts = {"chocolate mousse", "tiramisu",                    
"apple pie", "chocolate fudge cake"};                  
                 
for (counter=0; counter<desserts.length; counter++)                  
{                  
out.println("<li>" + desserts[counter] + "<br>");                  
}                  
%>                  
                 
</ul>                  
</body>                  
</html>

And the output is:

Desserts available:                   
· chocolate mousse                  
· tiramisu                  
· apple pie                  
· chocolate fudge cake

Copyright Melonfire, 2000. All rights reserved.

Couch Potato

Arrays come in particularly handy when dealing with form elements like checkboxes and multiple select list boxes. Take a look at the following form, which includes a bunch of checkboxes:

<html>                    
<head>                    
<basefont face="Arial">                    
</head>                    
<body>                    
                   
Pick your favourite shows:                    
<br>                    
<form action="potato.jsp" method="POST">                    
<input type="checkbox" name="shows" value="Ally McBeal">Ally                    
McBeal <input type="checkbox" name="shows" value="Buffy The                    
Vampire Slayer">Buffy The Vampire Slayer <input type="checkbox"                    
name="shows" value="The Practice">The Practice <input                    
type="checkbox" name="shows" value="Sex And The City">Sex                    
And The City <input type="checkbox" name="shows"                    
value="The Sopranos">The Sopranos <input type="checkbox"                    
name="shows" value="Survivor">Survivor <br> <input type="submit"                    
name="submit" value="Select"> </form>                    
                   
</body>                    
</html>

Now, once the form is submitted, the JSP script "potato.jsp" is responsible for processing the states of the various checkboxes. Data from the checkboxes is assigned to an array, and then this array is used to recreate a list of the selected items. Take a look.

<html>                    
<head>                    
<basefont face="Arial">                    
</head>                    
<body>                    
                   
So your favourite shows are:                    
<br>                    
<%                    
                   
// potato.jsp - process list of selected TV shows                    
                   
// define variables                    
String[] Shows;                    
                   
// assign values to variables                    
Shows = request.getParameterValues("shows");                    
                   
out.println("<ul>");                    
                   
// print by iterating through array                    
for(int counter = 0; counter < Shows.length; counter++)                    
{                    
 out.println("<li>" + Shows[counter]);                    
}                    
                   
out.println("</ul>");                    
%>                    
                   
</body>                    
</html>

As you can see, the first order of business is to create an array to hold the checkbox data - in this case, the array "Shows". Then, the Request object is used to obtain the values of the selected items via the
getParameterValues() method (similar to the getParameter() method, but returns a list of values, rather than a single value) and these values are then assigned to the "Shows" array. A "for" loop is then used to create a list of the selected items.

This technique can also be used with multiple select list boxes - here's the same example, rewritten to use a list box instead of a series of checkboxes.

<html>                    
<head>                    
<basefont face="Arial">                    
</head>                    
<body>                    
                   
Pick your favourite shows:                    
<br>                    
<form action="potato.jsp" method="POST">                    
<select name="shows" multiple>                    
 <option>Ally McBeal</option>                    
   <option>Buffy The Vampire Slayer</option>                    
   <option>The Practice</option>                    
   <option>Sex And The City</option>                    
   <option>The Sopranos</option>                    
   <option>Survivor</option>                    
</select>                    
<br>                    
<input type="submit" name="submit" value="Select">                    
</form>                    
                   
</body>                    
</html>

Obviously, the server-side script "potato.jsp" requires no changes at all.

Copyright Melonfire, 2000. All rights reserved.

Beating It Into Submission

You'll have noticed that in all the examples we've shown you thus far, we've used two pages - a single HTML page containing the form, and a separate JSP script which processes the form input and generates appropriate output. However, JSP provides an elegant method to combine those two pages into one via the form's SUBMIT button.

You've already seen that once a form is submitted to a JSP script, all the form variables become available to JSP. Now, in addition to the user-defined variables, each time you hit the SUBMIT button on a form, a variable named "submit" is created. And by testing for the presence or absence of this variable, a clever JSP developer can use a single JSP document to generate both the initial form and the output after it has been submitted.

The following code snippet demonstrates how the "welcome to The Matrix" example above could be rewritten using this technique.

<html>                     
<head>                    
<basefont face="Arial">                    
</head>                    
                   
<body>                    
<center>                    
<%                    
// matrix.jsp                    
                   
// check for submit variable                    
String submit = request.getParameter("submit");                    
                   
if(submit != null)                    
{                    
// form has been submitted, display result                    
                   
// define the variables used in the scriptlet                    
String fname;                    
  f                 
// assign values                    
fname = request.getParameter("name");                    
                   
// print the details                    
out.println("Welcome to The Matrix, " + fname + "!");                    
                   
}                    
else                    
{                    
// display initial form                    
%>                    
                   
<form method="GET" action="matrix.jsp">                    
<table cellspacing="5" cellpadding="5" border="0">                    
                   
<tr>                    
<td>                    
<font size="-1">Name, rank and serial, number, soldier!</font>                      
</td> <td align="left"> <input type="text" name="name" size="10">                      
</td> </tr>                    
                   
<tr>                    
<td colspan="2" align="center">                    
<input name="submit" type="submit">                    
</td>                    
</tr>                    
                   
</table>                    
</form>                    
                   
<%                    
}                    
%>                    
</center>                    
</body>                    
</html>

As you can see, the script first tests for the presence of the "submit" variable - if it doesn't find it, it assumes that the form has yet to be submitted and so displays the initial form.

Since the ACTION attribute of the <FORM> tag references the same JSP script, once the form has been submitted, the same script will be called to process the form input. This time, however, the "submit" variable will exist, and so JSP will not display the initial page, but rather the result page.

Note that for this to work, your

<input type="submit">

must have a NAME attribute with the value "submit", like this:

<input type="submit" name="submit">

And that's about it. Next time, we'll be hooking JSP up to a database in order to generate dynamic Web page - so don't miss that one. Until then...stay healthy!

Note: All examples in this article have been tested on Linux/i586 with Tomcat 3.2 and JServ 1.1. Examples are illustrative only, and are not meant for a production environment. YMMV!
Copyright Melonfire, 2000. All rights reserved.

The JSP Files - Part 5: No Forwading Address

Toolbox

JSP offers a number of advantages over other server-side scripting languages - as you've already seen, performance is just one of them. And this performance edge becomes particularly important when you combine it with another important benefit - the ability to seamlessly connect to a variety of database servers.

By offering seamless database connectivity (okay, it's not as transparent as the database connectivity available in PHP, but it's still pretty good!) in combination with faster response times, JSP allows developers to build complex, scalable, data-driven Web applications while simultaneously enjoying short development cycles.

OK, 'nuff said. Let's cut to the chase.

In this article, we're going to demonstrate how to use JSP to connect to a database, extract data from it, and use that data to build a dynamic Web page. We'll be building a simple Web application in order to help make the process clearer; this should also help you quantify how much easier (or harder) JSP is to use, as compared to other server-side scripting languages you may be familiar with.

If you're planning on trying out the examples below (recommended), you'll need to download and install the mySQL database server, available at http://www.mysql.com/. mySQL is a fast, reliable, open-source database management system, which offers a fair amount of power at a price that should move you to tears - it's free!

We'll be assuming that you've installed and configured mySQL, and have the appropriate permissions to create and edit database tables.

Since all database interaction in Java takes place using a technology known as JDBC, or Java Database Connectivity, you'll also need a JDBC module that allows you to connect to the mySQL database server. We'll be assuming that you've downloaded the mm.mySQL JDBC module from "Slapping Together A JSP Development Environment".

If you're using a database other than mySQL, fear not - JSP supports all major databases, and you can use the techniques described over the next few pages to talk to other databases too. You'll probably need to consult your database vendor's manual or Web site for information on how to obtain the necessary software.

Finally, some knowledge of SQL would come in handy. In case you don't know SQL, don't worry - it's extremely simple, and a few minutes with the "Speaking SQL" tutorial will have you executing queries like an expert.

With all that out of the way, let's actually get our hands dirty.

Dumped!

If you're familiar with SQL, you know that there are four basic types of operations possible with a database:

  • SELECT a record;
  • INSERT a record;
  • UPDATE a record;
  • DELETE a record.

In order to demonstrate these operations, we're going to build a little application that requires each of the functions listed above - an address book which allows multiple users to store and view contact information online.

As always, one of the first things you have to think about when designing a data-driven application is the design of the database (duh!). For this application, we've decided to use a single table called "abook", which contains fields for different types of contact information - address, phone, fax, email address, and the like. Every user in the system has a unique login id, and each record in the database is "owned" by a specific user.

We've put together a "dump file", which lets you create the database tables and initial set of records quickly - we suggest that you import this data into your mySQL database server, as we'll be using it throughout this article.

To import the data, download the dump file and use this command at your mySQL prompt:

mysql> mysql -u username -p database < dumpfile

Or you could insert the contents manually - here is what you'll need:

#                      
# Table structure for table 'abook'                      
#                      
                     
DROP TABLE IF EXISTS abook;                      
CREATE TABLE abook (                      
  id int(11) unsigned NOT NULL auto_increment,                      
  uid varchar(255) NOT NULL,                      
  fname varchar(255) NOT NULL,                      
  lname varchar(255) NOT NULL,                      
  tel varchar(255),                      
  fax varchar(255),                      
  email varchar(255),                      
  addr text,                      
  company varchar(255),                      
  comment text,                      
  PRIMARY KEY (id)                      
);                      
                     
#                      
# Dumping data for table 'abook'                      
#                      
                     
INSERT INTO abook (id, uid, fname, lname, tel, fax, email,                      
addr, company,comment) VALUES ( '1', 'john', 'Bugs',                      
'Bunny', '7376222', '', 'bugs@somedomain.com', 'The Rabbit                      
Hole, Dark Woods, Somewhere On Planet Earth', '',                      
'Big-ears in da house!'); INSERT INTO abook (id, uid,                      
fname, lname, tel, fax, email, addr, company,                      
comment) VALUES ( '2', 'john', 'Elmer', 'Fudd', '', '7628739',                      
'fuddman@somedomain.com','', '', ''); INSERT INTO abook (id,                      
uid, fname, lname, tel, fax, email, addr, company,comment)                      
VALUES ( '3', 'joe', 'Peter', 'Parker', '162627 x34', '',                      
'webcrawler@somedomain.com', 'Your Friendly Neighbourhood                      
Newspaper', '', 'My spidey-sense is tingling!');                      
INSERT INTO abook (id, uid, fname, lname, tel, fax, email,                      
addr, company, comment) VALUES ( '4', 'bill',                      
'Clark', 'Kent', '1-800-SUPERMAN', '',                      
'superdude@somedomain.com', '', '', 'Is it a bird? Is                      
it a plane?');

This will create a table named "abook" with columns for different types of contact information; these records are owned by three mythical users, "bill", "john" and "joe".

Now check whether or not the data has been successfully imported with a SELECT query (the SELECT SQL statement is used to retrieve information from a database). Enter this at your mySQL command prompt:

mysql> select uid, fname, lname from abook;

which, in English, means "display the columns uid, fname and lname from the address book". Here's what you should see:
+------+-------+--------+                      
| uid  | fname | lname  |                      
+------+-------+--------+                      
| john | Bugs  | Bunny  |                      
| john | Elmer | Fudd   |                      
| joe  | Peter | Parker |                      
| bill | Clark | Kent   |                      
+------+-------+--------+                      
4 rows in set (0.00 sec)

Copyright Melonfire, 2000. All rights reserved.

The Scenic Route

All working? Good. Now, let's use JSP to do exactly the same thing - fire a SELECT query at the database, and display the results in an HTML page.

<html>                       
<head>                      
<basefont face="Arial">                      
</head>                      
<body>                      
<%@ page language="java" import="java.sql.*" %>                      
                     
<%!                      
// define variables                      
String UId;                      
String FName;                      
String LName;                      
                     
// define database parameters                      
String host="localhost";                      
String user="us867";                      
String pass="jsf84d";                      
String db="db876";                      
String conn;                      
%>                      
                     
<table border="2" cellspacing="2" cellpadding="5">                      
                     
<tr>                      
<td><b>Owner</b></td>                      
<td><b>First name</b></td>                      
<td><b>Last name</b></td>                      
</tr>                      
                     
<%                      
                     
Class.forName("org.gjt.mm.mysql.Driver");                      
                     
// create connection string                      
conn = "jdbc:mysql://" + host + "/" + db + "?user=" + user                        
+ "&password=" + pass;                      
                     
// pass database parameters to JDBC driver                      
Connection Conn = DriverManager.getConnection(conn);                      
                     
// query statement                      
Statement SQLStatement = Conn.createStatement();                      
                     
// generate query                      
String Query = "SELECT uid, fname, lname FROM abook";                      
                     
// get result                      
ResultSet SQLResult = SQLStatement.executeQuery(Query);                      
                     
 while(SQLResult.next())                      
 {                      
   UId = SQLResult.getString("uid");                      
   FName = SQLResult.getString("fname");                      
   LName = SQLResult.getString("lname");                      
                     
   out.println("<tr><td>" + UId + "</td><td>" +                        
FName + "</td><td>" + LName + "</td></tr>");                      
 }                      
                     
// close connection                      
SQLResult.close();                      
SQLStatement.close();                      
Conn.close();                      
                     
%>                      
                     
</table>                      
</body>                      
</html>

And you'll see something like this:
                     
Owner  First name  Last name                      
john  Bugs    Bunny                      
john  Elmer    Fudd                      
joe  Peter    Parker                      
bill  Clark    Kent

Copyright Melonfire, 2000. All rights reserved.

One Step At A Time

Using JSP to extract data from a database involves several steps. Let's dissect each one.

1. First, we need to make sure that all the modules required for a JDBC connection are available to the JSP document. This is accomplished by means of the

<%@ page                        
...                        
%>

directive, used to define attributes that affect the JSP document.

<%@ page language="java" import="java.sql.*" %>

The "import" attribute is used to import all the packages and classes required for the script to execute - here, all the packages in the "java.sql.*" tree.

2. Next, it's necessary to declare all the variables required for this scriptlet; we've kept aside some for the results of the SQL query, and also created variables to hold database-specific information, such as the name of the database server, the username and password required to gain access, and the database to use for all queries. This information is used to build a connection string, at a later stage.

3. The next step is to load the JDBC driver required to access a mySQL database - this is accomplished with the statement

Class.forName("org.gjt.mm.mysql.Driver");

The name of the driver to be used for a specific database can always be obtained from the documentation you receive with the driver.

4. Now that the drivers have been loaded, it's time to open a connection to the database server. This is accomplished by means of the Connection object and its getConnection() method.

The getConnection() method requires a connection string as argument; this connection string is created by combining the server name, the username and password, and the name of the database to use into a single URL-like string.

// create connection string                        
conn = "jdbc:mysql://" + host + "/" + db + "?user=" + user                        
+ "&password=" + pass;                        
                       
// pass database parameters to JDBC driver                        
Connection Conn = DriverManager.getConnection(conn);

The getConnect() method then returns a connection identifier, which is used for subsequent SQL queries. All communication between JSP and the database server takes place through this connection. In this case, the specific instance of the Connection object is called "Conn".

5. Once a connection to the database is available, the Statement object is used to prepare a SQL statement for execution.

// query statement                        
Statement SQLStatement = Conn.createStatement();

6. At this point, a query is created:

// generate query                        
String Query = "SELECT uid, fname, lname FROM abook";

and the ResultSet object is used to store the results of the query.

// get result                        
ResultSet SQLResult = SQLStatement.executeQuery(Query);

7. Once the query has been executed and the results returned, a number of methods can be used to iterate through the result set. The example above uses the next() method, which simply moves forward through the list of records returned by the query. A "while" loop is used to iterate through the result set in combination with the next() method.

// get and display each record                        
 while(SQLResult.next())                        
 {                        
   UId = SQLResult.getString("uid");                        
   FName = SQLResult.getString("fname");                        
   LName = SQLResult.getString("lname");                        
                       
   out.println("<tr><td>" + UId + "</td><td>" +                        
FName + "</td><td>" + LName + "</td></tr>");                        
 }

Incidentally, the ResultSet object also comes with a handy prev() method, which allows you to display the preceding record.

The getString() method is used to access specific columns in the record currently being examined; these values are stored as strings in the JSP document. In addition to the getString() method, you can also use the getInt(), getTimeStamp() and getBoolean() methods to obtain column values as specific variable types.

8. Finally, each result set returned after a query occupies some amount of memory - and if your system is likely to experience heavy load, it's a good idea to use the various close() methods to free up memory.

// close connection                        
SQLResult.close();                        
SQLStatement.close();                        
Conn.close();

As you can see, connecting to a database through JSP is a little more complicated than the equivalent procedure in PHP. There's not much you can do about this but grin and bear it.
Copyright Melonfire, 2000. All rights reserved.

What's Your Name?

Now that you know how to connect to a database, let's begin developing the bare bones of the address book application. This first script asks for a user name and then connects to the database to display entries owned by that user.

We'll be using a single page for the entire operation - the "submit" variable (you remember this technique, don't you?) is used to decide whether to display the initial form or the result page. Take a look:

<html>                         
<head>                        
<basefont face="Arial">                        
</head>                        
                       
<body>                        
<center>                        
<%                        
// check submit state                        
String submit = request.getParameter("submit");                        
                       
// form not yet submitted                        
// display initial page                        
if(submit == null)                        
{                        
%>                        
                       
<form action="view.jsp" method="GET">                        
Enter your name:&nbsp;                        
<input type="text" name="name" size="10"> &nbsp; <input                          
type="submit" name="submit" value="Go"> </form>                        
                       
<%                        
}                        
// form submitted, display result                        
else                        
{                        
%>                        
                       
<%@ page language="java" import="java.sql.*" %>                        
                       
<%                        
// get username                        
String uid = request.getParameter("name");                        
                       
// define database parameters                        
String host="localhost";                        
String user="us867";                        
String pass="jsf84d";                        
String db="db876";                        
String conn;                        
%>                        
                       
<h2><% out.println(uid); %>'s Little Black Book</h2>                        
<hr>                        
                       
<table border=1 cellspacing=4 cellpadding=4>                        
<tr>                        
<td><b>First name</b></td>                        
<td><b>Last name</b></td>                        
<td><b>Tel</b></td>                        
<td><b>Fax</b></td>                        
<td><b>Email address</b></td>                        
</tr>                        
                       
<%                        
Class.forName("org.gjt.mm.mysql.Driver");                        
                       
// create connection string                        
conn = "jdbc:mysql://" + host + "/" + db + "?user=" + user                          
+ "&password=" + pass;                        
                       
// pass database parameters to JDBC driver                        
Connection Conn = DriverManager.getConnection(conn);                        
                       
// query statement                        
Statement SQLStatement = Conn.createStatement();                        
                       
// generate query                        
String Query = "SELECT * FROM abook WHERE uid = '" + uid + "'";                        
                       
// get result                        
ResultSet SQLResult = SQLStatement.executeQuery(Query);                        
                       
// display records                        
// if available                        
 while(SQLResult.next())                        
 {                        
   String FName = SQLResult.getString("fname");                        
   String LName = SQLResult.getString("lname");                        
   String Tel = SQLResult.getString("tel");                        
   String Fax = SQLResult.getString("fax");                        
   String Email = SQLResult.getString("email");                        
                       
   out.println("<tr><td>" + FName + "</td><td>" +                          
LName + "</td><td>" + Tel + "</td><td>" + Fax + "</td><td>" +                          
Email + "</td></tr>");                        
 }                        
// close connections                        
SQLResult.close();                        
SQLStatement.close();                        
Conn.close();                        
                       
}                        
%>                        
                       
</table>                        
</center>                        
</body>                        
</html>

As you can see, by checking the value of the "submit" variable, we've successfully combined both the initial page and the results page into a single JSP script. This script simply accepts a user name, connects to the database, and displays records for that user (assuming any exist). Log in as "bill", "joe" or "john" to view the records available for that user.

If you don't like the word "null" being displayed in columns which have no data, you can add a few "if" loops to replace it with an empty space.

<%                         
if (Fax.equals("null"))                        
{                        
Fax = "&nbsp;";                        
}                        
%>

Copyright Melonfire, 2000. All rights reserved.

New Friends

Thus far, we've simply been using SELECT queries to pull information out of a database. But how about putting something in?

SQL aficionados know that this happens via an INSERT query. And so, the next item on the agenda involves adding new entries to the address book. Here's the form we'll be using:

<html>                          
<head>                          
<basefont face="Arial">                          
</head>                          
                         
<body>                          
<center>                          
<h2>Add Address Book Entry</h2>                          
                         
<table border=0 cellspacing=5 cellpadding=5>                          
<form action="add_res.jsp" method="POST">                          
                         
<tr>                          
<td><b>Username</b></td>                          
<td>                          
<select name="uid">                          
<!-- generate list of available usernames from database -->                          
<%@ page language="java" import="java.sql.*" %>                          
<%                          
                         
 // database parameters                          
 String host="localhost";                          
String user="us867";                          
String pass="jsf84d";                          
String db="db876";                          
 String connString;                          
                         
 // load driver                          
 Class.forName("org.gjt.mm.mysql.Driver");                          
                         
 // create connection string                          
 connString = "jdbc:mysql://" + host + "/" + db + "?user="                          
       + user + "&password=" +  pass;                          
                         
 // pass database parameters to JDBC driver                          
 Connection Conn = DriverManager.getConnection(connString);                          
                         
 // query statement                          
 Statement SQLStatement = Conn.createStatement();                          
                         
 // generate query                          
 String Query = "SELECT DISTINCT uid FROM abook";                          
                         
 // get result                          
 ResultSet SQLResult = SQLStatement.executeQuery(Query);                          
                         
 // get and display each record                          
   while(SQLResult.next())                          
   {                          
     String UId = SQLResult.getString("uid");                          
                         
     out.println("<option>" + UId);                          
   }                          
                         
 // close connections                          
 SQLResult.close();                          
 SQLStatement.close();                          
 Conn.close();                          
                         
 %>                          
                         
</select>                          
</td>                          
</tr>                          
                         
<tr>                          
<td>First name</td>                          
<td><input type="Text" name="fname" size="15"></td>                          
</tr>                          
                         
<tr>                          
<td>Last name</td>                          
<td><input type="Text" name="lname" size="15"></td>                          
</tr>                          
                         
<tr>                          
<td>Address</td>                          
<td><textarea name="address"></textarea></td>                          
</tr>                          
                         
<tr>                          
<td>Tel</td>                          
<td><input type="Text" name="tel" size="10"></td>                          
</tr>                          
                         
<tr>                          
<td>Fax</td>                          
<td><input type="Text" name="fax" size="10"></td>                          
</tr>                          
                         
<tr>                          
<td>Email address</td>                          
<td><input type="Text" name="email" size="10"></td>                          
</tr>                          
                         
<tr>                          
<td>Company</td>                          
<td><input type="Text" name="company" size="25"></td>                          
</tr>                          
                         
<tr>                          
<td>Comment</td>                          
<td><input type="Text" name="comment" size="25"></td>                          
</tr>                          
                         
<tr>                          
<td colspan=2><input type="submit" name="submit"                          
value="Add"></td> </tr>                          
                         
</form>                          
</table>                          
                         
</center>                          
</body>                          
</html>

If you examine it closely, you'll see that this form performs a query to retrieve the list of users currently available in the system, and uses this data to generate a list box containing the different user names. This makes it possible to specify the owner of each record when it is INSERTed.

Once the form has been filled up and submitted, control passes to "add_res.jsp", which takes care of actually performing the INSERT operation. Take a look.

<html>                          
<head>                          
<basefont face="Arial">                          
</head>                          
<body>                          
<center>                          
                         
<%@ page language="java" import="java.sql.*" %>                          
                         
<%                          
// add_res.jsp                          
                         
// form data                          
String uid = request.getParameter("uid");                          
String fname = request.getParameter("fname");                          
String lname = request.getParameter("lname");                          
String address = request.getParameter("address");                          
String tel = request.getParameter("tel");                          
String fax = request.getParameter("fax");                          
String email = request.getParameter("email");                          
String company = request.getParameter("company");                          
String comment = request.getParameter("comment");                          
                         
// database parameters                          
String host="localhost";                          
String user="us867";                          
String pass="jsf84d";                          
String db="db876";                          
String conn;                          
                         
Class.forName("org.gjt.mm.mysql.Driver");                          
                         
// create connection string                          
conn = "jdbc:mysql://" + host + "/" + db + "?user=" + user          f                
+ "&password=" + pass;                          
                         
// pass database parameters to JDBC driver                          
Connection Conn = DriverManager.getConnection(conn);                          
                         
// query statement                          
Statement SQLStatement = Conn.createStatement();                          
                         
// generate query                          
String Query = "INSERT INTO abook (id, uid, fname, lname,                          
tel, fax, email, addr, company, comment) VALUES (NULL, '" +                          
uid + "', '" + fname + "', '" + lname + "', '" + tel                          
+ "', '" + fax + "', '" + email + "', '" + address + "',                          
'" + company + "', '" + comment + "')";                          
                         
// get result code                          
int SQLStatus = SQLStatement.executeUpdate(Query);                          
                         
 if(SQLStatus != 0)                          
 {                          
 out.println("Entry succesfully added.");                          
 }                          
 else                          
 {                          
 out.println("Error! Please try again.");                          
 }                          
                         
// close connection                          
SQLStatement.close();                          
Conn.close();                          
                         
%>                          
                         
</center>                          
</body>                          
</html>

This example demonstrates yet another method of the Statement object, the executeUpdate() method, used for INSERT or UPDATE operations. This method returns a result code indicating the number of rows affected by the operation - in case of the example above, this result code should be 1. In case it isn't...you've got trouble!

It should be noted at this point that if your INSERT statement contains special characters which need to be escaped (say, commas or single quotes), you'd do better to use the PreparedStatement class, which automatically takes care of escaping special characters and offers some performance benefits as well. A discussion of the PreparedStatement class is beyond the scope of this tutorial, but there's plenty of documentation out there should you ever require it.
Copyright Melonfire, 2000. All rights reserved.

No Forwarding Address

Next up, updating records. In order to demonstrate this, the first order of business is to modify the next-to-last example so that each entry displayed has an edit option next to it. Here's the modified code:

<html>                           
<head>                          
<basefont face="Arial">                          
</head>                          
                         
<body>                          
<center>                          
<%                          
// check submit state                          
String submit = request.getParameter("submit");                          
                         
// form not yet submitted                          
// display initial page                          
if(submit == null)                          
{                          
%>                          
                         
<form action="view.jsp" method="GET">                          
Enter your name:&nbsp;<input type="text" name="name"                            
size="10"> &nbsp; <input type="submit" name="submit"                            
value="Go"> </form>                          
                         
<%                          
}                          
// form submitted, display result                          
else                          
{                          
%>                          
                         
<%@ page language="java" import="java.sql.*" %>                          
                         
<%                          
// get username                          
String uid = request.getParameter("name");                          
                         
// define database parameters                          
String host="localhost";                          
String user="us867";                          
String pass="jsf84d";                          
String db="db876";                          
String conn;                          
%>                          
                         
<h2><% out.println(uid); %>'s Little Black Book</h2>                          
<hr>                          
                         
<table border=1 cellspacing=4 cellpadding=4>                          
<tr>                          
<td><b>First name</b></td>                          
<td><b>Last name</b></td>                          
<td><b>Tel</b></td>                          
<td><b>Fax</b></td>                          
<td><b>Email address</b></td>                          
<td>&nbsp;</td>                          
</tr>                          
                         
<%                          
Class.forName("org.gjt.mm.mysql.Driver");                          
                         
// create connection string                          
conn = "jdbc:mysql://" + host + "/" + db + "?user="                            
+ user + "&password=" + pass;                          
                         
// pass database parameters to JDBC driver                          
Connection Conn = DriverManager.getConnection(conn);                          
                         
// query statement                          
Statement SQLStatement = Conn.createStatement();                          
                         
// generate query                          
String Query = "SELECT * FROM abook WHERE uid = '" + uid + "'";                          
                         
// get result                          
ResultSet SQLResult = SQLStatement.executeQuery(Query);                          
                         
// display records                          
// if available                          
 while(SQLResult.next())                          
 {                          
   String FName = SQLResult.getString("fname");                          
   String LName = SQLResult.getString("lname");                          
   String Tel = SQLResult.getString("tel");                          
   String Fax = SQLResult.getString("fax");                          
   String Email = SQLResult.getString("email");                          
                         
   // get the record number HERE                          
   String ID = SQLResult.getString("id");                          
                         
   // add an edit link to each record with the ID                          
   out.println("<tr><td>" + FName + "</td><td>"                            
+ LName + "</td><td>" + Tel + "</td><td>" + Fax + "</td><td>"                            
+ Email + "</td><td><a + href=edit.jsp?id=" ID + ">edit this                            
entry</a></td></tr>");                          
 }                          
                         
// close connections                          
SQLResult.close();                          
SQLStatement.close();                          
Conn.close();                          
                         
}                          
%>                          
                         
</table>                          
</center>                          
</body>                          
</html>

Clicking this link will activate the script "edit.jsp" and pass the record number to it via the URL GET method.

Let's now take a look at "edit.jsp"

                           
<html>                          
<head>                          
<basefont face="Arial">                          
</head>                          
                         
<body>                          
<center>                          
<h2>Update Address Book Entry</h2>                          
                         
<%@ page language="java" import="java.sql.*" %>                          
                         
<%                          
// form variables                          
String fid = request.getParameter("id");                          
int id = Integer.parseInt(fid);                          
                         
String fname = "";                          
String lname = "";                          
String tel = "";                          
String fax = "";                          
String email = "";                          
String address = "";                          
String company = "";                          
String comment = "";                          
                         
// database parameters                          
String host="localhost";                          
String user="us867";                          
String pass="jsf84d";                          
String db="db876";                          
String conn;                          
                         
Class.forName("org.gjt.mm.mysql.Driver");                          
                         
// create connection string                          
conn = "jdbc:mysql://" + host + "/" + db + "?user=" + user                            
+ "&password=" + pass;                          
                         
// pass database parameters to JDBC driver                          
Connection Conn = DriverManager.getConnection(conn);                          
                         
// query statement                          
Statement SQLStatement = Conn.createStatement();                          
                         
// generate query                          
String Query = "SELECT * FROM abook where id=" + id;                          
                         
// get result                          
ResultSet SQLResult = SQLStatement.executeQuery(Query);                          
                         
// get and display record                          
 fname = SQLResult.getString("fname");                          
 lname = SQLResult.getString("lname");                          
 tel = SQLResult.getString("tel");                          
 fax = SQLResult.getString("fax");                          
 email = SQLResult.getString("email");                          
 address = SQLResult.getString("addr");                          
 company = SQLResult.getString("company");                          
 comment = SQLResult.getString("comment");                          
                         
// close connection                          
SQLResult.close();                          
SQLStatement.close();                          
Conn.close();                          
%>                          
                         
<table border=0 cellspacing=5 cellpadding=5>                          
<form action="edit_res.jsp" method="POST">                          
                         
<input type="hidden" name="id" value="<%= id %>">                          
                         
<tr>                          
<td>First name</td>                          
<td><input type="Text" name="fname" size="15" value="<%=                            
fname %>"></td> </tr>                          
                         
<tr>                          
<td>Last name</td>                          
<td><input type="Text" name="lname" size="15" value="<%=                            
lname %>"></td> </tr>                          
                         
<tr>                          
<td>Address</td>                          
<td><textarea name="address"><%= address %></textarea></td> </tr>                          
                         
<tr>                          
<td>Tel</td>                          
<td><input type="Text" name="tel" size="10" value="<%=                            
tel %>"></td> </tr>                          
                         
<tr>                          
<td>Fax</td>                          
<td><input type="Text" name="fax" size="10" value="<%=                            
fax %>"></td> </tr>                          
                         
<tr>                          
<td>Email address</td>                          
<td><input type="Text" name="email" size="10" value="<%=                            
email %>"></td> </tr>                          
                         
<tr>                          
<td>Company</td>                          
<td><input type="Text" name="company" size="25" value="<%=                            
company %>"></td> </tr>                          
                         
<tr>                          
<td>Comment</td>                          
<td><input type="Text" name="comment" size="25" value="<%=                            
comment %>"></td> </tr>                          
                         
<tr>                          
<td colspan=2><input type="submit" name="submit"                            
value="Update"></td> </tr>                          
                         
</form>                          
</table>                          
                         
</center>                          
</body>                          
</html>

As you can see, once "edit.jsp" receives the record number, it connects to the database, extracts the record, and then generates a simple form with the values already filled in (note our usage of the shortcut <%= %> construct to display variable values). The user is then free to modify the information displayed in the form; once done, the form is submitted to "edit_res.jsp", which takes care of the UPDATE operation.

<html>                           
<head>                          
<basefont face="Arial">                          
</head>                          
<body>                          
<center>                          
                         
<%@ page language="java" import="java.sql.*" %>                          
                         
<%                          
// edit_res.jsp                          
                         
// form data                          
String fid = request.getParameter("id");                          
int id = Integer.parseInt(fid);                          
                         
String fname = request.getParameter("fname");                          
String lname = request.getParameter("lname");                          
String address = request.getParameter("address");                          
String tel = request.getParameter("tel");                          
String fax = request.getParameter("fax");                          
String email = request.getParameter("email");                          
String company = request.getParameter("company");                          
String comment = request.getParameter("comment");                          
                         
// database parameters                          
String host="localhost";                          
String user="root";                          
String pass="";                          
String db="test";                          
String conn;                          
                         
Class.forName("org.gjt.mm.mysql.Driver");                          
                         
// create connection string                          
conn = "jdbc:mysql://" + host + "/" + db + "?user=" + user                            
+ "&password=" + pass;                          
                         
// pass database parameters to JDBC driver                          
Connection Conn = DriverManager.getConnection(conn);                          
                         
// query statement                          
Statement SQLStatement = Conn.createStatement();                          
                         
// generate query                          
String Query = "UPDATE abook SET fname='" + fname + "', lname='"                            
+ lname + "', tel='" + tel + "', fax='" + fax + "', email='"                            
+ email + "', addr='" + address + "', company='"  + company                            
+ "', comment='"  + comment + "' WHERE id=" + id;                          
                         
// get result code                          
int SQLStatus = SQLStatement.executeUpdate(Query);                          
                         
 if(SQLStatus != 0)                          
 {                          
 out.println("Entry successfully updated.");                          
 }                          
 else                          
 {                          
 out.println("Error! Please try again.");                          
 }                          
                         
// close connection                          
SQLStatement.close();                          
Conn.close();                          
                         
%>                          
                         
</center>                          
</body>                          
</html>

Of course, we could have combined all the scripts above into one single JSP document - but we'll leave that exercise to you for the moment.
Copyright Melonfire, 2000. All rights reserved.

Cleaning Up

Finally, it's time to do a little routine maintenance. This example demonstrates how to use the DELETE statement to delete a particular entry. Again, the basic principles remain the same, with only the query string changing.

First, the initial list page has to be altered to include a link to delete a specific entry - this is similar to the manner in which the "edit this entry" link was added. Assuming that's taken care of, the script "delete.jsp" should be called with the number of the record to be deleted. So, just as you have the link

"<a href=edit.jsp?id=" + ID + ">edit this entry</a>"
you will now have the additional link

"<a href=delete.jsp?id=" + ID + ">delete this entry</a>" 

Let's take a look at "delete.jsp".

<html>                            
<head>                            
<basefont face="Arial">                            
</head>                            
<body>                            
<center>                            
                           
<%@ page language="java" import="java.sql.*" %>                            
                           
<%                            
// delete.jsp                            
                           
// form data                            
String fid = request.getParameter("id");                            
int id = Integer.parseInt(fid);                            
                           
// database parameters                            
String host="localhost";                            
String user="us867";                            
String pass="jsf84d";                            
String db="db876";                            
String conn;                            
                           
Class.forName("org.gjt.mm.mysql.Driver");                            
                           
// create connection string                            
conn = "jdbc:mysql://" + host + "/" + db + "?user=" + user                            
+ "&password=" + pass;                            
                           
// pass database parameters to JDBC driver                            
Connection Conn = DriverManager.getConnection(conn);                            
                           
// query statement                            
Statement SQLStatement = Conn.createStatement();                            
                           
// generate query                            
String Query = "DELETE FROM abook WHERE id=" + id;                            
                           
// get result code                            
int SQLStatus = SQLStatement.executeUpdate(Query);                            
                           
 if(SQLStatus != 0)                            
 {                            
 out.println("Entry successfully deleted.");                            
 }                            
 else                            
 {                            
 out.println("Error! Please try again.");                            
 }                            
                           
// close connection                            
SQLStatement.close();                            
Conn.close();                            
                           
%>                            
                           
</center>                            
</body>                            
</html>

And that's about all we have for this issue of The JSP Files. Next time, we'll be taking a look at the HTTP session management capabilities available in JSP - so make sure you come back for that one!

Note: All examples in this article have been tested on Linux/i586 with Tomcat 3.2 and JServ 1.1. Examples are illustrative only, and are not meant for a production environment. YMMV!
Copyright Melonfire, 2000. All rights reserved.

The JSP Files - Part 6: State of Grace

A Perfect State

Over the past few weeks, you've learned a great deal about the various control structures and objects available in JSP. You've see how to retrieve information posted in an online form, and connect your JSP document to a database for dynamic content generation.

This week in The JSP Files, we're going to tackle yet another very interesting topic - the problem of maintaining "state" on a Web site. We'll be looking at two common solutions to this problem - cookies and server-based sessions - and using simple examples to illustrate the JSP constructs available to help you identify and track client requests on your Web site.

You'll also learn more than you want to know about what exactly "maintaining state" actually means, the advantages and disadvantages of each of the approaches just described...and, if we're doing our job right, get a laugh or two out of the whole exercise.

Wasted, Dude!

It's one of the things geeks say to each other when they want to impress the young women in earshot: "HTTP is a stateless protocol, and the Internet is a stateless development environment". In simple language, all this means is that the HyperText Transfer Protocol, which is the backbone of the Web, is unable to retain a memory of the identity of each client that connects to a Web site, and therefore treats each request for a Web page as a unique and independent connection, with no relationship whatsoever to the connections that preceded it - very similar to the behaviour of some of today's more adventurous teenagers, who get drunk every night, wake up the next morning with no memory at all of what happened, and go out again in the evening to do the same thing all over again...

Now, so long as you're aimlessly surfing from one site to another, this works without a problem. But what if you've decided to buy a few discs from CDNow.com? In a "stateless environment", it would be very difficult to keep track of all the items you've shortlisted for purchase, as the stateless nature of the HTTP protocol would make it impossible to keep track of the items selected.

Consequently, what is required is a method that makes it possible to "maintain state", something that allows client connections to be tracked and connection-specific data to be maintained. And thus came about "cookies", which allowed Web sites to store client-specific information in a file on the client system, and access the information in the file whenever required. So, in the shopping cart example above, the items selected would be added to the cookie, and would be retrieved and presented to the customer in a consolidated list during the billing process.

Why are they called "cookies"? The PR agency handling the account was obviously asleep at the wheel.

A Few Ground Rules

Since cookies are used to record information about your activities on a particular site, they can only be read by the site that created them. For example, Yahoo and Deja.com store your username in a cookie on your hard drive and use this information to automatically fill in log-in forms the next time you visit their Web sites. It's kinda like going to a chic restaurant, and having the maitre'd call you by name (something which hasn't happened to us of late!)

Before getting into the nitty-gritty of cookie technology, a few ground rules are in order:

  1. A single domain cannot set more than twenty cookies. A single cookie cannot exceed 4 KB in size. The maximum number of cookies that may be set is 300.

  2. The most common method of transmitting a cookie to a client is via the "Set-Cookie" HTTP header.

  3. A cookie usually possesses five types of attributes.

    The first of these is a NAME=VALUE pair, used to store information such as a username, email address or credit-card number. The NAME is a string used to identify the cookie, while the VALUE is the data to be stored in the cookie. For example,

    clarkkent=superman

    The EXPIRES attribute defines the date on which the cookie is automatically removed from the system. The date must be in the format "weekday, dd-mon-yy hh:mm:ss GMT". For example,

    expires="Sun, 31-Dec-2030 17:51:06 GMT"

    Cookies without a specifically defined expiry date remain active for so long as the browser remains open, and are destroyed once the browser is closed. You can delete an existing cookie be setting this attribute to a date in the past.

    The PATH attribute is used to set the top-level directory on the Web server from which cookies can be accessed. In most cases, this is set to

    path=/

    to ensure that the cookie can be accessed by each and every document on the server.

    The DOMAIN attribute is used to specify the domain which the cookie is linked to, and the SECURE attribute indicates that a cookie should only be set if there exists a secure protocol between the browser and the server.

  4. Of all the five attributes, the first is the only one that is not optional.

  5. Every good browser offers users the option to disable cookies. If a user decides to exercise his or her right to do so, your cookies will not be stored, and any attempt to access them will fail. Users who do this are usually career criminals or tax evaders.

Copyright Melonfire, 2000. All rights reserved.

Learning To Write...

Now, there are innumerable ways to go about creating and reading cookies on a client browser - you can use Javascript, you can use PHP, you can use any of the wonderful programming languages out there. However, our concern here is with JSP - so let's take a look at an example which demonstrates how to read and write a cookie.

This is a simple hit counter which creates a cookie the first time the user visits the Web page, and then increments the counter on each subsequent visit.

<%                              
// counter.jsp                              
                             
// declare some variables                              
Cookie cookieCounter = null;                              
                             
// the cookie you want                              
String cookieName = "counter";                              
int cookieFound = 0;                              
                             
// a few more useful variables                              
String tempString;                              
int count=0;                              
                             
// get an array of all cookies available on client                              
Cookie[] cookies = request.getCookies();                              
                             
// iterate through array looking for your cookie                              
for(int i=0; i<cookies.length; i++)                              
{                              
   cookieCounter = cookies[i];                              
   if (cookieName.equals(cookieCounter.getName()))                              
 {                              
 cookieFound = 1;                              
   break;                              
 }                              
                             
}                              
                             
// if found                              
if(cookieFound == 1)                              
{                              
                             
 // get the counter value as string                              
 tempString = cookieCounter.getValue();                              
                             
 // convert it to a number                              
 count = Integer.parseInt(tempString);                              
                             
 // increment it            f;                  
 count++;                              
                             
 // back to a string                              
 tempString = Integer.toString(count);                              
                             
 // store it in the cookie for future use                              
 cookieCounter.setValue(tempString);                              
                             
 // set some other attributes                              
 cookieCounter.setMaxAge(300);                              
 cookieCounter.setPath("/");                              
                             
 // send cookie to client                              
 response.addCookie(cookieCounter);                              
}                              
// if not found                              
else                              
{                              
 // create a new cookie with counter 0                              
 Cookie alpha = null;                              
 alpha = new Cookie("counter", "0");                              
 alpha.setMaxAge(300);                              
 alpha.setPath("/");                              
 response.addCookie(alpha);                              
}                              
%>                              
                             
<html>                              
<head>                              
<basefont face="Arial">                              
</head>                              
                             
<body>                              
                             
<%                              
// display appropriate message                              
if (count > 0)                              
{                              
out.println("You have visited this page " + count + "                              
time(s)! Don't you have anything else to do, you bum?! ");                              
} else { out.println("Welcome, stranger!"); }  %>                              
                             
</body>                              
</html>

Sure, it looks a little complicated - but it won't once we break it down for you.

The first thing you need to know is how to create a cookie on the client - this is accomplished with the following code:

<%                              
Cookie alpha = null;                              
alpha = new Cookie("counter", "0");                              
alpha.setMaxAge(300);                              
alpha.setPath("/");                              
response.addCookie(alpha);                              
%>

The first two lines create a new instance of a Cookie object - "alpha". The cookie variable "counter" is then initialized and set to the string "0". Next, the setMaxAge() and setPath() methods of the Cookie object are used to set the expiry date (in seconds) and the cookie's availability, respectively. Finally, a call to the Response object's addCookie() method takes care of actually transmitting the cookie to the client.

As already mentioned, the only attribute which is not optional is the NAME=VALUE pair. If you'd like your cookie to remain available even after the user closes the browser, you should explicitly set an expiry date; if not, the cookie will be destroyed once the browser is closed.

The Cookie object also comes with a couple of other interesting methods.

  • setValue(someString) - sets the value of the cookie to someString
  • getValue() - returns the current value of the cookie
  • setPath(someURL) - sets the PATH attribute of a cookie to someURL
  • getPath() - returns the current value of the PATH attribute
  • setMaxAge(someSeconds) - sets the EXPIRES attribute of the cookie, in seconds
  • getMaxAge() - returns the current value of the EXPIRES attribute
  • setDomain(someURL) - sets the DOMAIN attribute of the cookie
  • getDomain() - returns the current value of the DOMAIN attribute
  • setSecure(flag) - sets the SECURE attribute of the cookie as either true or false
  • getSecure() - returns the current value of the SECURE attribute

Note that you can only save string values in a cookie with setValue() - which entails a lot of string-to-number-to-string conversions if you actually want to store a number (as in this example).

Copyright Melonfire, 2000. All rights reserved.

...And Read

So that takes care of writing a cookie - but how about reading it? Here's the code.

<%                               
// declare some variables                              
Cookie cookieCounter = null;                              
                             
// the cookie you want                              
String cookieName = "counter";                              
int cookieFound = 0;                              
                             
// a few more useful variables                              
String tempString;                              
int count=0;                              
                             
// get an array of all cookies available on client                              
Cookie[] cookies = request.getCookies();                              
                             
// iterate through array looking for your cookie                              
for(int i=0; i<cookies.length; i++)                              
{                              
   cookieCounter = cookies[i];                              
   if (cookieName.equals(cookieCounter.getName()))                              
 {                              
 cookieFound = 1;                              
   break;                              
 }                              
                             
}                              
%>

Before you can read the cookie, you need to find it on the client's hard drive. Since JSP does not currently allow you to directly locate and identify the cookie by name, you need to iterate through all available cookies until you find the one you're looking for. In the example above, the "for" loop does just that; if and when it finds the cookie, it sets the "cookieFound" variable to 1 and breaks out of the loop.

At this point, the cookie is stored in the Cookie object "cookieCounter". You can then use the getValue() object method to get the current value of the cookie variable, and use it in your script.

                               
<%                              
// if found                              
if(cookieFound == 1)                              
{                              
                             
 // get the counter value as string                              
 tempString = cookieCounter.getValue();                              
                             
 // convert it to a number                              
 count = Integer.parseInt(tempString);                              
                             
 // increment it                              
 count++;                              
                             
 // back to a string                              
 tempString = Integer.toString(count);                              
                             
 // store it in the cookie for future use                              
 cookieCounter.setValue(tempString);                              
                             
 // set some other attributes                              
 cookieCounter.setMaxAge(300);                              
 cookieCounter.setPath("/");                              
                             
 // send cookie to client                              
 response.addCookie(cookieCounter);                              
}                              
%>
What's In A Name?

Once you've understood these two fundamental techniques, the rest of the code should be simple to decipher. If a cookie is found, the counter variable is incremented, and the setValue() method is used to write a new value to the cookie; this counter variable is then displayed on the page. If a cookie is not found, it implies that this is the user's first visit to the page (or a visit made after a previous cookie has expired); a new cookie is set and an appropriate message displayed.

Again, since this example deals with numbers rather than strings, innumerable contortions are required to convert the string value in the cookie to a number, increment it, and then convert it back to a string for storage in the cookie.

Here's another example, this one a simple form. Enter your name and submit the form - a cookie will be created containing the name you entered. When you next visit the page, your name will be automatically filled in for you.

<%                               
// form.jsp                              
                             
// declare some variables                              
Cookie thisCookie = null;                              
                             
// the cookie you want                              
String cookieName = "username";                              
int cookieFound = 0;                              
String username = "";                              
                             
// get an array of all cookies available on client                              
Cookie[] cookies = request.getCookies();                              
                             
// iterate through array looking for your cookie                              
for(int i=0; i<cookies.length; i++)                              
{                              
   thisCookie = cookies[i];                              
   if (cookieName.equals(thisCookie.getName()))                              
 {                              
 cookieFound = 1;                              
   break;                              
 }                              
                             
}                              
                             
// if found                              
if(cookieFound == 1)                              
{                              
// get the counter value                              
username = thisCookie.getValue();                              
}                              
%>                              
                             
                             
<html>                              
<head>                              
<basefont face="Arial">                              
</head>                              
                             
<body>                              
                             
<form action="login.jsp" method="post">                              
<table>                              
                             
<tr>                              
<td>Your name</td>                              
<td><input type=text name=username value="<%=                                
username %>">&nbsp;<input type="Submit" value="Click                                
me"></td> </tr>                              
                             
                             
</table>                              
</form>                              
                             
</body>                              
</html>

This is the initial login form, "form.jsp" - as you can see, it checks for the presence of a cookie, and uses it to fill in the account username if available.

When the form is submitted, "login.jsp" is called to process the data entered into the form; it will also set cookie attributes appropriately.

<%                               
// login.jsp                              
                             
// get values from form                              
String username = request.getParameter("username");                              
                             
// create a new cookie to store the username                              
Cookie alpha = null;                              
alpha = new Cookie("username", username);                              
alpha.setMaxAge(300);                              
alpha.setPath("/");                              
                             
// send it to client                              
response.addCookie(alpha);                              
%>                              
                             
<html>                              
<head>                              
<basefont face="Arial">                              
</head>                              
                             
<body>                              
                             
Get lost, <b><%= username %></b>!                              
                             
</body>                              
</html>

Simple, huh?

Copyright Melonfire, 2000. All rights reserved.

Plan B

The cookie-based approach is quite common; many Web sites use it, because it is flexible, simple, and independent of the server-side language (once the cookie has been saved to the client's hard drive, you can read it using JavaScript, or PHP, or JSP, or ...) The only problem: it is dependent on the cookie being accepted by the client.

And so, another common approach is the use of a "session" to store specific bits of information when a client visits a Web site; this session data is preserved for the duration of the visit, and is usually destroyed on its conclusion. A session can thus be considered a basket of information which contains a host of variable-value pairs; these variable-value pairs exist for the duration of the visit, and can be accessed at any point during it. This approach provides an elegant solution to the "stateless" nature of the protocol, and is used on many of today's largest sites to track and maintain information for personal and commercial transactions.

Every session created is associated with a unique identification string, or "session ID"; this string is sent to the client, while a temporary entry with the same unique identification number is created on the server, either in a flat file or in a database. It now becomes possible to register any number of "session variables" - these are ordinary variables, which can be used to store textual or numeric information, and can be read from, or written to, throughout the session.

The session ID is transmitted to the client either via a cookie, or via the URL GET method. The client, in turn, must reference each request with this session ID, so that the server knows which session each client is associated with and uses the appropriate session variables for each client. In case the client doesn't support cookies and the URL method is rejected or not used, session management capabilities and session variables will not be available to the client, and every request will be treated as though it were coming for the first time.

Sessions are typically left active for as long as the user's browser is open, or for a pre-defined period. Once the user's browser is closed, or the specified time period is exceeded, the session and all variables within it are automatically destroyed.

Session Dissection

Creating a JSP session is much simpler than writing a cookie. To demonstrate this, here's the session equivalent of the cookie-based counter you saw a few pages back.

<html>                                
<head>                                
</head>                                
                               
<body>                                
                               
<%                                
// get the value of the session variable                                
Integer visits = (Integer)session.getValue("counter");                                
                               
// if null                                
if (visits == null)                                
{                                
// set it to 0 and print a welcome message                                
visits = new Integer(0);                                
session.putValue("counter", visits);                                
out.println("Welcome, stranger!");                                
}                                
else                                
{                                
// else increment and write the new value                                
visits = new Integer(visits.intValue() + 1); session.putValue                                
("counter", visits); out.println("You have visited this                                
page " + visits + " time(s)! Don't you have anything                                
else to do, you bum?! "); }  %>                                
                               
</body>                                
</html>

There isn't much you have to do to create a session - simply use the
putValue() method of the Session object to create one or more session variable, and JSP will automatically create a session and register the variables. You can then use the getValue() method to retrieve the values of the session variables automatically.

An important point to be noted here is that it is necessary to typecast the session variable while using getValue() - in the example above, we've specifically stated the type of the variable in parentheses before assigning it to a regular JSP variable. Since JSP allows you to bind objects to the session, you can bind an Integer object and thereby bypass some of the string-to-number conversion routines in the equvalent cookie example.

With this information in mind, the example above becomes much simpler to read. An "if" statement is used to take care of the two possible
alternatives: a first-time visitor (no prior session) or a returning visitor (pre-existing session). Depending on whether or not the "counter" variable exists, appropriate action is taken.

The Session object also comes with a bunch of other interesting methods - here are some of them:

  • getId() - returns a string containing the unique session ID
  • setMaxInactiveInterval(someSeconds) - keeps the session active for someSeconds duration after the last client request
  • invalidate() - destroy the session
  • getAttribute() and setAttribute() - try these if getValue() and putValue() don't work
  • getCreationTime() - returns the time at which this session was created, in seconds, as an offset from midnight January 1 1970

Copyright Melonfire, 2000. All rights reserved.

Access Denied

Here's another simple example which demonstrates some of the methods above, and also illustrates how JSP sessions can be used to protect Web pages with sensitive information.

This example presents a form ("start.html") asking for your name, and takes you to a new page ("login.jsp") once you submit the form. "login.jsp" creates a session to store the name you entered, and offers a link to "rootshell.jsp", which is the sensitive file to be protected.

So long as the session is active, any attempt to access the page "rootshell.jsp" will succeed. On the flip side, if a session is not active, any attempt to access "rootshell.jsp" by bypassing the initial form will fail, and the user will be redirected to "start.html".

This is a relatively primitive example, but serves to demonstrate one of the more common uses of session variables.

All the redirection in this example is accomplished using the Response object (you remember this, don't you?)

<html>                                 
<head>                                
<basefont face="Arial">                                
</head>                                
                               
<body>                                
<!-- start.html -->                                
<form action="login.jsp" method="post">                                
<table>                                
                               
<tr>                                
<td>Your name</td>                                
<td><input type=text name=username>&nbsp;<input                                  
type="Submit" value="Click me"></td> </tr>                                
                               
                               
</table>                                
</form>                                
                               
</body>                                
</html>

Once the form is submitted, "login.jsp" takes over.

<html>                                 
<head>                                
<basefont face="Arial"                                
</head>                                
                               
<body>                                
<%                                
                               
// get the form variable                                
String username = request.getParameter("username");                                
                               
// create a session                                
session.putValue("username", username);                                
                               
// set a timeout period                                
session.setMaxInactiveInterval(300);                                
                               
// display a link to the protected file                                
out.println("Thank you for using this service.");                                  
out.println("Click <a href=rootshell.jsp>here</a> for                                  
root access"); %>                                
                               
</body>                                
</html>

And here's the top-secret page.

<html>                                 
<head>                                
<basefont face="Arial">                                
</head>                                
                               
<body>                                
<%                                
// rootshell.jsp                                
                               
// get the username from the session                                
String username = (String)session.getValue("username");                                
                               
// if null, security breach!                                
if (username == null)                                
{                                
 response.setHeader("Location", "start.html");                                
}                                
else                                
{                                
// display the protected page                                
%>                                
                               
Welcome to your root shell, <b><%= username %></b>!                                
<p>                                
Your session ID is <% out.println( session.getId() ); %>                                
<p>                                
This session will expire in <% out.println(                                
session.getMaxInactiveInterval() ); %> seconds.                                
                               
<%                                
}                                
%>                                
                               
</body>                                
</html>

To test this, first log in and find your way to "rootshell.jsp" - you should have no trouble accessing it. Then close the browser, start it up again, and try to get to "rootshell.jsp" without going through the login process; you should be automatically redirected to the login page.

And that's about it. You should now have a pretty clear idea of how JSP attempts to solve the "stateless protocol" problem, together with some understanding of how to create and use both client-side cookies and server-side sessions. Go practice!

Note: All examples in this article have been tested on Linux/i586 with Tomcat 3.2 and JServ 1.1. Examples are illustrative only, and are not meant for a production environment. YMMV!
Copyright Melonfire, 2000. All rights reserved.

The JSP Files -- Part 7: Bugs, Beans and Banks

Burning Up

No programmer, no matter how good (s)he is, writes bug-free code all the time. And so, most programming languages come with built-in capabilities to catch errors and take remedial action. This action could be something as simple as displaying an error message, or as complex as heating your computer's innards until they burst into flame (just kidding!)

Over the next couple of pages, we're going to look at some of the error-management techniques available in JSP, and also demonstrate some of the JSP directives used to integrate standalone JavaBeans into your JSP scripts.

Bugathon

First, though, a quick lesson in semantics. There's an important distinction to be aware of between "errors" and "exceptions".

JSP "errors" cannot usually be trapped, as they usually involve problems beyond the application developer's control - things like the server running out of memory, missing files or a corrupted filesystem.

The term "exceptions", on the other hand, refers to those errors which can be tracked and controlled. For example, if an argument provided to a function is incorrect, JSP will "throw" an "invalid argument" exception, together with a stack trace or detailed explanation of the problem. Exceptions like these can be "caught" by the application, and appropriately diverted to an exception-handling routine.

Since JSP shares much in common with Java, it won't surprise you to learn that JSP's concept of exceptions is derived almost entirely from Java. In Java, an exception is an instance of an object; in JSP, an implicit Exception object is available to identify and manage exceptions.

Exceptionally Clever

There are two basic components to the process of handling JSP exceptions:

  1. Add a directive to your JSP script identifying the name of the file to call when an exception occurs.

  2. Create an appropriate "error page", optionally using the Exception object to obtain greater detail about the exception.

Let's illustrate this process with a simple example. Here's a JSP script that divides a number by zero - a process guaranteed to make any programming language scream in anguish.

<%                                  
int a = 19;                                  
int b = 0;                                  
int c = a/b;                                  
%>

Here's the output:

Error: 500                                  
Internal Servlet Error:                                  
javax.servlet.ServletException: / by zero                                  
 at org.apache.jasper.runtime.PageContextImpl.handlePage                                  
Exception(PageContextImp                                  
l.java:459)                                  
 at _0002fb_0002ejspb_jsp_2._jspService                                  
(_0002fb_0002ejspb_jsp_2.java:72)                                  
 at org.apache.jasper.runtime.HttpJsp                                  
Base.service(HttpJspBase.java:119)                                  
 at javax.servlet.http.HttpServlet.                                  
service(HttpServlet.java:853)                                  
 at org.apache.jasper.servlet.JspServlet                                  
$JspServletWrapper.service(JspServlet.ja                                  
va:177)                                  
 at org.apache.jasper.servlet.JspServlet.                                  
serviceJspFile(JspServlet.java:318)                                  
 at org.apache.jasper.servlet.JspServlet.                                  
service(JspServlet.java, Compiled                                  
Code)                                  
 at javax.servlet.http.HttpServlet.                                  
service(HttpServlet.java:853)                                  
 at org.apache.tomcat.core.ServletWrapper.                                  
doService(ServletWrapper.java:404)                                  
 at org.apache.tomcat.core.Handler.service                                  
(Handler.java:286)                                  
 at org.apache.tomcat.core.ServletWrapper.                                  
service(ServletWrapper.java:372)                                  
 at org.apache.tomcat.core.ContextManager.                                  
internalService(ContextManager.java:79                                  
7)                                  
 at org.apache.tomcat.core.ContextManager.                                  
service(ContextManager.java:743)                                  
 at org.apache.tomcat.service.connector.                                  
Ajp12ConnectionHandler.processConnection                                  
(Ajp12ConnectionHandler.java:166)                                  
 at org.apache.tomcat.service.TcpWorkerThread.                                  
runIt(PoolTcpEndpoint.java,                                  
Compiled Code)                                  
 at org.apache.tomcat.util.ThreadPool$Control                                  
Runnable.run(ThreadPool.java,                                  
Compiled Code)                                  
 at java.lang.Thread.run(Thread.java, Compiled Code)                                  
Root cause:                                  
java.lang.ArithmeticException: / by zero                                  
 at _0002fb_0002ejspb_jsp_2._jspService                                  
(_0002fb_0002ejspb_jsp_2.java:62)                                  
 at org.apache.jasper.runtime.HttpJspBase.                                  
service(HttpJspBase.java:119)                                  
 at javax.servlet.http.HttpServlet.service                                  
(HttpServlet.java:853)                                  
 at org.apache.jasper.servlet.JspServlet$Jsp                                  
ServletWrapper.service(JspServlet.ja                                  
va:177)                                  
 at org.apache.jasper.servlet.JspServlet.                                  
serviceJspFile(JspServlet.java:318)                                  
 at org.apache.jasper.servlet.JspServlet.                                  
service(JspServlet.java, Compiled                                  
Code)                                  
 at javax.servlet.http.HttpServlet.service                                  
(HttpServlet.java:853)                                  
 at org.apache.tomcat.core.ServletWrapper.                                  
doService(ServletWrapper.java:404)                                  
 at org.apache.tomcat.core.Handler.service                                  
(Handler.java:286)                             &nbsfp;    
 at org.apache.tomcat.core.ServletWrapper.                                  
service(ServletWrapper.java:372)                                  
 at org.apache.tomcat.core.ContextManager.                                  
internalService(ContextManager.java:79                                  
7)                                  
 at org.apache.tomcat.core.ContextManager.                                  
service(ContextManager.java:743)                                  
 at org.apache.tomcat.service.connector.                                  
Ajp12ConnectionHandler.processConnection                                  
(Ajp12ConnectionHandler.java:166)                                  
 at org.apache.tomcat.service.TcpWorkerThread.                                  
runIt(PoolTcpEndpoint.java,                                  
Compiled Code)                                  
 at org.apache.tomcat.util.ThreadPool$Control                                  
Runnable.run(ThreadPool.java,                                  
Compiled Code)                                  
 at java.lang.Thread.run(Thread.java, Compiled Code)

Ugly, huh?

In order to have this exception handled by JSP, so that the user never has to see something so ugly, you need to simply add a

<%@ page errorPage="error.jsp" %>

to the script, so that it looks like this:

<%@ page errorPage="error.jsp" %>                                  
<%                                  
int a = 19;                                  
int b = 0;                                  
int c = a/b;                                  
%>

An exception thrown by the script will now be caught by JSP, and automatically routed to "error.jsp". Let's look at that next.
Copyright Melonfire, 2000. All rights reserved.

Bad News

The exception-handling routine "error.jsp" can be as simple or complex as you want to make it. If you want something friendly and easy to understand, you could use the following:

<html>                                   
<head>                                  
<basefont face="Arial">                                  
</head>                                  
                                 
<body bgcolor="white">                                  
<h2>Oops!</h2>                                  
Something bad just happened.                                    
Click here to go back to the main page. </body>                                  
                                 
</html>

Now, if you run the example above again, JSP should automatically divert you to this page instead of grossing you out with long and icky error messages.

The script above simply notifies the user that an error has occurred; it says nothing about the type of error, or the reasons for its occurrence. If you'd like to display this as well, you need to use the built-in Exception object to obtain information about the exception. The next example uses a modified "error.jsp" to illustrate this:

<%@ page isErrorPage="true" %>                                   
<html>                                  
<head>                                  
<basefont face="Arial">                                  
</head>                                  
                                 
<body bgcolor="white">                                  
<h2>Oops!</h2>                                  
Something bad just happened:                                  
<br>                                  
<b><i><%= exception.getMessage() %></i></b>                                  
                                 
</body>                                  
</html>

And this time, the output will be a little more helpful.

Oops!                                   
Something bad just happened:                                  
/ by zero

Pay special attention to the first line of the script; the directive

<%@ page isErrorPage="true" %>

tells JSP that this is an error page, and initializes an instance of the Exception object for use.

The Exception object comes with a couple of useful methods - the
exception.getMessage() method is used to obtain a description of the error, while the exception.printStackTrace() method is used to print debugging information.

You Throw(), I'll Catch

It's also possible to use the Java "throw" construct to artificially induce an exception in your JSP script. This comes in handy, for example, when validating form field data - if the values entered are not in the expected format, you can throw an exception (with an informative error message) and re-direct the user to an error page.

Here's an example of how this can be used. This is a simple form which asks you to enter a number

<html>                                   
<head>                                  
<basefont face="Arial">                                  
</head>                                  
                                 
<body>                                  
                                 
<form action="number.jsp">                                  
Enter a number between 1 and 3                                    
<input type=text name=number size=1> </form>                                  
                                 
</body>                                  
</html>

and this is the server-side JSP script which checks it for errors, and throws an exception if certain conditions are not met.

<html>                                   
<head>                                  
<basefont face="Arial">                                  
</head>                                  
                                 
<body>                                  
<%@ page errorPage="error.jsp" %>                                  
<%                                  
String temp = request.getParameter("number");                                  
                                 
int number = Integer.parseInt(temp);                                  
                                 
if (number != 2)                                  
 {                                  
 throw new Exception ("How dumb can you get?!") ;                                  
 }                                  
else                                  
 {                                  
 out.println("Hmmm...maybe you're not as dumb as you look!");                                  
 }                                  
%>                                  
                                 
</body>                                  
</html>

Next up, a brief look at JavaBeans and how they integrate with the JSP environment.
Copyright Melonfire, 2000. All rights reserved.

Bean Bag

One of the most compelling things about JSP, from a development point of view, is that it allows for the easy integration of existing JavaBeans into JSP scripts (for those of you not in the loop, JavaBeans is object-oriented technology which allows developers to build reusable Java components or applications). The advantages of this are obvious: an organization which has already made an investment in JavaBeans technology can leverage off it to quickly reuse existing code modules, at minimal time and cost.

We're not going to get into the nitty-gritty of building a JavaBean here - there are innumerable tutorials out there on the topic, including a good one from Sun Microsystems. Instead, we're simply going to touch briefly on the JSP constructs which allow you to import a Bean into your JSP script, set Bean properties and access Bean methods.

JavaBeans are brought into a JSP script by means of the <jsp:useBean> action, which creates an instance of the Bean and identifies the scope of its activities.

The following code snippet creates an instance of the Bean "iceCream", identifies it with the unique ID "vanilla" and defines its scope to be limited to the "page".

<jsp:useBean id="vanilla" scope="page" class="iceCream">                                     
</jsp:useBean>

The "scope" attribute above defines the extent of the Bean's influence. For example, "scope=page" implies that the instance will remain active for the current page, while "scope=session" indicates that the instance will remain available throughout the session.

Taking It To The Bank

Closely related to <jsp:useBean> is <jsp:setProperty>, typically used to set Bean properties; these properties may be set explicitly, or on the basis of parameters available in the Request object (you remember this, don't you?)

The following code snippet uses the <jsp:setProperty> action to assign the value "7683" to the Bean property "accountBalance". Note that the <jsp:setProperty> action references an instance of a previously-defined Bean, named "account"

<jsp:useBean id="account" scope="page" class="Bank">                                    
<jsp:setProperty name="account" property="accountBalance"                                    
value="7683" /> </jsp:useBean>

If you'd like to set instance properties on the basis of data in the Request object - say, form values - you could use

<jsp:setProperty name="account" property="*" />

and JSP would automatically iterate through the Request object, match parameter names with available Bean properties, and assign values appropriately.

Turning Up The Heat

In order to illustrate how this works, we've written a simple Bean which accepts temperature values and converts them between Celsius and Fahrenheit scales. /#l#http://www.webmasterbase.com/examples/jspfiles/temperature.zip/#lt#/Here it is./#el#/

And here's a page which uses it:

<html>                                    
<head>                                    
<basefont face="Arial">                                    
</head>                                    
<body>                                    
<!-- initialize the Bean, set some defaults -->                                    
                                   
<jsp:useBean id="c" scope="page" class="Temperature">                                    
<jsp:setProperty name="c" property="celsius" value="10" />                                    
</jsp:useBean>                                    
                                   
<%                                    
// get the current temperature                                    
out.println("Temperature in Celsius is " + c.getCelsius() + "<p>");                                    
                                   
// turn up the heat                                    
c.setCelsius(36.8);                                    
                                   
// get the current temperature                                    
out.println("Temperature in Celsius is now " + c.getCelsius() + "<p>");                                    
                                   
// convert the temperature to Fahrenheit                                    
out.println(c.getCelsius() + " Celsius is " +                                    
c.convertCelsiusToFahrenheit(c.getCelsius()) + " Fahrenheit<p>");                                    
                                   
// ...and back again                                    
out.println(c.getFahrenheit() + " Fahrenheit is " +                                    
c.convertFahrenheitToCelsius(c.getFahrenheit()) + " Celsius<p>"); %>                                    
                                   
</body>                                    
</html>

And here's the output:

Temperature in Celsius is 10.0                                    
Temperature in Celsius is now 36.8                                    
36.8 Celsius is 98.24 Fahrenheit                                    
98.24 Fahrenheit is 36.8 Celsius

And that's about it for the moment. In the next - and final - article in this series, we'll be exploring JSP's tag libraries, which allow Web designers to add powerful funtionality to their Web pages without knowing JSP. Make sure you make it out here for that one!

Note: All examples in this article have been tested on Linux/i586 with Tomcat 3.2 and JServ 1.1. Examples are illustrative only, and are not meant for a production environment. YMMV!
Copyright Melonfire, 2000. All rights reserved.

The JSP Files -- Part 8: Tagged and Bagged

The Beginning Of The End

Over the past few weeks, we've taken you on a guided tour of the intricacies of JSP, beginning with basics like conditional statements and loops, and quickly moving on to more complex things like form processing, session management, and error handling.

But all good things must come to an end - and so, in this final episode of The JSP Files, we'll be briefly touching on a few other facets of this powerful server-side scripting language.

Playing Tag

One of the most exciting features about JSP is the ability to build and use custom "tag libraries" in your JSP applications. A "tag library" is a reusable block of JSP code, typically written to replace Java code with easy-to-read-and-understand tags (similar in appearance to HTML markup). Once written, these tag libraries can be used over and over again, thereby bringing a new element of reusability to the language.

In addition to reusability, tag libraries also offer substantial advantages from the maintenance point of view. Since tag libraries are largely defined using XML-type markup, they make it possible to separate application presentation from application logic - which, in turn, implies that designers and developers working on Web applications can use a tag without worrying about how and why it works. This separation between program code and final layout is something most designers would kill to have - and it's now available to almost anyone who knows how to string together Java and JSP code.

Another advantage of the separation discussed above, is the ease of use when it comes to adding new features to a tag library, or making changes to existing features. Since a tag library is portable and reusable, a change made to it will immediately reflect in all JSP pages using that tag library. Similarly, a new feature added to the tag library becomes immediately available to all pages carrying that library.

Tag libraries are slowly catching on, with many JSP developers releasing custom tag libraries for free online. These libraries are typically designed for specific tasks - database connectivity, string manipulation and the like - and they provide a rich vein for JSP developers to mine for their own projects. After all, why waste time writing Java code to send email messages when you can find a feature-rich, properly-tested and free tag library to do the same thing online?

Looking Inside

A tag library is made up of several components. First comes the tag class itself, written in Java - this contains all the behind-the-scenes code which makes the tag function. This class will be referenced in the tag library descriptor, and constitutes the meat of the sandwich we're building.

Next, you need a "tag library descriptor", an XML file usually identified with the .TLD file extension. This TLD contains information on different aspects of the tag library: the name of the tag, and of the Java class associated with it, a short description of functionality, and optional attributes and body content.

Both these components are usually packaged into a JAR file for easy distribution.

Now, we're not going to get into the nitty-gritty of writing a tag library here - there are already a whole bunch of tutorials which discuss this in detail, and links to some are included at the end of this article. What we will do, however, is illustrate how a tag library can be incorporated into your JSP document, and how it interacts with the rest of your script.

In order to illustrate this, we'll be using the Jakarta Project's DATETIME tag library, designed to manipulate date- and time-stamps. You can download a copy of this library here, and you can find a number of other freeware tag libraries at this site, one of the larger repositories on the Web.

Once you've downloaded a copy of the library, you need to tell Tomcat about it before you can begin using it. The first step here is to decide the context within which you plan to use the library - for purposes of this example, we will assume the context is "/test/". Next, copy the TLD file from the distribution into the context's "web-inf/" directory, and the main JAR file into the context's "web-inf/lib/" directory.

The last step here is to open up the "web.xml" file which resides in the "web-inf/" directory, and alter it to reflect the new tag library - this is accomplished via the <taglib> directive.

<taglib> <taglib-uri>http://jakarta.apache.org/taglibs/                                     
datetime-1.0</taglib-uri>                                    
<taglib-location>/WEB-INF/datetime.tld</taglib-location>                                    
</taglib>

This element specifies the location of the tag library, as well as a unique URI used to reference it.
Copyright Melonfire, 2000. All rights reserved.

Meeting Popeye

At this point, you can begin using the new tag library in your JSP pages. First, declare it with the "taglib" directive - this directive must appear before any custom tags in the page.

<%@ taglib uri="http://jakarta.apache.org/taglibs/datetime-1.0"                                      
prefix="popeye" %>

The URI is the unique identifier for the tag library, and must match the URI specified in "web.xml", while the prefix appears in every call to a custom tag, and is used to distinguish between tags from different libraries in the same page.

Once the library has been declared, you can begin using custom tags in your JSP scripts. Consider the following example, which uses a custom tag from the DATETIME library to calculate the number of seconds elapsed since January 1 1970.

<html>                                      
<head>                                      
</head>                                      
<body>                                      
                                     
<%@ taglib uri="http://jakarta.apache.org/taglibs/datetime-1.0"                                      
prefix="popeye" %>                                      
                                     
The number of milliseconds since January 1, 1970 is <popeye:                                      
currenttime/>                                      
                                     
</body>                                      
</html>

And the output is:

The number of milliseconds since January 1, 1970 is 987165837280

What if you simply want the current date and time? By combining the <currenttime> tag with the <format> tag, the DATETIME library makes it a snap!

<html>                                      
<head>                                      
</head>                                      
<body>                                      
                                     
<%@ taglib uri="http://jakarta.apache.org/taglibs/datetime-1.0"                                      
prefix="popeye" %>                                      
                                     
The current date and time is                                      
<popeye:format pattern="hh:mm EEE MMMM dd yyyy"> <popeye:                                      
currenttime/> </popeye:format>                                      
                                     
</body>                                      
</html>

In case you're wondering, the EEEs and MMMs you see there are formatting codes, used to define the format in which the date and time is to be printed. Here's the output:

The current date and time is  06:22 Fri April 13 2001

The example above also illustrates how some tags can be nested within one another - this can make for powerful combinations, and is one of the clever things about this architecture.

How about generating a list of days or months? The DATETIME library's got you covered with its <weekdays> and <months> tags...

<html>                                      
<head>                                      
</head>                                      
<body>                                      
                                     
<%@ taglib uri="http://jakarta.apache.org/taglibs/datetime-1.0"                                      
prefix="popeye" %>                                      
                                     
<form>                                      
Select a day                                      
<select name="weekday">                                      
<popeye:weekdays id="day">                                      
<option value="<jsp:getProperty name="day" property="dayOfWeek"/>                                      
"> <jsp:getProperty name="day" property="weekday"/> </popeye:weekdays>                                      
</select> </form>                                      
                                     
</body>                                      
</html>

The DATETIME library comes with a whole bunch of other useful tags too - take a look at the documentation to see the various other features available.
Copyright Melonfire, 2000. All rights reserved.

You've Got Mail!

Now, our original thesis was that tag libraries would allow Web designers with no knowledge of JSP to implement complex functionality on a Web page. While the examples you've just seen were simple and illustrative, they haven't really proved that thesis - after all, it's reasonable to suppose that any competent Web designer would know how to manipulate date and time values via JavaScript and wouldn't really require a tag library for the purpose. So let's try something most client-side specialists wouldn't know how to handle - email delivery.

Typically, the process of generating email from a Web site is handled via a server-side script - Perl gurus open a pipe to sendmail, while PHP programmers reach for the mail() function. This implies a foreknowledge of either PHP or Perl - not something a novice Web designer may be expected to possess. What solution does JSP offer this poor soul?

The Jakarta MAILER library.

Using a couple of simple tags from this library, any Web developer can quickly add mail-processing capability to a Web page - in fact, the process is simpler than the equivalent techniques in Perl and PHP. Take a look.

<html>                                       
<head>                                      
</head>                                      
<body>                                      
                                     
<%@ taglib uri="jspmailer" prefix="jmail" %>                                      
                                     
<jmail:mail server="mail.server.com" to="recipient@server.com"                                        
from="sender@server.com" subject="This stuff is pretty cool!">                                        
<jmail:message> OK, you've convinced me - this tag library thing                                        
is awesome! Where do I sign up? </jmail:message> <jmail:send/>                                        
</jmail:mail>                                      
                                     
</body>                                      
</html>

By simplifying otherwise complex code, custom tag libraries like the one above can promote both efficiency and harmony in group development projects, by allowing the developers to concentrate on building better tools (libraries) and the designers to concentrate on presentation (rather than code). As JSP evolves, you can expect tag libraries to grow in importance - even now, they are by far one of the most compelling reasons to choose this server-side language over others.

Applet Antics

You've already seen how JSP "actions" work - in the last article, for example, we demonstrated the <jsp:useBean> and <jsp:setProperty> actions in conjunction with JavaBeans, while <jsp:include> was illustrated in the very first article in this series. However, we missed out on a couple of important ones - and so, we'd like to introduce you to <jsp:plugin>, used to incorporate Java applets into a Web page.

The <jsp:plugin> directive takes care of generating all the HTML code necessary to embed and activate a Java applet. Consider the following
example:

<html>                                       
<head>                                      
</head>                                      
<body>                                      
                                     
<jsp:plugin type="applet" code="NewsTicker.class"                                      
name="newsticker" height="100" width="100">                                      
                                     
<jsp:params>                                      
<jsp:param name="x" value="10"/>                                      
<jsp:param name="y" value="25"/>                                      
<jsp:param name="cx" value="90"/>                                      
<jsp:param name="cy" value="114"/>                                      
<jsp:param name="bgcolor" value="102,102,153"/>                                      
<jsp:param name="textcolor" value="0,0,0"/>                                      
<jsp:param name="hilitecolor" value="255,0,0"/>                                      
</jsp:params>                                      
                                     
<jsp:fallback>Oops! Something bad happened and I can't display this                                      
applet</jsp:fallback>                                      
                                     
</jsp:plugin>                                      
                                     
</body>                                      
</html>

The code above sets up the applet contained in "NewsTicker.class", and passes it a bunch of name-value pairs of parameters. The <jsp:param> tag is used to pass these parameters to the applet, while the <jsp:fallback> directive contains error text, in the event that the applet cannot be found or displayed.

When JSP compiles and renders the page, the code above is automatically converted to its HTML equivalent.

<html>                                       
<head>                                      
</head>                                      
<body>                                      
                                     
<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"                                        
width="100" height="100" codebase="http://java.sun.com/products/                                      
plugin/1.2.2/jinstall-1_2_2-win.cab#V                                      
ersion=1,2,2,0">                                      
<PARAM name="java_code" value="NewsTicker.class">                                      
<PARAM name="type" value="application/x-java-applet;">                                      
<PARAM name="cy" value="114">                                      
<PARAM name="cx" value="90">                                      
<PARAM name="bgcolor" value="102,102,153">                                      
<PARAM name="hilitecolor" value="255,0,0">                                      
<PARAM name="y" value="25">                                      
<PARAM name="x" value="10">                                      
<PARAM name="textcolor" value="0,0,0">                                      
<COMMENT>                                      
<EMBED type="application/x-java-applet;"  width="100"  height="100"                                      
pluginspage="http://java.sun.com/products/plugin/"                                      
java_code="NewsTicker.class"                                      
cy=114                                      
cx=90                                      
bgcolor=102,102,153                                      
hilitecolor=255,0,0                                      
y=25                                      
x=10                                      
textcolor=0,0,0                                      
>                                      
<NOEMBED>                                      
</COMMENT>                                      
Oops! Something bad happened and I can't display this applet                                        
</NOEMBED></EMBED> </OBJECT>                                      
                                     
</body>                                      
</html>

And finally, the <jsp:forward> directive is used to automatically redirect a client request to another document. The following code would automatically redirect the client to the script "endzone.jsp".

<jsp:forward page="endzone.jsp" />

Just as in the previous example, additional parameters can be passed to the new script via <jsp:param>. For example,

<jsp:forward page="endzone.jsp">                                       
 <jsp:param name="user" value="joe" />                                      
 <jsp:param name="uid" value="653" />                                      
 <jsp:param name="gid" value="1220" />                                      
</jsp:forward>

And with that, it's about time to call this a wrap. We hope you enjoyed it, and that it served as a good starting point for your entry into the world of JSP.

If you're interested in learning more about the topics discussed in this series, take a look at our JSP section on Melonfire Trog, Sun Microsystems' JSP pages, Java documentation and references, or this tutorial on tag libraries. If, on the other hand, you have questions, comments, or large sums of money for us, drop us a line - we'd love to hear from you!

Until next time... stay healthy!

Note: All examples in this article have been tested on Linux/i586 with Tomcat 3.2 and JServ 1.1. Examples are illustrative only, and are not meant for a production environment. YMMV!
Copyright Melonfire, 2000. All rights reserved.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments

Comments on this post are closed.