Chapter 4. Deploying Web Applications

A Java servlet/JSP engine is not really useful without servlets and JSPs, and deploying servlets can sometimes be a difficult and error-prone process, because, in addition to writing and compiling the servlet, you will need to edit at least 2 XML files to get the servlet properly deployed. I will cover the manual method here, but there are other ways, such as using the Manager Web Application or developing an Ant build process. There is also a deployer package that you can download. I don't know how to use it though. If you do know, please email me!

We will write and compile a simple "HelloWorld" servlet and deploy it, using this example to "bootstrap" future deployments. We need to test if the deployment environment is properly setup, and try out some customization features, so we will keep our first servlet simple to familiarize ourselves with the process.

4.1. Creating the HelloWorld Servlet

First, open your favorite text editor or Java IDE and create the following file :

Example 4-1. HelloWorld Servlet

// Filename : HelloWorld.java
// Description : This servlet merely says hello!


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

public class HelloWorld extends HttpServlet {

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

                response.setContentType("text/html");
                PrintWriter out = response.getWriter();

                out.println("<html>");
                out.println("<head><title>Hello, Cruel World!</title></head>");
                out.println("<body>");
                out.println("<h1>Hello, Cruel World !</h1>");
                out.println("This is my first servlet.");
                out.println("</body>");
        }// end doGet

}///:~

Now, we save the file as HelloWorld.java and compile it. Here, you will find the first of several differences between Tomcat 4 and Tomcat 5.

If you're like me, you normally use the servlet classes supplied by Tomcat to compile your servlets, take note that the filename of the package has changed : it is now called servlet-api.jar, not servlet.jar, as it was previously. ( Am I wrong ? Let me know ! )

If you don't know what I'm talking about, just compile the servlet using the following command:

# javac -classpath $CATALINA_HOME/common/lib/servlet-api.jar HelloWorld.java

To avoid having to key in the "classpath" switch every time, just include the servlet-api.jar package inside your CLASSPATH. That is,

export CLASSPATH=$CLASSPATH:$CATALINA_HOME/common/lib/servlet-api.jar

Your servlet should compile cleanly without errors, but if you do, check the syntax in your source code. If you just cut and pasted my code above, you should not get any errors.

If your compile completed successfully, you should see a file called HelloWorld.class inside the same directory. You are now ready to proceed to deploying your first servlet.

4.2. Deploying "HelloWorld"

4.2.1. Creating the directory structure

Before you begin deployment, you will need to create a directory structure under the $CATALINA_HOME/webapps directory that conforms to the servlet specifications. For our example "HelloWorld" servlet, we are going to create a directory called "MyFirst", and we are going to save our "HelloWorld" servlet under that directory.

As tomcat user,

$ cd $CATALINA_HOME/webapps
$ mkdir MyFirst
$ mkdir MyFirst/WEB-INF
$ mkdir MyFirst/WEB-INF/classes
$ mkdir MyFirst/WEB-INF/lib

You should get a directory structure similar to the one below:

Directory structure of a new web application



A little explanation may be helpful at this point. The directory structure is important to the servlet engine. The purposes of the various directories are shown below :

Table 4-1. Web Application Directory Structure

/MyFirst This is the web applications root directory. This is analogous to a directory in the Apache webserver, in that you will put your static HTML files, image files (gif, jpg, etc.) and JavaServer Pages (JSPs) here. If you have an index.html file in this directory, the URL used in a browser to view it is http://hostname.domain.com:8080/MyFirst/index.html. You can create a subdirectory here that stores other HTML files or image files.
/MyFirst/WEB-INF This is where your web application's configuration file web.xml will go.
/MyFirst/WEB-INF/classes This is where the servlets that make up your web application should be copied or saved.
/MyFirst/WEB-INF/lib If your application requires additional support libraries, for example JDBC drivers, they should be copied here.

To illustrate this graphically, our final web application should be laid out as shown below:

Directory structure of a new web application



4.2.2. Creating the Context Descriptor file

This section has been revised and is different from older versions of this document. See this Appendix for an explanation of the changes.

The context descriptor file, according to the Tomcat official documentation, is "used to define Tomcat specific configuration options, such as loggers, data sources, session manager configuration and more".

The file follows an XML syntax, and the name of the file is always the name of the web application, with a .xml extension. So, for this application, called MyFirst, the name of the context descriptor is MyFirst.xml.

Create a file called MyFirst.xml with the following contents:

<!-- MyFirst Context -->
<Context path="/MyFirst" docBase="MyFirst" debug="0" reloadable="true"/>

Save the file into $CATALINA_HOME/conf/Catalina/localhost/ directory.

With much older versions of Tomcat, such as the early Tomcat 3.x series or 4.0.x series, you had to add the <Context> definitions inside server.xml. If you are reading an older version of my article, you may notice that I still described the server.xml method. With Tomcat 5.x, the context descriptor provides a cleaner separation of web application configuration and the main Tomcat server configuration. An added benefit is that web applications deployed in this way do not require a stop and restart of the Tomcat server process. Tomcat should automatically pick it up while it is still running.

4.2.3. Creating a web.xml file for the web application

The file web.xml is sometimes known as a deployment descriptor, and it is basically the configuration file for your web application. In this file, you determine, among other things :

  • the URL of the servlets in your web application

  • the authentication method you wish to use

  • Your filter definitions

For now, we will simply register HelloWorld as a servlet in the web application called MyFirst. We create a new web.xml file with the following contents inside it :

<?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/dtd/web-app_2_3.dtd">

<web-app>

<servlet>
        <servlet-name>HelloWorld</servlet-name>
        <servlet-class>HelloWorld</servlet-class>
</servlet>

<servlet-mapping>
        <servlet-name>HelloWorld</servlet-name>
        <url-pattern>/HelloWorld</url-pattern>
</servlet-mapping>

</web-app>

You will notice that we had to do two things here :

  • Associate the servlet class file (in this case, HelloWorld.class) with a handler (HelloWorld)

  • Define how the servlet is accessed via a URL

In previous releases of Tomcat, if you did not define the <servlet-mapping> element, you could still invoke the servlet by typing http://hostname.domain.com/MyFirst/servlet/HelloWorld. As of version 4.1.18, this option is turned off, and you will have to define your servlet's URI.

In the web.xml file we just created, we told Tomcat that the servlet called HelloWorld.class is referred to as HelloWorld, and that the URL by which this servlet is to be referred to is http://hostname.domain.com:8080/MyFirst/HelloWorld.

4.2.4. Copying the servlets, JSPs and support files to their respective directories

Now we can copy the Java class file that we compiled earlier, into the deployment directory. Because this is a servlet, it will go into $CATALINA_HOME/webapps/MyFirst/WEB-INF/classes directory. There is no need to copy the source file into that directory.

For more complicated deployments, such as servlets that require additional classes, such as JDBC drivers, or libraries, these additional files must be stored inside the /WEB-INF/lib subdirectory of the web application directory. If you wish to make these libraries available to all web applications in Tomcat, save them inside $CATALINA_HOME/common/lib/ directory.

For JavaServer Pages (JSPs), the *.jsp files go in the same directory as the static HTML files, that is, under $CATALINA_HOME/webapps/My_Web_Application/.

4.3. Saying "HelloWorld"

Testing your servlet

We are now ready to test our HelloWorld servlet. Since this is the first servlet we are testing, and we are not really sure what we will see, I strongly advise going into X Windows and opening several terminal windows to display error and information messages, as they occur. Here's how we're going to test and see if our Tomcat deployment can indeed say "HelloWorld" !

  1. Start X Windows and the desktop environment of your choice.

  2. Log in as root

  3. Open 3 terminal windows

  4. In the first terminal window, execute the following commands :

    # cd $CATALINA_HOME/bin
    # ./startup.sh
    
  5. In the second terminal window, execute the following commands :

    # cd $CATALINA_HOME/logs
    # tail -f catalina.out
    

    This will display the messages that Tomcat writes to the log file catalina.out, which is automatically created, if it does not already exist.

  6. In the third terminal window, execute the following commands :

    # cd $CATALINA_HOME/logs
    # tail -f localhost_log.YYYY-MM-DD.txt
    

    substitute YYY-MM-DD with the date (for example : 2003-02-11)

As Tomcat starts up, you can see the messages it writes to the 2 log files ('tail -f' opens the terminal window in a kind of console mode, so you can see events as they happen) . If there are any errors, they will be reflected, sometimes in a very verbose fashion. Take note of the errors, if there are any, and report them on the mailing list, if you cannot solve it yourself.

If Tomcat started without errors (or even if it did have errors), we can test the servlet with our browser.

Checking with a browser

  1. Open Netscape or Mozilla on the local machine

  2. For the URL, key in : http://localhost:8080/MyFirst/HelloWorld

  3. You should see a web page that says, very emphatically, "Hello, Cruel World !". If you see that, then, congratulations ! Your first servlet was successfully deployed !

4.4. Deploying Java Server Pages

This operation is actually quite straightforward. However, from the amount of email I get asking me about this, I thought I'd add a section on this topic.

Deploying JSPs is simpler than deploying web applications. You will still need to do many of the steps outlined above. But you do not need to define your JSP file inside the deployment descriptor, web.xml. If you did not work through the previous example, I strongly urge you to. It will help in your understanding. A summary of steps you need to do to deploy JSPs is shown below:

Deploying JSPs

  1. Install Tomcat

  2. Create a directory structure for your web application

  3. Add a context entry inside server.xml

  4. Create the JSP file

  5. Copy the JSP file to the appropriate directory (i.e. $CATALINA_HOME/webapps/[application_name]/)

For the sake of continuity, I am going to assume you did the previous exercise. To begin, let us create a simple JSP that displays a date and a link to the servlet we created earlier. The source code is shown below:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Hello JSP World!</title>
</head>
<body>
<h1>Hello, JSP World!</h1>

<p>
The time now is : <%= new java.util.Date() %>. 
</p>

<p>
To see the servlet example <a href="HelloWorld">click here</a>.
</p>

</body>
</html>
</programlisting>

After we have created the file, we will save it as index.jsp and we will deploy it by copying it to the web application directory. Recall that the web application directory consists of the following directory structure:

Directory structure of a new web application



We copy the JSP file (and subsequent JSP files) into /opt/tomcat/webapps/MyFirst directory. Not the classes directory -- that is for servlets!

After we copy the file into the directory, we can test it by simply starting up Tomcat and entering the following URL: http://localhost:8080/MyFirst/index.jsp.

You should see a delay, then the page will appear. The delay is caused by Tomcat compiling the JSP, then returning the results to the browser. You can actually pre-compile JSPs to reduce the delay by using the jspc.sh utility in Tomcat. To execute, simply supply the name of the JSP you wish to compile to the utility like so,

# cd $CATALINA_HOME/bin
# ./jspc.sh $CATALINA_HOME/webapps/MyFirst/index.jsp