As described in Using Apache to Run Web Scripts, Apache can be used to run Perl, Ruby, PHP, and Python scripts. For Java, a different approach is needed because Apache doesn’t serve JSP pages. Instead, we’ll use Tomcat, a server designed for processing Java in a web environment. Apache and Tomcat are very different servers, but there is a familial relationship—like Apache, Tomcat is a development effort of the Apache Software Foundation.
This recipe provides an overview of JSP programming with Tomcat, but makes several assumptions:
You have some familiarity with the concepts underlying JavaServer Pages, such as what a servlet container is, what an application context is, and what the basic JSP scripting elements are.
The Tomcat server has been installed so that you can execute JSP pages, and you know how to start and stop it.
You are familiar with the Tomcat webapps directory and how a Tomcat application is structured. In particular, you understand the purpose of the WEB-INF directory and the web.xml file.
You know what a tag library is and how to use one.
I recognize that this is a lot to assume. If you’re unfamiliar with JSP or need instructions for installing Tomcat, Appendix C provides the necessary background information.
Once you have Tomcat in place, you should install the following components so that you can work through the JSP examples in this book:
The mcb
sample
application located in the tomcat directory of the recipes
distribution.
A MySQL JDBC driver. You might already have one installed for use with the scripts in earlier chapters, but Tomcat needs a copy, too. This book uses MySQL Connector/J.
The JSP Standard Tag Library (JSTL), which contains tags for performing database activities, conditional testing, and iterative operations within JSP pages.
This section discusses how to install these components, provides a brief overview of some of the JSTL tags, and describes how to write the JSP equivalent of the MySQL table-display script that was implemented in Using Apache to Run Web Scripts using Perl, Ruby, PHP, and Python.
Web applications for Tomcat typically are packaged
as
files WAR (web archive) files and installed under its
webapps directory, which is
roughly analogous to Apache’s htdocs document root directory. The
recipes
distribution includes a
sample application named mcb
that
you can use for trying the JSP examples described here. Look in the
distribution’s tomcat
directory, where you will find a file named mcb.war. Copy that file to Tomcat’s
webapps directory.
Here’s an example installation procedure for Unix, assuming that the recipes
distribution and Tomcat are
located at /u/paul/recipes and
/usr/local/jakarta-tomcat.
Adjust the pathnames as necessary for your own system. The command
to install mcb.war looks like
this:
%cp /u/paul/recipes/tomcat/mcb.war /usr/local/jakarta-tomcat/webapps
For Windows, if the relevant directories are C: ecipes and C:jakarta-tomcat, use this command:
C:>copy C:
ecipes omcatmcb.war C:jakarta-tomcatwebapps
After copying the mcb.war
file to the webapps
directory, restart Tomcat. As distributed, Tomcat is configured by
default to look for WAR files under webapps when it starts up and
automatically unpack any that have not already been unpacked. This
means that restarting Tomcat after copying mcb.war to the webapps directory should be enough to
unpack the mcb
application. When
Tomcat finishes its startup sequence, look under webapps and you should see a new
mcb directory under which are
all the files contained in mcb.war. (If Tomcat doesn’t unpack
mcb.war automatically, see the
sidebar “Unpacking a WAR File Manually.”) If you like,
have a look around in the mcb
directory at this point. It should contain several files that
clients can request using a browser. There should also be a
WEB-INF subdirectory, which is
used for information that is private—that is, available for use by
scripts in the mcb directory,
but not directly accessible by clients.
Next, verify that Tomcat can serve pages from the mcb
application context by requesting some
of them from your browser. The following URLs request in turn a
static HTML page, a servlet, and a simple JSP page:
http://localhost:8080/mcb/test.html http://localhost:8080/mcb/servlet/SimpleServlet http://localhost:8080/mcb/simple.jsp
Adjust the hostname and port number in the URLs appropriately for your installation.
The JSP pages in the mcb
application need a JDBC driver for connecting to the cookbook
database.
The following instructions describe how to install the MySQL
Connector/J driver; the installation procedure for other drivers
should be similar.
To install MySQL Connector/J for use by Tomcat applications, place a copy of it in Tomcat’s directory tree. Assuming that the driver is packaged as a JAR file (as is the case for MySQL Connector/J), there are three likely places under the Tomcat root directory where you can install it, depending on how visible you want the driver to be:
To make the driver available only to the mcb
application, place it in the
mcb/
WEB-INF/lib directory under
Tomcat’s webapps
directory.
To make the driver available to all Tomcat applications but not to Tomcat itself, place it in the shared/lib directory under the Tomcat root.
To make the driver available both to applications and to Tomcat, place it in the common/lib directory under the Tomcat root.
I recommend installing a copy of the driver in the common/lib directory. That gives it the
most global visibility (it will be accessible both by Tomcat and by
applications), and you’ll need to install it only once. If you
enable the driver only for the mcb
application by placing a copy in
mcb/WEB-INF/lib, but then
develop other applications that use MySQL, you’ll need to either
copy the driver into those applications or move it to a more global
location.
Making the driver more globally accessible also is useful if you think it likely that at some point you’ll elect to use JDBC-based session management or realm authentication. Those activities are handled by Tomcat itself above the application level, so Tomcat needs access to the driver to carry them out.
Here’s an example installation procedure for Unix, assuming that the MySQL Connector/J driver and Tomcat are located at /tmp/mysql-connector-java-bin.jar and /usr/local/jakarta-tomcat. Adjust the pathnames as necessary for your own system. The command to install the driver looks like this:
%cp /tmp/mysql-connector-java-bin.jar /usr/local/jakarta-tomcat/common/lib
For Windows, if the components are installed at C:mysql-connector-java-bin.jar and C:jakarta-tomcat, use this command:
C:>copy C:mysql-connector-java-bin.jar C:jakarta-tomcatcommonlib
After installing the driver, restart Tomcat and then request
the following mcb
application
page to verify that Tomcat can find the JDBC driver properly:
http://localhost:8080/mcb/jdbc_test.jsp
You might need to edit jdbc_test.jsp first to change the connection parameters.
Most of the scripts that are part of the mcb
sample application use JSTL, so it’s
necessary to install it or those scripts won’t work. To install a
tag library into an application context, copy the library’s files
into the proper locations under the application’s
WEB-INF directory. Generally, this
means installing at least one JAR file and a
tag library descriptor (TLD) file, and adding some
tag library information to the application’s web.xml file. JSTL actually consists of
several tag sets, so there are there are several JAR files and TLD
files. The following instructions describe how to install JSTL for
use with the mcb
application:
Make sure that the mcb.war file has been unpacked to
create the mcb
application
directory hierarchy under the Tomcat webapps directory. (Refer back to
Installing the mcb application.) This is
necessary because the JSTL files must be installed under the
mcb/WEB-INF directory,
which will not exist until mcb.war has been unpacked.
Get the JSTL distribution from the Jakarta Project web site. Go to the Jakarta Taglibs project page, which is accessible at http://jakarta.apache.org/taglibs/.
Follow the Standard Taglib link to get to the JSTL information page; the latter has a Downloads section from which you can get the binary JSTL distribution. Be sure to get version 1.1.2 or higher.
Unpack the JSTL distribution into some convenient location, preferably outside of the Tomcat hierarchy. The commands to do this are similar to those used to unpack Tomcat itself (see the section “Installing a Tomcat Distribution” in Appendix C). For example, to unpack a ZIP-format distribution, use the following command, adjusting the filename as necessary:
%jar xf jakarta-taglibs-standard.zip
Unpacking the distribution creates a directory containing several files. Copy the JAR files (jstl.jar, standard.jar, and so forth) to the mcb/WEB-INF/lib directory. These files contain the class libraries that implement the JSTL tag actions. Copy the tag library descriptor files (c.tld, sql.tld, and so forth) to the mcb/WEB-INF directory. These files define the interface for the actions implemented by the classes in the JAR files.
The mcb/WEB-INF
directory contains a file named web.xml that is the web application
deployment descriptor file (a fancy name for
“configuration file”). Modify web.xml to add
<taglib>
entries for each of the JSTL TLD files. The entries look
something like this:
<taglib> <taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri> <taglib-location>/WEB-INF/c.tld</taglib-location> </taglib> <taglib> <taglib-uri>http://java.sun.com/jsp/jstl/sql</taglib-uri> <taglib-location>/WEB-INF/sql.tld</taglib-location> </taglib>
Each <taglib>
entry contains a <taglib-uri>
element that
specifies the symbolic name by which mcb
JSP pages refer to the
corresponding TLD file, and a <taglib-location>
element that indicates the location of the TLD
file under the mcb
application directory. (You’ll find that web.xml as distributed already
contains these entries. However, you should take a look at them
to make sure they match the filenames of the TLD files that you
just installed in the previous step.)
The mcb/WEB-INF
directory also contains a file named jstl-mcb-setup.inc. This file is not
part of JSTL itself, but it contains a JSTL <sql:setDataSource>
tag that is used by many of the mcb
JSP pages to set up a data source
for connecting to the cookbook
database. The file looks
like this:
<sql:setDataSource var="conn" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/cookbook" user="cbuser" password="cbpass" />
Edit the driver
,
url
, user
, and password
tag attributes as necessary
to change the connection parameters to those that you use for
accessing the cookbook
database. Do not change the var
attribute.
The JSTL distribution also includes WAR files containing documentation and examples (standard-doc.war and standard-examples.war). If you want to install these, copy them into Tomcat’s webapps directory. (I recommand that you install the documentation so that you can access it locally from your own server. It’s useful to install the examples as well, because they provide helpful demonstrations showing how to use JSTL tags in JSP pages.)
Restart Tomcat so that it notices the changes you’ve just
made to the mcb
application
and so that it unpacks the WAR files containing the JSTL
documentation and examples. If Tomcat doesn’t unpack WAR files
for you automatically, refer back to the sidebar
“Unpacking a WAR File Manually.”
After installing JSTL and restarting Tomcat, request the
following mcb
application page to
verify that Tomcat can find the JSTL tags properly:
http://localhost:8080/mcb/jstl_test.jsp
This section discusses the syntax for some of the JSTL tags used
most frequently by mcb
JSP pages.
The descriptions are very brief, and many of these tags have
additional attributes that allow them to be used in ways other than
those shown here. For more information, consult the JSTL
specification (see Appendix D).
A JSP page that uses JSTL must include ain
taglib
directive
for each tag set that the page uses. Examples in this book use the
core and database tags, identified by the following taglib
directives:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
The uri
values should match the symbolic values that are listed in
the web.xml
<taglib>
entries (see the previous
section Installing the JSTL distribution).
The
prefix
values
indicate the initial string used in tag names to identify tags as
part of a given tag library.
JSTL tags are written in XML format, using a special syntax for tag attributes to include
expressions. Within tag attributes, text is interpreted literally
unless enclosed within ${...}
, in which case it is
interpreted as an expression to be evaluated. The following sections
summarize some of the commonly used core and database tags.
The JSTL core tag set. The following tags are part of the JSTL core tag set:
<c:out>
This tag evaluates its value
attribute and is replaced by
the result. One common use for this tag is to provide content
for the output page. The following tag produces the value
3:
<c:out value="${1+2}"/>
<c:set>
This tag assigns a value to a variable. For example, to
assign a string to a variable named title
and then use the variable
later in the <title>
element of the output page, do this:
<c:set var="title" value="JSTL Example Page"/> <html> <head> <title><c:out value="${title}"/></title> </head> ...
This example illustrates a principle that is generally
true for JSTL tags: to specify a variable into which a value
is to be stored, name it without using ${...}
notation. To refer to that variable’s value later, use it
within ${...}
so that it is
interpreted as an expression to be evaluated.
<c:if>
This tag evaluates the conditional test given in its
test
attribute. If the test
result is true, the tag body is evaluated and becomes the
tag’s output; if the result is false, the body is
ignored:
<c:if test="${1 != 0}"> 1 is not equal to 0 </c:if>
The comparison operators are ==
, !=
, <
, >
, <=
, and >=
. The alternative operators
eq
, ne
, lt
, gt
, le
, and ge
make it easier to avoid using
special HTML characters in expressions. Arithmetic operators
are +
, -
, *
, /
(or div
), and %
(or mod
). Logical operators are &&
(or and
), ||
(or or
), and !
(or not
). The special empty
operator is true if a value is
empty or null
:
<c:set var="x" value=""/> <c:if test="${empty x}"> x is empty </c:if> <c:set var="y" value="hello"/> <c:if test="${!empty y}"> y is not empty </c:if>
The <c:if>
tag
does not provide any “else” clause. To perform
if/then/else testing, use the <c:choose>
tag.
<c:choose>
This is another conditional tag, but it allows multiple
conditions to be tested. Include a
<c:when>
tag for each
condition that you want to test explicitly, and a <c:otherwise>
tag if there is
a “default” case:
<c:choose> <c:when test="${count == 0}"> Please choose an item </c:when> <c:when test="${count gt 1}"> Please choose only one item </c:when> <c:otherwise> Thank you for choosing exactly one item </c:otherwise> </c:choose>
<c:forEach>
This tag acts as an iterator, enabling you to loop over a set of values. The
following example uses a <c:forEach>
tag to loop
through a set of rows in the result set from a query
(represented here by the rs
variable):
<c:forEach items="${rs.rows}" var="row"> id = <c:out value="${row.id}"/>, name = <c:out value="${row.name}"/> <br /> </c:forEach>
Each iteration of the loop assigns the current row to
the variable row
. Assuming
that the query result includes columns named id
and name
, their values are accessible as
row.id
and
row.name
.
The JSTL database tag set. The JSTL database tags enable you to issue SQL statements and access their results:
<sql:setDataSource>
This tag sets up connection parameters to be used when
JSTL contacts the database server. For example, to specify
parameters for using the MySQL Connector/J driver to access
the cookbook
database, the
tag looks like this:
<sql:setDataSource var="conn" driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost/cookbook" user="cbuser" password="cbpass" />
The driver
, url
, user
, and password
attributes specify the
connection parameters, and the var
attribute names the variable to
associate with the connection. By convention, mcb
JSP pages in this book use the
variable conn
, so tags
occurring later in the page that require a data source can
refer to the connection using the expression ${conn}
.
To avoid listing connection parameters repeatedly in JSP
pages that use MySQL, you can put the <sql:setDataSource>
tag in a
file and include the file from each page that needs a database
connection. For the recipes
distribution, this include file is WEB-INF/jstl-mcb-setup.inc. JSP
pages can access the file as follows to set up the database
connection:
<%@ include file="/WEB-INF/jstl-mcb-setup.inc" %>
To change the connection parameters used by the mcb
pages, edit jstl-mcb-setup.inc.
<sql:update>
To issue a statement such as UPDATE
, DELETE
, or INSERT
that doesn’t return rows, use
a <sql:update>
tag.
A
dataSource
tag attribute indicates the data source, the rows-affected
count resulting from the statement is returned in the variable
named by the var
attribute,
and the statement itself should be specified in the tag
body:
<sql:update dataSource="${conn}" var="count"> DELETE FROM profile WHERE id > 100 </sql:update> Number of rows deleted: <c:out value="${count}"/>
<sql:query>
To process statements that return a result set, use <sql:query>
. As with <sql:update>
, the dataSource
attribute indicates the
data source, and the text of the statement is given in the tag
body. The <sql:query>
tag also takes a var
attribute that names a variable to associate with the result
set so that you can access the rows of the result:
<sql:query dataSource="${conn}" var="rs"> SELECT id, name FROM profile ORDER BY id </sql:query>
By convention, the mcb
JSP pages use rs
as the name of the result set
variable. Strategies for accessing the contents of a result
set are outlined shortly.
<sql:param>
You can write data values literally into a statement string,
but JSTL also allows the use of placeholders, which is helpful
for values that contain characters that are special in SQL
statements. Use a ?
character for each placeholder in the statement string, and
provide values to be bound to the placeholders using <sql:param>
tags in the body
of the statement-issuing tag. A data value can be specified
either in the body of an <sql:param>
tag or in its
value
attribute:
<sql:update dataSource="${conn}" var="count"> DELETE FROM profile WHERE id > ? <sql:param>100</sql:param> </sql:update> <sql:query dataSource="${conn}" var="rs"> SELECT id, name FROM profile WHERE cats = ? AND color = ? <sql:param value="1"/> <sql:param value="green"/> </sql:query>
The contents of a result set returned by <sql:query>
are accessible several
ways. Assuming that you have associated a variable named rs
with the result set, you can access row
i
of the result either as rs.rows[
i
]
or as rs.rowsByIndex[
i
]
, where row numbers begin at 0. The first
form produces a row with columns that can be accessed by name. The
second form produces a row with columns that can be accessed by
column number (beginning with 0). For example, if a result set has
columns named id
and name
, you can access the values for the
third row by using column names like this:
<c:out value="${rs.rows[2].id}"/> <c:out value="${rs.rows[2].name}"/>
To use column numbers instead, do this:
<c:out value="${rs.rowsByIndex[2][0]}"/> <c:out value="${rs.rowsByIndex[2][1]}"/>
You can also use <c:forEach>
as an iterator to loop
through the rows in a result set. To access column values by name,
iterate using rs.rows
:
<c:forEach items="${rs.rows}" var="row"> id = <c:out value="${row.id}"/>, name = <c:out value="${row.name}"/> <br /> </c:forEach>
To access column values by number, iterate using rs.rowsByIndex
:
<c:forEach items="${rs.rowsByIndex}" var="row"> id = <c:out value="${row[0]}"/>, name = <c:out value="${row[1]}"/> <br /> </c:forEach>
The number of rows in the result set is available as rs.rowCount
:
Number of rows selected: <c:out value="${rs.rowCount}"/>
Names of the columns in the result set are available using
rs.columnNames
:
<c:forEach items="${rs.columnNames}" var="name"> <c:out value="${name}"/> <br /> </c:forEach>
Using Apache to Run Web Scripts
shows how to write Perl, Ruby, PHP, and Python versions of
a script to display the names of the tables in the cookbook
database. With the JSTL tags, we
can write a corresponding JSP page that provides that information as
follows:
<%-- show_tables.jsp - Display names of tables in cookbook database --%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %> <%@ include file="/WEB-INF/jstl-mcb-setup.inc" %> <html> <head> <title>Tables in cookbook Database</title> </head> <body bgcolor="white"> <p>Tables in cookbook database:</p> <sql:query dataSource="${conn}" var="rs"> SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'cookbook' ORDER BY TABLE_NAME </sql:query> <c:forEach items="${rs.rowsByIndex}" var="row"> <c:out value="${row[0]}"/><br /> </c:forEach> </body> </html>
The taglib
directives
identify which tag libraries the script needs, and the include
directive pulls in the code that
sets up a data source for accessing the cookbook
database. The rest of the script
generates the page content.
Assuming that you’ve installed the mcb.war file in your Tomcat server’s webapps directory as described earlier, you should find the show_tables.jsp script in the mcb subdirectory. Request it from your browser as follows:
http://localhost:8080/mcb/show_tables.jsp
The JSP script does not produce any Content-Type:
header explicitly. The JSP
engine produces a default header with a content type of text/html
automatically.
3.21.248.162