Recipe 17.3. Using Tomcat to Run Web Scripts


Problem

You want to run Java-based programs in a web environment.

Solution

Write programs using JSP notation and execute them using a servlet container such as Tomcat.

Discussion

As described in Section 17.2, 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 relationshiplike 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 Section 17.2 using Perl, Ruby, PHP, and Python.

Installing the mcb application

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:\recipes and C:\jakarta-tomcat, use this command:

C:\> copy C:\recipes\tomcat\mcb.war C:\jakarta-tomcat\webapps                

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

Unpacking a WAR File Manually

WAR files are actually ZIP-format archives that can be unpacked using jar, WinZip, or any other tool that understands ZIP files. However, when unpacking a WAR file manually, you'll need to create its top-level directory first. The following sequence of steps shows one way to do this, using the jar utility to unpack a WAR file named mcb.war that is assumed to be located in Tomcat's webapps directory. For Unix, change location to the webapps directory, and then issue the following commands:

% mkdir mcb % cd mcb % jar xf ../mcb.war                   

For Windows, the commands are only slightly different:

C:\> mkdir mcb C:\> cd mcb C:\> jar xf ..\mcb.war                   

Unpacking the WAR file in the webapps directory creates a new application context, so you'll need to restart Tomcat before it notices the new application.


Installing the JDBC driver

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-tomcat\common\lib                

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.

Installing the JSTL distribution

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:

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

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

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

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

  5. 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.)

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

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

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

Writing JSP pages with JSTL

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> 

Writing a MySQL script using JSP and JSTL

Section 17.2 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.




MySQL Cookbook
MySQL Cookbook
ISBN: 059652708X
EAN: 2147483647
Year: 2004
Pages: 375
Authors: Paul DuBois

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net