Chapter 2
IN THIS CHAPTER
Seeing how servlets work in the MVC model.
Learning about the life cycle of a JSP page
Trying out expressions and JSTL tags
Doing more with the Request object
Looking at a complete, albeit simple, JSP application
In Book 7, Chapter 1, you discover how to create servlets that write HTML data directly to a page by using the PrintWriter
object accessed through response.out
. Although this technique works, it is far from the ideal way to develop web applications. Any sensible web application design separates the business logic (the Java code) from the presentation (the HTML). Generating HTML directly from a Java servlet was fine for introducing how servlets work, but it isn't a viable way to write actual web applications.
That’s where JavaServer Pages (a technology usually called JSP for short) comes in. A JavaServer Page is an HTML file that has Java servlet code embedded in it in special tags. When you run a JSP, all the HTML is automatically sent as part of the response, along with any HTML that’s created by the Java code you embed in the JSP file. As a result, JSP spares you the chore of writing all those out.println
statements.
Note: To work with JavaServer Pages, you must first set up a working Tomcat environment. For information on how to do that, please refer to Book 7, Chapter 1.
A JSP is an HTML document that’s saved in a file with the extension .jsp
instead of .htm
or .html
. In many cases, .jsp
files are stored in the application's home folder. But if your application has a lot of .jsp
files, you can store them in subfolders. When you run the jar
command to create a .war
file to deploy to Tomcat, the .jsp
files will be included in the .war
file so they wind up in the right place on the server. (For more information, refer to Chapter 1 of this minibook.)
A .jsp
file consists of a mixture of HTML elements and special tags. Here's an incredibly simple example — not particularly useful, but it demonstrates how tags are embedded with HTML:
<html>
<body>
<p>Two plus two equals ${2 + 2}.</p>
</body>
</html>
Here, the embedded tag is ${2 + 2}
. This tag is called an expression tag. When the page is rendered, the expression in the tag is evaluated and the result is rendered to the page. So, this JSP page displays the following text on the browser:
Two plus two equals 4.
Let’s take a closer look at the life cycle of a simple JSP page such as the preceding one. Suppose the JSP page is named Four.jsp
and it lives in a web application named misc
on your local computer, where Tomcat is installed. You could request the JSP page by entering the following in a browser address bar: http://localhost:8080/misc/Four.jsp. Or, you could click a link that references this URL.
Either way, the server receives a GET
request for the Four.jsp
file.
Assuming this is the first time Four.jsp
is requested, its HTML and tags are parsed and converted to a Java servlet, saved in a source file named Four_jsp.java
and compiled to a class named Four_jsp.class
. These files are saved within a folder called work
on the Tomcat server.
The Four_jsp
servlet is then invoked. It uses an output stream to write HTML code for the page in much the same manner as the programs in Chapter 1 of this minibook wrote HTML using PrintWriter.out
to write HTML. In fact, if you peek inside the Four_jsp.java
file, you'll find these lines:
out.write("<html>\r\n");
out.write(" <body>\r\n");
out.write(" <p>Two plus two equals ");
out.write((java.lang.String)
org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${2 + 2}",
java.lang.String.class,
(javax.servlet.jsp.PageContext)_jspx_page_context, null));
out.write("</p> \r\n");
out.write(" </body>\r\n");
out.write("</html>");
With the exception of the line that calls the proprietaryEvaluate
method, these lines simply regurgitate the HTML in the Four.jsp
file. The proprietaryEvaluate
method call handles the ${2 + 2}
expression.
Fortunately, you don't have to worry about how the servlet created for a JSP page works — you can simply trust that it does. The point is that every JSP page becomes a servlet, and it’s the servlet that actually responds to the request for the JSP page.
Most JSP applications involve not only GET
requests but POST
or PUT
requests as well. A typical JSP presents a form into which the user enters data. When the user submits the form, the data is sent to the server as a POST
request. The POST
is handled by a servlet often called a controller. (The controller servlet is distinct from the servlet automatically generated for the .jsp
page; you have to code the controller servlet yourself!)
The controller servlet receives the data entered by the user, validates it, and acts on it, often by retrieving or updating database data. The controller typically adds data to the JSP page by appending it to the request in the form of request attributes, which usually wind up in the request message body as JSON data. Then the controller forwards the request to the JSP page.
When the JSP page receives the request, it renders the response in the form of HTML, which is then sent to the user to be displayed on the browser.
This basic servlet architecture is consistent with the popular Model-View-Controller (MVC) paradigm used for modern web applications. In an MVC application, application components are segregated into three distinct layers:
I explain how to create controller servlets later in this chapter. But first, let's look more closely at the types of tags you can use in a JSP page.
You can include many different types of tags in JSP pages. In this section, I show you how you can incorporate expressions into your JSP pages using Unified Expression Language (UEL) tags and JSP Standard Tag Library (JSTL) tags.
One of the most common needs in JSP pages is to evaluate expressions. The syntax for evaluating expressions is governed by a standard called UEL. Here’s the basic form of a UEL expression:
${ expression }
Wherever you place a UEL expression in your JSP page, the expression will be evaluated and the expression itself will be replaced by the result of the evaluation.
Here’s the example that I present earlier in this chapter:
<p>Two plus two equals ${2 + 2}.</p> <!--<ce:anchor id="pp:778 np:779" role="page-break"/>-->
Here, the UEL tag is ${2 + 2}
and the expression within the tag is 2 + 2
. When the expression is evaluated, the result (4
) replaces the entire tag. So, the text rendered into the page is:
Two plus two equals 4.
A UEL expression can contain standard mathematical, relational, and logical operators, plus a few others, as shown in Table 2-1.
TABLE 2-1 UEL Expression Operators
Operator |
Explanation |
Arithmetic Operators |
|
|
Addition |
|
Subtraction (or negation when used as a unary operator) |
|
Multiplication |
|
Division |
|
Modulus division |
Relational Operators |
|
|
Equal to |
|
Not equal to |
|
Greater than |
|
Less than |
|
Greater than or equal to |
|
Less than or equal to |
Logical Operators |
|
|
And |
|
Or |
|
Not |
Conditional Operator |
|
|
Evaluate A, then evaluate either B or C depending on result of A |
Empty Operator |
|
|
Prefix operator that determines if a value is |
UEL expressions are also used to access objects that are available via request attributes. In your Java servlet, you can create a request attribute by calling the Request
object's setAttribute
method. Then, the JSP page can retrieve the attribute using a UEL expression. I explain how to do this in the section “Working with Attributes,” later in this chapter.
JSTL tags are designed to simplify the task of crafting the user interface in a JSP page. With JST tags, you can easily provide for data formatting, as well as repeating or conditional content.
JSTL is based on XML, so JSTL tags fit naturally in your HTML code. JSTL tags elements are enclosed by <
and >
symbols, have an element name, and can optionally have attributes and content. A start tag marks the beginning of a JSTL tag, and the end is marked by an end tag that uses the same element name preceded by a slash. If a JSTL tag has no content between the start and end elements, you can combine the start and end tags by ending the tag with a slash. For example:
<c:out value = "Two plus two equals ${2+2}."/>
This example renders the text Two plus two equals 4
.
Here's an example of a JSTL tag that has separate start and end tags with content in between:
<c:forEach begin="1" end="10">
<p>All work and no play makes Jack a dull boy.</p>
</c:forEach>
This example renders ten consecutive paragraphs, all saying All work and no play makes Jack a dull boy.
JSTL tags come in five flavors:
In the following sections, I show you some of the more common tags in the core and formatting groups.
Before you can start using JSTL tags in your JSP pages, you need to download the .jar
files that implement the tags. You can download the necessary .jar
files from the Apache Tomcat website at http://tomcat.apache.org/download-taglibs.cgi
. You should download the following two files:
taglibs-standard-impl-1.2.5.jar
taglibs-standard-spec-1.2.5.jar
Create a folder named lib
in your application's WEB-INF
folder. Then copy the taglib .jar
files to the new lib
folder.
If you have the necessary permissions, you can also deploy these files directly to Tomcat so they'll be available to any application. Just copy the files to web-apps\ROOT\web\WEB-INF\lib
.
Before you can use JSTL tags in a JSP page, you must add a <taglib>
directive to the JSP page to identify the tag category you want to use (core, formatting, functions, and so on). The <taglib>
directive sets a prefix that appears before tags for the specific category. For example, you can specify that all core tags begin with c:
.
Table 2-2 shows the prefix and <taglib>
directive you should use for each JSTL tag category. Although you can specify any prefix you want, you should stick to the standard prefixes listed in the table.
Here's an example of a simple .jsp
with <taglib>
directives for the core and functions categories:
<html>
<%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix = "fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>
<body>
<p>This page contains two taglib directives</p>
</body>
</html>
TABLE 2-2 JSTL Tag Prefixes and <taglib> Directives
Category |
Prefix |
<taglib> Directive |
Core |
|
|
Formatting |
|
|
Functions |
|
|
SQL |
|
|
XML |
|
|
As you can see, the taglib directives appear near the top of the file, immediately following the <html>
start tag.
The core tags provide basic functionality, such as displaying the results of expressions, making choices, and processing loops, with a few other goodies thrown in for good measure. Table 2-3 shows all 14 of the available core tags. I look more closely at the most important ones in the sections that follow.
TABLE 2-3 Core Tags
Tag |
What It Does |
|
Catches any exceptions that might be thrown within the body of the tag. |
|
A |
|
A conditional tag. The body of the tag is evaluated if the condition is true. |
|
Gets a resource based on a URL and renders its contents to a page or to a variable or a reader. |
|
Sets up a |
|
Iterates over a string of delimited tokens. |
|
Evaluates an expression and renders it to the page. It can optionally encode XML tags to guard against script injection attacks. |
|
Used in the body of a |
|
Adds a parameter to a URL created by the |
|
Redirects to a URL. |
|
Removes a variable created by a |
|
Creates a variable and assigns it a value. |
|
Creates a URL to which parameters can be added using the |
|
Used in the body of a |
One of the most commonly used core tags is out
. This tag evaluates an expression and renders it to the page. The expression is supplied via the value attribute, like this:
<c:out value="All work and no play makes Jack a dull boy."/>
You can include a UEL expression tag in the value. For example:
<c:out value = "Two plus two equals ${2+2}."/>
And you can include the attribute excapeXML
to force the special XML characters <
, >
, &
, '
, and "
to be rendered by escape sequences such as <
or &
. This special encoding can help prevent a common type of software attack called cross-site scripting, in which an attacker attempts to inject code into the value of a form field.
You can create variables that you can use in your JSP page by using the c:set
tag. You specify the name of the variable using the var
attribute and the value by using the value
attribute.
When you're finished with a variable, you can destroy it by using the c:remove
tag.
Here’s an example that creates a variable named two
, gives it the value 2
, uses it in expressions in the value attribute of a c:out
tag, and then removes the variable:
<c:set var="two" value="2"/>
<c:out value="${two} + ${two} = ${two + two}"/>
<c:remove var="two"/>
You can create the equivalent of an if
statement by using the c:if
tag. Here's an example:
<c:set var="commissionrate" value="0.02"/>
<c:set var="salestotal" value="9886.00"/>
<c:if test="${salestotal >= 10000.00}">
<c:set var="commissionrate" value="0.05"/>
<p><c:out value="Your commission rate is ${commissionrate}."/></p>
</c:if>
Here, a variable named commissionrate
is created and given an initial value of 0.02
. Then, a c:if
tag is used to see if a variable named salestotal
is greater than $10,000. If it is, commissionrate
is increased to 0.05
and the lucky salesperson is told about the increase. Alas, in this case, there will be no such happy news, as salestotal
has been set to $9,886
— just below the threshold. Better luck next month!
Note that the c:if
tag does not have an else
clause. You can simulate that by following a c:if
with another c:if
that tests for the opposite condition, like this:
<c:set var="commissionrate"/>
<c:set var="salestotal" value="12955.00"/>
<p><c:out value="Your sales total is ${salestotal}."/></>
<c:if test="${salestotal >= 10000.00}">
<c:set var="commissionrate" value="0.05"/>
</c:if>
<c:if test="${salestotal < 10000.00}">
<c:set var="commissionrate" value="0.02"/>
</c:if>`
<p><c:out value="Your commission rate is ${commissionrate}."/></p>
In this example, the commissionrate
variable is not given an initial value; instead, it is assigned either 0.02
or 0.05
depending on the value of salestotal
. This time, the lucky salesperson gets the commission bump because salestotal
is set to $12,995
.
This same logic could be implemented with c:choice
as follows:
<c:choose>
<c:when test="${salestotal < 10000.00}">
<c:set var="commissionrate" value="0.02"/>
</c:when>
<c:when test="${salestotal >= 10000.00}">
<c:set var="commissionrate" value="0.05"/>
</c:when>
</c:choose>
Here, the first c:when
covers the case in which the sales total is less than $10,000 and the second c:when
covers the case where the sales total is greater than or equal to $10,000.
Another way to do this would be with c:otherwise
, like this:
<c:choose>
<c:when test="${salestotal >= 10000.00}">
<c:set var="commissionrate" value="0.05"/>
</c:when>
<c:otherwise>
<c:set var="commissionrate" value="0.02"/>
</c:otherwise>
</c:choose>
The last core tag I'll cover in this section is c:forEach
, which lets you create simple iterations. You can mimic a standard for statement by setting the begin
and end
attributes, like this:
<c:forEach var="i" begin="1" end="10">
<p><c:out value="${i}"/></p>
</c:forEach>
This loop simply counts from 1 to 10, displaying each number on a separate line.
You can use the step
attribute to specify a step other than 1, but unfortunately you can't use a negative value for step. So, there’s no way to count backward, at least not without some clever programming. Here’s one way to do it:
<c:forEach var="i" begin="0" end="9">
<c:set var="j" value="${10-i}"/>
<p><c:out value="${j}"/></p>
</c:forEach>
Notice here that the forEach
actually counts from 0 this time instead of from 1. That’s because the subtraction is done before the value is printed, so if you started from 1 you’d end up counting backward from 9.
You can also use c:forEach
to iterate over a list. I show you an example of that in the section “The ListMovies Application Meets JSP,” later in this chapter.
The formatting tags let you format values as numbers and dates. You can specify detailed formats for numbers, controlling such things as the number of decimal digits to display and whether to use commas or currency symbols or format numbers as percentages. You can also format dates using a variety of common formats.
In this section, I focus on using the fmt:formatNumber
command to format numeric values. Table 2-4 lists the attributes of this tag.
Here's an example that formats the variable salestotal
as currency and commissionrate
as a percentage.
<fmt:formatNumber var="totalfmt" value="${salestotal}" type="currency"/>
<fmt:formatNumber var="commfmt" value="${commissionrate}" type="percent"/>
In both cases, the formatted values are returned in string variables, which can later be included on the page.
TABLE 2-4 fmt:formatNumber Attributes
Attribute |
What It Does |
|
The value to be formatted. |
|
The variable used to store the result. If omitted, the tag is rendered in place. |
|
Specifies one of three types of formatting: |
|
A |
|
The maximum number of digits shown to the left of the decimal point. |
|
The minimum number of digits shows to the left of the decimal point. |
|
The maximum number of digits shown to the right of the decimal point. |
|
The minimum number of digits shows to the right of the decimal point. |
|
A formatting pattern used to format the value. The pattern string can include symbols such as |
Here's an example that uses various attributes to indicate that the numeric value of the variable n
should be rendered with at most seven digits and at least one digit to the left of the decimal point, exactly three digits to the right of decimal point, and with digit groups separated by commas:
<fmt:formatNumber value="${n}"
maxIntegerDigits="7"
minIntegerDigits="1"
maxFractionDigits="3"
minFractionDigits="3"
groupingUsed="true"/>
With this formatting, the value 1234.56
will be displayed as 1,234.560
.
The pattern
attribute lets you provide a formatting specification more concisely by using characters such as #
and 0
for digits, as well as commas and a decimal point. Here's how the previous formatting example could be done with pattern
:
<fmt:formatNumber value="${n}" pattern="#,###,##0.000"/>
The resulting output is the same.
Up to this point in this chapter, I focus on using expressions and JSTL tags to create JSP pages. The JSP pages are responsible for handling the Presentation layer of a JSP application. In this section, I turn my attention to creating servlets that handle the Controller layer.
A servlet for a JSP application is very different from a stand-alone servlet. A stand-alone servlet is responsible for emitting HTML that will be sent to the client as part of the HTTP response (see Chapter 1 of this minibook). It typically does this by grabbing a PrintWriter
instance from the Response
object and writing hand-crafted HTML.
That's a serious violation of the MVC design paradigm for modern web applications, in which the presentation logic of the application should be separated from the business and control logic. In a JSP application, the JSP page is solely responsible for crafting the user interface: That’s the job of the HTML and the UEL expressions and JSTL tags in the .jsp
file.
The servlet in a JSP application is responsible for processing the request received via a GET
message, which may involve calling upon classes in the Model layer to retrieve or update database data or to make business decisions. When these tasks have been completed, the servlet redirects the request to the JSP page, which builds the final presentation and sends it off to the client.
There are two important tasks you need to know how to do to create even a simple controller servlet for a JSP application. First, you need to know how to attach data to the Request
object so that the data will be passed on to the JSP page; you do that by setting request attributes. Second, you need to know how to redirect the request to the JSP page.
To attach data to the Request
object, you use the Request.setAttribute
method. This method has the following signature:
void setAttribute(java.lang.String name, java.lang.Object o)
As you can see, just two parameters are required. The first parameter is a String that provides a name for the attribute. The second parameter is the attribute itself, which can be literally any kind of Java object. In other words, you can pass absolutely anything you want to the Presentation layer. It's up to the Presentation layer to render the object in a format suitable for the client.
Here’s an example that adds an ArrayList
named movies
using the attribute name movies
:
request.setAttribute("movies", movies);
The JSP can then access the ArrayList
using the attribute name movies
.
In the section “Creating loops,” earlier in this chapter, I mention that you can use c:forEach
to iterate over a collection. Here's an example that retrieves Movie
objects from the movies
attribute, assigns them to a variable named movie
, and then displays the Title
property of each Movie
:
<c:forEach var="movie" items="${movies}">
<p>${movie.title}</p>
</c:forEach>
You'll see code similar to this in a complete action later in this chapter.
When your controller servlet has attached all the data to request attributes, it’s time to redirect the request to the JSP page. You do in the servlet’s doGet
or doPost
method by using a somewhat confusing combination of method calls on the Request
object:
request.getRequestDispatcher("/ListMovies.jsp").forward(request, response);
Here, you first call a Request
method named getRequestDispatcher
to obtain a RequestDispatcher
object. This method requires that you specify a URL for the resource you want to redirect to — in this case, the JSP page named ListMovies.jsp
.
When you have the RequestDispatcher
in hand, you call its forward
method, which forwards the request. You must supply both a Request
and a Response
object, which are typically passed on from the Request
and Response
method received as arguments to the doGet
or doPost
method. Keep in mind that the Request
object now carries the attributes you assigned. In this way, the JSP page will receive the attributes so it can format the data.
That's about all there is to it, at least for the simplest of JSP pages. In the next section, I put everything together in a complete application.
This section presents a JSP version of the Movies application that I present in Chapter 1 of this minibook. This version uses a servlet called moviejsp
. Figure 2-1 shows the output displayed by the JSP. Like the version in Chapter 1, this version displays the movies contained in a text file named movies.txt
. This version also adds a count of the movies in the file, as shown in the header “9 of My Favorite Movies.”
The application consists of four components:
Movie.java
: A class that represents a movie with three properties: Title
, Year
, and Price
. The class uses the accessor pattern to expose these properties. (This class is shown in Listing 2-1.)MovieIO.java
: A class that manages the file I/O necessary to retrieve the movie data from the Movies.txt
file. This class is identical to the version presented in Chapter 1 of this minibook and is shown in Listing 2-2 for reference.ListMovies.java
: The controller servlet for the application. In the web.xml
file, this class is mapped directly to a servlet named movies
with the URL pattern \Movies
. So, it can be invoked from a browser by navigating to http://localhost:8080/moviejsp/Movies
. This class is shown in Listing 2-3.ListMovies.jsp
: The JSP page for the application. When a request is made for the moviejsp
servlet, the ListMove
class calls upon MovieIO
to get the list of movies. It then appends the list to the Request
object and forwards the request to ListMovies.jsp
. The JSP page then renders the HTML for the response and sends it to the browser. The JSP page is shown in Listing 2-4.LISTING 2-1 Movies.java
package com.lowewriter.moviejsp;→1
public class Movie
{
private String title;
private int year;
private double price;
public Movie(String title, int year,
double price)
{
this.title = title;
this.year = year;
this.price = price;
}
public String getTitle()→17
{
return title;
}
public int getYear()→22
{
return year;
}
public double getPrice()→27
{
return price;
}
}
Here are the key lines of this class:
Movie
class is part of the package com.lowewriter.moviejsp
. All the other classes for this application also belong to this package.getTitle
method is the accessor for the title
property.getYear
is the accessor for the year
property.getPrice
is the accessor for the price
property.LISTING 2-2 MovieIO.java
package com.lowewriter.moviejsp;
import java.io.*;
import java.util.*;
public class MovieIO
{
public static ArrayList<Movie> getMovies()
{
ArrayList<Movie> movies = new ArrayList<Movie>();
BufferedReader in = getReader("c:\\data\\movies.txt");
Movie movie = readMovie(in);
while (movie != null)
{
movies.add(movie);
movie = readMovie(in);
}
return movies;
}
private static BufferedReader getReader(String name)
{
BufferedReader in = null;
try
{
File file = new File(name);
in = new BufferedReader(new FileReader(file) );
}
catch (FileNotFoundException e)
{
System.out.println("The file doesn't exist.");
System.exit(0);
}
return in;
}
private static Movie readMovie(BufferedReader in)
{
String title;
int year;
double price;
String line = "";
String[] data;
try
{
line = in.readLine();
}
catch (IOException e)
{
System.out.println("I/O Error");
System.exit(0);
}
if (line == null)
return null;
else
{
data = line.split("\t");
title = data[0];
year = Integer.parseInt(data[1]);
price = Double.parseDouble(data[2]);
return new Movie(title, year, price);
}
}
}
LISTING 2-3 ListMovies.java
package com.lowewriter.moviejsp;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
public class ListMovies extends HttpServlet
{
public void doGet(HttpServletRequest request,→10
HttpServletResponse response)
throws IOException, ServletException
{
ArrayList<Movie> movies = MovieIO.getMovies();→14
request.setAttribute("movies", movies);→16
request.setAttribute("number", movies.size());→17
request.getRequestDispatcher("/ListMovies.jsp")→18
.forward(request, response);
}
}
Here are the key points of the ListMovie.java servlet class:
doGet
method accepts Request
and Response
objects.MovieIO.getMovies()
is called to obtain a list of movies. The controller servlet is concerned only with the representation of this data as a list; the MovieIO
class is the only class that knows that the underlying data is stored in a text file.Request
object as an attribute named movies
.number
.ListMovies.jsp
page.LISTING 2-4 ListMovies.jsp
<!doctype html public "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>→3
<html>
<head>
<title>List Movies: The JSP</title>
</head>
<!--<ce:anchor id="pp:794 np:795" role="page-break"/>--><body>
<h2><c:out value="${number}"/> of My Favorite Movies</h1>→10
<h3 >
<c:forEach var="movie" items="${movies}">→12
<p>${movie.year}: ${movie.title}</p>
</c:forEach>
</h3>
</body>
</html>
Following is an explanation of the key lines in this JSP:
taglib
directive is required to use the JSTL core tags.number
attribute is retrieved from the Response
object and inserted in the heading.c:forEach
tag iterates over all the movie
objects in the movies
attribute. For each movie, the year
and title
properties are extracted and displayed on the page.