Now that we've considered each of the pieces that constitute our ListManager web application, we'll look at how those pieces are put together into a web application WAR file. For completeness, we'll include all the servlets and JSP pages from this chapter, not just the ones that implement the mailing list manager. In order to do this, we must:
Write a web.xml file that configures all the
servlets Arrange that configuration filealong with the servlet
implementation classes, JSP pages, and related filesin their
correct places in a directory hierarchy Zip them all up (with the jar tool) to create a
WAR file
Recall from the start of this chapter that we used these commands to compile the servlet classes and create the WAR file:
javac -d WEB-INF/classes/ *.java jar cMf je3.war indexl *.jsp *.jspx ListManager/*.jsp WEB-INF/web. xml WEB-INF/tags/*.tag WEB-INF/classes
We'll consider the directory hierarchy of the web application first, and then look at the web.xml file.
Our je3 web application is structured as follows:
This is the root directory for the application. The servlet container will map a file x in this directory to a URL like this:
http://localhost:8080/je3/x
The default file served for the URL "je3/". This is just a plain HTML file that contains links to the various examples contained in the web application.
The hello.jsp, hello2.jsp and hello3.jspx examples go here.
A directory for the ListManager application, which serves to keep it separate from this chapter's other servlet and JSP examples.
The ListManager login page.
The ListManager edit preferences page.
Most web applications have a WEB-INF/ subdirectory for configuration information, servlet class files, and other auxiliary files. The servlet container does not expose these files to the client (although a servlet may do so if it chooses), so it is reasonably safe to store sensitive configuration information (such as passwords) beneath this directory.
The all-important configuration file that maps servlet names to Java class names and URLs to servlet names. It also defines servlet initialization parameters and maps tag library URIs to the actual location of the TLD file.
Java class files for the Controller servlet, its User and UserFactory model classes, and also the HelloNet, ErrorHandlerServlet, and Counter servlets.
.tag files defining the custom JSP 2.0 tags used in the web application.
The WEB-INF/web.xml file is the main configuration file for a web application. In a well-designed web application, this is the only file that may need customization when deploying the application to a new server or in a new network environment. The web.xml file for the servlet and JSP examples in this chapter, including the ListManager web application, is shown in Example 20-14.
The bulk of the web.xml file consists of <servlet> tags, which map servlet implementation classes to servlet names and define initialization parameters for servlets that need them. Note that it is perfectly legal to define multiple names for the same servlet implementation class. Creating multiple named instances of the same servlet implementation in this way allows you to specify different initialization parameters for each instance. You might set up multiple copies of the ListManager Controller servlet to manage multiple mailing lists, for example.
The other important tags in the configuration file are the <servlet-mapping> tags, which map servlet names to the URLs by which they may be invoked. Note that there can be more than one <servlet-mapping> tag for each servlet and that a <servlet-mapping> can include wildcard characters. <servlet> and <servlet-mapping> are the most important tags for a web.xml file, but they are by no means the only ones. The example illustrates a few others; see the Servlet specification for full details on the syntax of this file.
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd" version="2.4"> <!-- This is descriptive information about the webapp as a whole --> <display-name>Java Examples in a Nutshell</display-name> <description> Servlet and JSP examples from Java Examples in a Nutshell, 3rd edition, including a simple web application to allow users to subscribe and unsubscribe from a mailing list, and to set their mail delivery preferences. </description> <!-- Next come servlet tags that map class files to servlet names and --> <!-- also define servlet initialization parameters --> <servlet> <servlet-name>Hello</servlet-name> <servlet-class>je3.servlet.HelloNet</servlet-class> </servlet> <servlet> <servlet-name>ErrorHandler</servlet-name> <servlet-class>je3.servlet.ErrorHandlerServlet</servlet-class> </servlet> <!-- The Counter servlet uses initialization parameters --> <servlet> <servlet-name>Counter</servlet-name> <servlet-class>je3.servlet.Counter</servlet-class> <init-param> <param-name>countfile</param-name> <!-- where to save state --> <param-value>/tmp/counts.ser</param-value> <!-- adjust for your system--> </init-param> <init-param> <param-name>saveInterval</param-name> <!-- how often to save --> <param-value>30000</param-value> <!-- every 30 seconds --> </init-param> </servlet> <!-- The Controller servlet for the ListManager application needs --> <!-- initialization parameters to specify the database to be used. --> <!-- You'll need to set these before you can use the application. --> <servlet> <servlet-name>Controller</servlet-name> <servlet-class>je3.servlet.Controller</servlet-class> <init-param> <!-- the JDBC driver class to use --> <param-name>jdbcDriver</param-name> <param-value>com.mysql.jdbc.Driver</param-value> </init-param> <init-param> <!-- The database to connect to --> <param-name>jdbcURL</param-name> <param-value>jdbc:mysql:///test</param-value> </init-param> <init-param> <!-- The username to connect as --> <param-name>jdbcUser</param-name> <param-value></param-value> </init-param> <init-param> <!-- The password to use --> <param-name>jdbcPassword</param-name> <param-value></param-value> </init-param> <init-param> <!-- the database table to use --> <param-name>tablename</param-name> <param-value>testlist</param-value> </init-param> <init-param> <!-- the name of the mailing list --> <param-name>listname</param-name> <param-value>Test Email List</param-value> </init-param> </servlet> <!-- Next we map URLs and URL patterns to servlet names --> <servlet-mapping> <servlet-name>Hello</servlet-name> <url-pattern>/Hello</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ErrorHandler</servlet-name> <url-pattern>/ErrorHandler</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Counter</servlet-name> <url-pattern>/Counter</url-pattern> </servlet-mapping> <!-- Note the wildcard below: any URL ending in .count invokes Counter --> <servlet-mapping> <servlet-name>Counter</servlet-name> <url-pattern>*.count</url-pattern> </servlet-mapping> <!-- These are the different URLs that invoke the ListManager Controller --> <!-- Note that we could also use wildcards here. --> <servlet-mapping> <servlet-name>Controller</servlet-name> <url-pattern>/ListManager/</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Controller</servlet-name> <url-pattern>/ListManager/login.action</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Controller</servlet-name> <url-pattern>/ListManager/logout.action</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Controller</servlet-name> <url-pattern>/ListManager/edit.action</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Controller</servlet-name> <url-pattern>/ListManager/unsubscribe.action</url-pattern> </servlet-mapping> <!-- ListManager sessions timeout after 15 minutes of inactivity --> <session-config> <session-timeout>15</session-timeout> </session-config> </web-app>