O'Reilly    
 Published on O'Reilly (http://oreilly.com/)
 See this if you're having trouble printing code examples


Using Tomcat

Deploying Web Applications to Tomcat

04/19/2001

Related Apache Articles on O'Reilly Network's ONLamp.com:

Getting, Installing, and Running Apache

Securing Your Apache Serve (Chapter 3 from Apache: The Definitive Guide)

AxKit: An XML-Delivery Toolkit for Apache

An Amble Through Apache Configuration

Also in Using Tomcat:

Configuring Tomcat with IIS Web Server

Configuring Tomcat and Apache With JK 1.2

Demystifying Tomcat 4's server.xml File

Embedding Tomcat Into Java Applications

Using SOAP with Tomcat

In this article we are going to cover the deployment of web applications using Tomcat. We are performing a manual deployment to fully explain the steps involved when deploying a web application.

The best way to describe the deployment process is to create a web application of our own that includes the important components found in most Java web applications; then package it for deployment. The following sections will take you through the steps involved in deploying a web application. The name of our web application will be onjava.

.

In this article, we

Creating the Web Application Directory Structure

The first thing you need to do is create the directory structure that will contain the application. We discussed this structure in Part 1, Java Web Applications, and I include the relevant details in Table 1.


Table 1. The Web Application Directory Structure

Directory

Contains

/onjava

This is the root directory of the web application. All JSP and XHTML files are stored here.

/onjava/WEB-INF

This directory contains all resources related to the application that are not in the document root of the application. This is where your web application deployment descriptor is located. Note that the WEB-INF directory is not part of the public document. No files contained in this directory can be served directly to a client.

/onjava/WEB-INF/classes

This directory is where servlet and utility classes are located.

/onjava/WEB-INF/lib

This directory contains Java Archive files that the web application depends upon. For example, this is where you would place a JAR file that contained a JDBC driver.

The name of our web application, onjava, is the root of our directory structure.

While in development I suggest creating the directory directly in the Tomcat /webapps directory. When it comes time for deployment, you can package your web application into a WAR file and go though the production deployment process.

The last step in creating the web application directory structure is adding a deployment descriptor. At this point you'll be creating a default web.xml file that contains only the DTD, describing the web.xml file, and an empty <webapp/> element. Listing 1 contains the source for a default web.xml file.

Listing 1 web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">

<web-app>
</web-app>

Now copy this file to the TOMCAT_HOME/onjava/WEB-INF/ directory, and we'll begin adding web application components to it in the following sections.

Creating a Web Application ServletContext

After you've created the web application directory structure, you must add a new ServletContext to Tomcat. The ServletContext defines a set of methods that are used by components of a web application to communicate with the servlet container. The ServletContext acts as a container for the web application. There is only one ServletContext per web application. We will discuss the relationship between a ServletContext and its web application in much more detail in Part 4, "Web Applications and the ServletContext."

To add a new ServletContext to Tomcat you need to add the following entry to the TOMCAT_HOME/conf/server.xml file, setting the values for the path and docBase to the name of your web application. Notice again that the name we are using is onjava.

<Context path="/onjava" docBase="onjava" debug="0" reloadable="true" />

There are two things here we need to focus on. The first, path="/onjava", tells the servlet container that all requests with /onjava appended to the server's URL belong to the onjava web application. The second, docBase="onjava", tells the servlet container that the web application exists in the /onjava directory.

Adding JSPs

Now that you have created the web application directories and added ServletContext, you can add server-side Java components. The first components we are going to add are JSPs.

The first JSP will include a simple login screen. Listing 2 contains the source for the login.jsp page.

Listing 2 login.jsp

<html>
<head>
 <title>OnJava Demo</title>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

<body bgcolor="#FFFFFF" onLoad="document.loginForm.username.focus()">

 <table width="500" border="0" cellspacing="0" cellpadding="0">
  <tr>
   <td> </td>
  </tr>
  <tr>
  <td>
   <img src="/onjava/images/monitor2.gif"></td>
  </tr>
  <tr>
   <td> </td>
  </tr>
 </table>
 <table width="500" border="0" cellspacing="0" cellpadding="0">
  <tr>
   <td>
    <table width="500" border="0" cellspacing="0" cellpadding="0">
     <form name="loginForm" method="post" action="servlet/com.onjava.login">
     <tr>
      <td width="401"><div align="right">User Name: </div></td>
      <td width="399"><input type="text" name="username"></td>
     </tr>
     <tr>
      <td width="401"><div align="right">Password: </div></td>
      <td width="399"><input type="password" name="password"></td>
     </tr>
     <tr>
      <td width="401"> </td>
      <td width="399"><br><input type="Submit" name="Submit"></td>
     </tr>
     </form>
    </table>
   </td>
  </tr>
 </table>
</body>
</html>

As you look at this JSP, you'll see nothing very special about it. The only thing you should pay attention to is the action of the form. It references a servlet in the package com.java named login. This servlet will retrieve the username-password parameters from the request and perform its own processing.

There isn't much to deploying a JSP. You just copy it to the public directory of your web application, which in this case is TOMCAT_HOME/webapps/onjava/. Any images that it references should be placed in an images folder that you have created in the /onjava directory.

To see this JSP in action, open the following URL in a browser:

http://localhost:8080/onjava/login.jsp

If you changed the default HTTP port, as mentioned in Installing and Configuring Tomcat, you will need to request the URL from the appropriate port value. If everything was configured correctly, you should see an image similar to Figure 1.

Screen shot.
Figure 1. If everything is configured correctly, you'll see something like this.

If you do not see a page similar to this image, make sure you have the correct entry in the server.xml file, as described in the section, "Creating a Web Application ServletContext."

The second JSP is the target JSP referenced by the servlet defined in the following section. This JSP will retrieve the request attribute USER that was added to the request with the following servlet. It will then output the String value of the attribute. Listing 3 contains the source for the target JSP.

Listing 3 welcome.jsp

<html>
<head>
 <title>OnJava Demo</title>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

 <table width="500" border="0" cellspacing="0" cellpadding="0">
  <tr>
   <td> </td>
  </tr>
  <tr>
  <td>
   <img src="/onjava/images/monitor2.gif"></td>
  <td>
   <b>Welcome : <%= request.getAttribute("USER")
%></b>
  </td>
  </tr>
  <tr>
   <td> </td>
  </tr>
 </table>
</body>
</html>

As we stated earlier to deploy this JSP, you simply need to copy it to the public directory of your web application, which in this case is TOMCAT_HOME/webapps/onjava/.

Adding Servlets

The next component to add is a servlet. This servlet will be the action of login.jsp's form. It will retrieve the username and password values from HttpServletRequest, look up the associated user, and then forward the request to a target JSP. The source code for this servlet can be found in Listing 4.

For our example the value of the USER is static. Normally you would perform a real lookup of some sort, but, to keep things simple, I'm just returning String Bob.

Listing 4 com.onjava.login.java

package com.onjava;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;

public class login extends HttpServlet {

 private String target = "/welcome.jsp";

 private String getUser(String username, String password) {

// Just return a static name
  // If this was reality, we would perform a SQL lookup
  return "Bob";
 }

 public void init(ServletConfig config)
  throws ServletException {

  super.init(config);
 }

 public void doGet(HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, IOException {

  // If it is a get request forward to doPost()
  doPost(request, response);
 }

 public void doPost(HttpServletRequest request,
  HttpServletResponse response)
  throws ServletException, IOException {

  // Get the username from the request
  String username = request.getParameter("username");
  // Get the password from the request
  String password = request.getParameter("password");

  String user = getUser(username, password);

  // Add the fake user to the request
  request.setAttribute("USER", user);

  // Forward the request to the target named
  ServletContext context = getServletContext();

  RequestDispatcher dispatcher =
   context.getRequestDispatcher(target);
  dispatcher.forward(request, response);
 }

 public void destroy() {
 }
}

To deploy a servlet as part of a web application you first need to compile the servlet and move it into the web application's /WEB-INF/classes directory. For this example, you should compile this servlet and move it to the /onjava/WEB-INF/classes/com/onjava/ directory.

This class file is in the subdirectory com.onjava because of its package name.

The next step in deploying the login servlet is to add a servlet entry into the web application's web.xml file. An example <servlet> element can be found in the following code snippet.

It isn't necessary to add all servlets to the web.xml file; it's only necessary when the servlet requires additional information, such as initialization parameters.

Example <servlet> Element

<servlet>
  <servlet-name>ExampleServlet</servlet-name>
  <servlet-class>packagename.ExampleServlet</servlet-class>
  <init-param>
   <param-name>parameter</param-name>
   <param-value>value</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

This servlet entry contains a simple servlet definition. A description of each of its parts can be found in Table 2.

Table 2. The Sub-elements of a <servlet>

Sub-element

Description

<servlet-name>

The <servlet-name> element is simply the canonical name of the deployed servlet.

<servlet-class>

The <servlet-class> sub-element references the fully qualified class name of the servlet.

<init-param>

The <init-parameter> sub-element is an optional parameter containing a name-value pair that is passed to the servlet on initialization. It contains two sub-elements, <param-name> and <param-value>, which contain the name and value, respectively, to be passed to the servlet.

<load-on-startup>

The <load-on-startup> sub-element indicates the order in which each servlet should be loaded. Lower positive values are loaded first. If the value is negative or unspecified, then the container can load the servlet at anytime during startup.

To add our login servlet we need to make the following entry into the TOMCAT_ROOT/onjava/WEB-INF/web.xml file:

<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.onjava.login</servlet-class>
</servlet>

That's all there is to it. To see your web application in action, restart the Tomcat server and open the following URL in your browser:

http://localhost:8080/onjava/login.jsp

You should see an image similar to Figure 1 (which was referred to above). Now enter a username and password and press the "Submit Query" button. If everything went according to plan, you should see an image similar to Figure 2.

Screen shot.
Figure 2. Results after pressing "Submit Query".

If you didn't see an image similar to Figure 2, make sure that you have the servlet class in the appropriate directory and the entry in the web.xml file matches the code snippet referenced above.

Adding Tag Libraries

The final component that we're adding is a tag library. This library contains a single tag, HelloTag, that replaces every occurrence of the text <onjava:hello/> with the literal string "Hello". While this is a perfectly silly example of a tag library, it allows us to present a practical example of deploying a tag library. The source code for the tag handler can be found in Listing 5 and the source for the tld can be found in Listing 6.

Listing 5 HelloTag.java

package com.onjava;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspTagException;
import javax.servlet.jsp.tagext.TagSupport;

public class HelloTag extends TagSupport
{
 public void HelloTag() {

 }

 // Method called when the closing hello tag is encountered
 public int doEndTag() throws JspException {

  try {

   // We use the pageContext to get a Writer
   // We then print the text string Hello
   pageContext.getOut().print("Hello");
  }
  catch (Exception e) {

   throw new JspTagException(e.getMessage());
  }
  // We want to return SKIP_BODY because this Tag does not support
  // a Tag Body
  return SKIP_BODY;
 }

 public void release() {

  // Call the parent's release to release any resources
  // used by the parent tag.
  // This is just good practice for when you start creating
  // hierarchies of tags.
  super.release();
 }
}

Listing 6 taglib.tld

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE taglib
  PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
"http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">

<!-- a tag library descriptor -->

<taglib>
 <tlibversion>1.0</tlibversion>
 <jspversion>1.1</jspversion>
 <shortname>onjava</shortname>
 <uri>/onjava</uri>

 <tag>
 <name>hello</name>
 <tagclass>com.onjava.HelloTag</tagclass>
 <bodycontent>empty</bodycontent>
 <info>Just Says Hello</info>
 </tag>
</taglib>

To deploy this tag library, we need to make an entry to the web.xml file. The modified web.xml file can be found in Listing 7.

Listing 7 web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app PUBLIC
 '-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN'
 'http://java.sun.com/j2ee/dtds/web-app_2_3.dtd'>

<web-app>

 <servlet>
  <servlet-name>login</servlet-name>
  <servlet-class>com.onjava.login</servlet-class>
 </servlet>

 <taglib>
  <taglib-uri>/onjava</taglib-uri>
  <taglib-location>/WEB-INF/lib/taglib.tld</taglib-location>
 </taglib>

</web-app>

The added <taglib> entry contains two elements. The first <taglib> element, <taglib-uri>, tells the container how the tag library is to be referenced. For this example we use the value /onjava, which is the way we'll reference the tag library in our JSPs.

The second <taglib> element, <taglib-location>, defines the location of the tag library's descriptor (TLD). The TLD defines the tags contained in the library and the handlers that will process the defined tags.

To complete your deployment, copy the compiled tag library and the taglib.tld into the TOMCAT_ROOT/onjava/WEB-INF/lib directory.

To test you new tag library, you need to modify the welcome.jsp page, replacing the Welcome message with a reference to the <onjava:hello /> tag. You need to also add a taglib directive referencing the taglib.tld to the welcome.jsp file. The modified JSP is in Listing 7.


Listing 7 Modified welcome.jsp

<%@ taglib uri="/onjava" prefix="onjava" %>
<html>
<head>
 <title>Onjava Demo</title>
 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>

 <table width="500" border="0" cellspacing="0" cellpadding="0">
  <tr>
   <td> </td>
  </tr>
  <tr>
  <td>
   <img src="/onjava/images/monitor2.gif"></td>
  <td>
   <b><onjava:hello /> : <%= request.getAttribute("USER") %></b>
  </td>
  </tr>
  <tr>
   <td> </td>
  </tr>
 </table>
</body>
</html>

Now open the login.jsp page as described previously and run through the demo again. This time instead of Welcome: Bob, you should see the message Hello: Bob.

Creating and Deploying a WAR File

When your web application is ready for deployment, you need to package it for distribution. As we discussed previously in Java Web Applications, web applications are packaged in WAR files. The steps required to "WAR-up" your /onjava web application and deploy it are as follows:

  1. Change to the root directory of your web application. In this case the root directory would be TOMCAT_HOME/webapps/onjava/.

  2. Archive the web application:

    jar cvf onjava.war .
  3. Copy the resulting WAR file, onjava.war, to the TOMCAT_HOME/webapps directory.

    If you're deploying this WAR file to the Tomcat installation that you were developing in, then you will need to back up your development directory and remove it from the TOMCAT_HOME/webapps directory.

  4. Add a new Context entry to the /TOMCAT_HOME/conf/server.xml file, referencing the onjava web application.

  5. Restart Tomcat.

That's it. Your application should now be deployed and running. If it isn't, check your entry in the TOMCAT_HOME/conf/server.xml file to ensure that you have set the appropriate values.

Now that you know how to create and deploy a web applications, we'll examine the relationship of the web application and its ServletContext in a future article.

James Goodwill is the co-Founder of Virtuas Solutions, LLC, a Colorado-based software consultancy.


Read more Using Tomcat columns.

Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.