You are on page 1of 52

How to Install Apache Tomcat

8 (on Windows, Mac OS X,


Ubuntu) and Get Started with
Java Servlet Programming
This practical can be completed in a 3-hour session.
This installation and configuration guide is applicable to Tomcat 7 and 8, and possibly
the earlier versions.
Take note that Tomcat 8 requires JDK 1.7. It will NOT work with JDK 1.6. If your JDK is
below 1.7, upgrade it (See JDK How-To). You can check your JDK version via command
"javac -version".

1. Introduction
1.1 Web Application (Webapp)
A web application (or webapp), unlike standalone application, runs over the Internet.
Examples of webapps are google, amazon, ebay, facebook and twitter.
A webapp is typically a 3-tier (or multi-tier) client-server database application run over
the Internet as illustrated in the diagram below. It comprises five components:
1. HTTP Server : E.g., Apache HTTP Server, Apache Tomcat Server, Microsoft
Internet Information Server (IIS), nginx, Google Web Server (GWS), and others.
2. HTTP Client (or Web Browser) : E.g., Internet Explorer (MSIE), FireFox,
Chrome, Safari, and others.
3. Database : E.g., Open-source

MySQL,

Apache

Derby,

mSQL,

SQLite,

PostgreSQL, OpenOffice's Base; Commercial Oracle, IBM DB2, SAP SyBase, MS SQL
Server, MS Access; and others.
4.

Client-Side

Programs : could be written in HTML Form, JavaScript,

VBScript, Flash, and others.


5.

Server-Side Programs : could be written in Java Servlet/JSP, ASP, PHP, Perl,


Python, CGI, and others.

The typical use-case is:


1.

A user, via a web browser (HTTP client), issues a URL request to an HTTP server
to start a webapp.

2.

A client-side program (such as an HTML form) is loaded into client's browser.

3.

The user fills up the query criteria in the form.

4.

The client-side program sends the query parameters to a server-side program.

5.

The server-side program receives the query parameters, queries the database
and returns the query result to the client.

6.

The client-side program displays the query result on the browser.

7.

The process repeats.

1.2 Hypertext Transfer Protocol (HTTP)

HTTP is an application layer protocol runs over TCP/IP. The IP provides support for
routing and addressing (via an unique IP address for machines on the Internet);
while TCP supports multiplexing via 64K ports from port number 0 to 65535. The

default port number assigned to HTTP is TCP port 80.


HTTP is an asynchronous request-response application-layer protocol. A client
sends a request message to the server. The server then returns a response
message to the client.

HTTP is a pull protocol, a client pulls a page from the server (instead of server
pushes pages to the clients).
The syntax of the message is defined in the HTTP specification.

1.3 Apache Tomcat HTTP Server


Apache Tomcat is a Java-capable HTTP server, which could execute special Java
programs known as Java Servlet and Java Server Pages (JSP). It is the official Reference
Implementation (RI) for Java Servlets and JavaServer Pages (JSP) technologies. Tomcat is
an open-source project, under the "Apache Software Foundation" (which also provides
the most use, open-source, industrial-strength Apache HTTP Server). The mother site for
Tomcat is http://tomcat.apache.org. Alternatively, you can find tomcat via the Apache
mother site @ http://www.apache.org.
Tomcat was originally written by James Duncan Davison (then working in Sun), in 1998,
based on an earlier Sun's server called Java Web Server (JWS). It began at version 3.0
after JSWDK 2.1 it replaced. Sun subsequently made Tomcat open-source and gave it to
Apache.
The various Tomcat releases are:
1.

Tomcat 3.x (1999): RI for Servlet 2.2 and JSP 1.1.

2.

Tomcat 4.x (2001): RI for Servlet 2.3 and JSP 1.2.

3.

Tomcat 5.x (2002): RI for Servlet 2.4 and JSP 2.0.

4.

Tomcat 6.x (2006): RI for Servlet 2.5 and JSP 2.1.

5.

Tomcat 7.x (2010): RI for Servlet 3.0, JSP 2.2 and EL 2.2.

6.

Tomcat 8.x (2013): RI for Servlet 3.1, JSP 2.3, EL 3.0 and Java WebSocket 1.0.

Tomcat is an HTTP application runs over TCP/IP. In other words, the Tomcat server runs
on a specific TCP port in a specific IP address. The default TCP port number for HTTP
protocol is 80, which is used for the production HTTP server. For test HTTP server, you
can choose any unused port number between 1024 and 65535.

2. How to Install Tomcat 8 and Get Started


with Java Servlet Programming
2.1 STEP 1: Download and Install Tomcat
NOTE: At the time of writing, Tomcat 9 is at the alpha stage, not stable release. We shall
install Tomcat 8.0.30.

For Windows
1. Goto http://tomcat.apache.org Downloads Tomcat 8.0 "8.0.{xx}"
(where {xx} is the latest upgrade number) Binary Distributions Core
"ZIP" package (e.g., "apache-tomcat-8.0.{xx}.zip", about 8 MB).
2. Create your project directory, say "d:\myProject" or "c:\myProject". UNZIP the
downloaded file into your project directory. Tomcat will be unzipped into
directory "d:\myProject\apache-tomcat-8.0.{xx}".
3. For ease of use, we shall shorten and rename

this

directory

to

"d:\myProject\tomcat".
Take note of Your Tomcat Installed Directory. Hereafter, I shall refer to the Tomcat
installed directory as <TOMCAT_HOME>.

For Mac OS X
1. Goto http://tomcat.apache.org Download Tomcat 8.0 "8.0.{xx}"
(where {xx} denotes the latest upgrade number) Binary distribution
Core "tar.gz" package (e.g., "apache-tomcat-8.0.{xx}.tar.gz", about 8 MB).
2. To install Tomcat:
1. Goto "~/Downloads", double-click the downloaded tarball (e.g.,
"apache-tomcat-8.0.{xx}.tar.gz") to expand it into a folder (e.g.,
"apache-tomcat-8.0.{xx}").
2. Move the extracted folder

(e.g.,

"apache-tomcat-8.0.{xx}")

to

"/Applications".
3. For ease of use, we shall shorten and rename this folder to "tomcat".
Take note of Your Tomcat Installed Directory. Hereafter, I shall refer to the Tomcat
installed directory as <TOMCAT_HOME>.

For Ubuntu

Read "How to Install Tomcat 8 on Ubuntu". You need to switch between these two
articles.
For academic learning, I recommend " zip" (or "tar.gz") version, as you could simply
delete the entire directory when Tomcat is no longer needed (without running any uninstaller). You are free to move or rename the Tomcat's installed directory. You can
install (unzip) multiple copies of Tomcat in the same machine. For production, it is easier
to use the installer to properly configure the Tomcat.

Tomcat's Directories
Take a quick look at the Tomcat installed directory. It contains the following subdirectories:

bin : contains the binaries; and startup script ( startup.bat for Windows

and startup.sh for Unixes and Mac OS X), shutdown script ( shutdown.bat for Windows
and shutdown.sh for Unix and Mac OS X), and other binaries and scripts.
conf :
contains
the
system-wide
configuration
files,
such

as server.xml, web.xml, context.xml, and tomcat-users.xml.


lib : contains the Tomcat's system-wide JAR files, accessible by all webapps. You

could also place external JAR file (such as MySQL JDBC Driver) here.
logs : contains Tomcat's log files. You may need to check for error messages
here.

webapps : contains the webapps to be deployed. You can also place the WAR
(Webapp Archive) file for deployment here.
work : Tomcat's working directory used by JSP, for JSP-to-Servlet conversion.
temp : Temporary files.

2.2 STEP 2: Create an Environment


Variable JAVA_HOME
(For Windows)
You need to create an environment variable called "JAVA_HOME" and set it to your JDK
installed directory.
1. First, find your JDK installed directory. The default is " c:\Program
Files\Java\jdk1.8.0_{xx}", where {xx} is the upgrade number. Take note of
your JDK installed directory.
2. To set the environment variable JAVA_HOME in Windows 7/8/10: Start "Control
Panel" System Advanced system settings Switch to "Advanced" tab
Environment Variables System Variables "New" In "Variable Name",
enter "JAVA_HOME" In "Variable Value", enter your JDK installed directory as
noted in Step 1.
3. To verify, RE-START a CMD shell (restart needed to refresh the environment)
and issue:
4. SET JAVA_HOME

JAVA_HOME=c:\Program Files\Java\jdk1.8.0_{xx}
JDK installed directory

<== Verify that this is YOUR

(For Mac OS X)
Skip this step. No need to do anything.

2.3 STEP 3: Confi gure Tomcat Server


The Tomcat configuration files are located in the " conf" sub-directory of your Tomcat
installed
directory,
e.g.
"d:\myProject\tomcat\conf"
(for
Windows)
or
"/Applications/tomcat/conf" (for Mac OS X). There are 4 configuration XML files:
1. server.xml
2.
3.

web.xml

4.

tomcat-users.xml

context.xml

Make a BACKUP of the configuration files before you proceed.

Step 3(a) "conf\server.xml" - Set the TCP Port Number


Use a programming text editor (e.g., NotePad++, TextPad for Windows; or gEdit, jEdit
for Mac OS X) to open the configuration file " server.xml", under the "conf" sub-directory
of Tomcat installed directory.
The default TCP port number configured in Tomcat is 8080, you may choose any number
between 1024 and 65535, which is not used by an existing application. We shall choose
9999 in this article. (For production server, you should use port 80, which is preassigned to HTTP server as the default port number.)
Locate the following lines (around Line 69) that define the HTTP connector, and
change port="8080" to port="9999".
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
Java AJP Connector: /docs/config/ajp.html
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL HTTP/1.1 Connector on port 8080
-->
<Connector port="9999" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />

Step 3(b) "conf\web.xml" - Enabling Directory Listing


Again, use a programming text editor to open the configuration file " web.xml", under the
"conf" sub-directory of Tomcat installed directory.
We shall enable directory listing by changing " listings" from "false" to "true" for the
"default" servlet. This is handy for test system, but not for production system for
security reasons.

Locate the following lines (around Line 103) that define the "default" servlet; and
change the "listings" from "false" to "true".
<!-- The default servlet for all web applications, that serves static
-->
<!-- resources. It processes all requests that are not mapped to other -->
<!-- servlets with servlet mappings.
-->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

Step 3(c) "conf\context.xml" - Enabling Automatic Reload


We shall add the attribute reloadable="true" to the <Context> element to enable
automatic reload after code changes. Again, this is handy for test system but not for
production, due to the overhead of detecting changes.
Locate the <Context> start element (around Line 19), and change it to <Context
reloadable="true">.
<Context reloadable="true">
......
......
</Context>

Step 3(d) (Optional) "conf\tomcat-users.xml"


Enable the Tomcat's manager by adding the highlighted lines, inside the <tomcatusers> elements:
<tomcat-users>
<role rolename="manager-gui"/>
<user username="manager" password="xxxx" roles="manager-gui"/>
</tomcat-users>

This enables the manager GUI app for managing Tomcat server.

2.4 STEP 4: Start Tomcat Server


The Tomcat's executable programs and scripts are kept in the " bin" sub-directory of the
Tomcat installed directory, e.g., "d:\myProject\tomcat\bin"
"/Applications/tomcat/bin" (for Mac OS X).

Step 4(a) Start Server

(for

Windows)

or

For Windows
Launch a CMD shell. Set the current directory to " <TOMCAT_HOME>\bin", and run
"startup.bat" as follows:
// Change the current directory to Tomcat's "bin"
// Assume that Tomcat is installed in "d:\myProject\tomcat"
d:
// Change the current drive
cd \myProject\tomcat\bin // Change Directory to YOUR Tomcat's "bin" directory
// Start Tomcat Server
startup

For Mac OS X
I assume that Tomcat is installed in " /Applications/tomcat". To start the Tomcat server,
open a new "Terminal" and issue:
// Change current directory to Tomcat's binary directory
cd /Applications/tomcat/bin
// Start tomcat server
./catalina.sh run

A new Tomcat console window appears. Study the messages on the console. Look out
for the Tomcat's port number (double check that Tomcat is running on port 9999). Future
error messages will be send to this console. System.out.println() issued by your Java
servlets will also be sent to this console.
......
......
xxx xx, xxxx x:xx:xx xx org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["http-bio-9999"]
xxx xx, xxxx x:xx:xx xx org.apache.coyote.AbstractProtocol start
INFO: Starting ProtocolHandler ["ajp-bio-8009"]
xxx xx, xxxx x:xx:xx xx org.apache.catalina.startup.Catalina start
INFO: Server startup in 2477 ms

(Skip Unless ...) Cannot Start Tomcat: Read "How to Debug".


Step 4(b) Start a Client to Access the Server
Start a browser (as HTTP client). Issue URL " http://localhost:9999" to access the Tomcat
server's welcome page. The hostname " localhost" (with IP address of 127.0.0.1) is meant
for local loop-back testing inside the same machine. For users on the other machines
over the net, they have to use the server's IP address or DNS domain name or
hostname in the format of "http://serverHostnameOrIPAddress:9999".

Try issuing URL http://localhost:9999/examples to view the servlet and JSP examples. Try
running some of the servlet examples.
(Optional) Try issuing URL http://localhost:9999/manager/html to run the Tomcat Web
Manager. Enter the username and password configured earlier in tomcat-users.xml.

Step 4(c) Shutdown Server


For Windows
You can shutdown the tomcat server by either:
1. Press Ctrl-C on the Tomcat console; OR
2. Run "<TOMCAT_HOME>\bin\shutdown.bat" script. Open a new "cmd" and
issue:
3. // Change the current directory to Tomcat's "bin"
4. d:
// Change the current drive
5. cd \myProject\tomcat\bin
// Change Directory to YOUR Tomcat's "bin"
directory
6.
7. // Shutdown the server
8. shutdown

For Mac OS X
To shutdown the Tomcat server:
1. Press Control-C (NOT Command-C) on the Tomcat console; OR
2. Run the "<TOMCAT_HOME>/bin/shutdown.sh" script. Open a new "Terminal"
and issue:
3. // Change current directory to Tomcat's bin directory
4. cd /Applications/tomcat/bin
5.
6. // Shutdown the server
./shutdown.sh

WARNING : You MUST properly shutdown the Tomcat. DO NOT kill the cat by pushing
the window's "CLOSE" button.

2.5 STEP 5: Develop and Deploy a WebApp


Step 5(a) Create the Directory Structure for your WebApp

First of all, choose a name for your webapp. Let's call it "hello". Goto Tomcat's "webapps"
sub-directory. Create the following directory structure for you webapp " hello" (as
illustrated):
1.

Under Tomcat's "webapps", create your webapp root directory "hello" (i.e.,
"<TOMCAT_HOME>\webapps\hello").

2.

Under "hello", create a sub-directory "WEB-INF" (case sensitive, a "dash" not an


underscore) (i.e., "<TOMCAT_HOME>\webapps\hello\WEB-INF").

3.

Under "WEB-INF", create a sub-sub-directory " classes" (case sensitive, plural) (i.e.,
"<TOMCAT_HOME>\webapps\hello\WEB-INF\classes").

You need to keep your web resources (e.g., HTMLs, CSSs, images, scripts, servlets, JSPs)
in the proper directories:

"hello": The is called the context root (or document base directory) of your
webapp. You should keep all your HTML files and resources visible to the web users

(e.g., HTMLs, CSSs, images, scripts, JSPs) under this context root.
"hello/WEB-INF": This directory, although under the context root, is not visible to

the web users. This is where you keep your application's web descriptor file
"web.xml".
"hello/WEB-INF/classes": This is where you keep all the Java classes such as
servlet class-files.

You should RE-START your Tomcat server to pick up the hello webapp. Check the
Tomcat's console to confirm that "hello" application has been properly depolyed:
......
INFO: Deploying web application directory D:\myProject\tomcat\webapps\hello
......

You can issue the following URL to access the web application "hello":
http://localhost:9999/hello

You should see the directory listing of the directory " <TOMCAT_HOME>\webapps\hello",
which shall be empty (provided you have enabled directory listing in web.xml earlier).

Step 5(b) Write a Welcome Page

Create the following HTML page and save as " HelloHome.html" in your application's root
directory "hello".
1<html>
2 <head><title>My Home Page</title></head>
3 <body>
4 <h1>My Name is so and so. This is my HOME.</h1>
5 </body>
6</html>
You can browse this page by issuing this URL:
http://localhost:9999/hello/HelloHome.html

Alternatively, you can issue an URL to your web application root " hello":
http://localhost:9999/hello

The server will return the directory listing of your base directory. You can then click on
"HelloHome.html".
Rename "HelloHome.html" to "index.html", and issue a directory request again:
http://localhost:9999/hello

Now, the server will redirect the directory request to " index.html", if the root directory
contains an "index.html", instead of serving the directory listing.
You can check out the home page of your peers by issuing:
http://YourPeerHostnameOrIPAddress:9999/hello
http://YourPeerHostnameOrIPAddress:9999/hello/HelloHome.html
http://YourPeerHostnameOrIPAddress:9999/hello/index.html

with a valid "YourPeerHostnameOrIPAddress", provided that your peer has started his
tomcat server and his firewall does not block your access. You can use command such
as "ipconfig" (Windows), "ifconfig" (Mac OS X and Unix) to find your IP address.

(Skip Unless...) The likely errors are "Unable to Connect", "Internet Explorer
cannot display the web page", and "404 File Not Found". Read "How to Debug" section.

2.6 STEP 6: Write a "Hello-world" Java Servlet


A servlet is Java program that runs inside a Java-capable HTTP Server, such as Apache
Tomcat. A web user invokes a servlet by issuing an appropriate URL from a web browser
(HTTP client).
Before you proceed, I shall assume that you are familiar with Java Programming and
have installed the followings:
1.
2.

JDK (Read "How to install JDK and Get Started").


A programming text editor, such as TextPad or Notepad++ (for Windows); jEdit or
gEdit (for Mac OS X) (Read "Programming Text Editor").

Step 6(a) Write a "Hello-world" Java Servlet


A Java servlet is a Java program that runs inside a HTTP server. A web user invokes a
servlet by issuing a URL from a browser (or HTTP client).
In this example, we are going to write a Java servlet called HelloServlet, which says
"Hello, world!". We will then write a configuration such that web users can invoke this
servlet by
illustrated:

issuing

URLhttp://hostname:port/hello/sayhello from

their

browser,

as

Write the following source codes called "HelloServlet.java" and save it under your
application
"classes"
directory
(i.e.,
"<TOMCAT_HOME>\webapps\hello\WEB-

INF\classes\HelloServlet.java").

This servlet says "Hello",


information, and prints a random number upon each request.

echos

some

request

1// To save as "<TOMCAT_HOME>\webapps\hello\WEB-INF\classes\HelloServlet.java"


2import java.io.*;
3import javax.servlet.*;
4import javax.servlet.http.*;
5
6public class HelloServlet extends HttpServlet {
7 @Override
8 public void doGet(HttpServletRequest request, HttpServletResponse response)
9
throws IOException, ServletException {
10
11
// Set the response MIME type of the response message
12
response.setContentType("text/html");
13
// Allocate a output writer to write the response message into the network socket
14
PrintWriter out = response.getWriter();
15
16
// Write the response message, in an HTML page
17
try {
18
out.println("<html>");
19
out.println("<head><title>Hello, World</title></head>");
20
out.println("<body>");
21
out.println("<h1>Hello, world!</h1>"); // says Hello
22
// Echo client's request information
23
out.println("<p>Request URI: " + request.getRequestURI() + "</p>");
24
out.println("<p>Protocol: " + request.getProtocol() + "</p>");
25
out.println("<p>PathInfo: " + request.getPathInfo() + "</p>");
26
out.println("<p>Remote Address: " + request.getRemoteAddr() + "</p>");
27
// Generate a random number upon each request
28
out.println("<p>A Random Number: <strong>" + Math.random() + "</strong></p>");
29
out.println("</body></html>");
30
} finally {
31
out.close(); // Always close the output writer
32
}
33 }
34}

Step 6(b) Compiling the Servlet


We need the Servlet API to compile the servlet. Servlet API is NOT part of JDK.
Nonetheless, Tomcat provides a copy in <TOMCAT_HOME>/lib/servlet-api.jar. We need to
include this JAR file in the compilation via the -cp (classpath) option.

(For Windows)
// Assume that Tomcat is installed in d:\myProject\tomcat
// Change directory to the source file

d:
cd \myProject\tomcat\webapps\hello\WEB-INF\classes
// Compile
javac -cp .;d:\myProject\tomcat\lib\servlet-api.jar HelloServlet.java
// Note: You need to enclose the jar file in double quotes if the path contains blank
//
e.g., javac -cp .;"d:\Path To\tomcat\lib\servlet-api.jar" HelloServlet.java

(For Mac OS X)
// Assume that Tomcat is installed in /Applications/tomcat
// Change directory to the source file
cd /Applications/tomcat/webapps/hello/WEB-INF/classes
// Compile
javac -cp .:/Applications/tomcat/lib/servlet-api.jar HelloServlet.java

The output of the compilation is " HelloServlet.class". Browse the "classes" folder to make
sure that it is created.

(Skip Unless...) Read "Common Errors in Compiling Java Servlet".


Step 6(c) Confi gure Servlet's Request URL in
"webapps\hello\WEB-INF\web.xml"
A web user invokes a servlet, which is kept in the web server, by issuing a request
URL from the browser. We need to configure this request URL for our HelloServlet.
Create the following configuration file called "web.xml", and save it under
"webapps\hello\WEB-INF" (i.e., "<TOMCAT_HOME>\webapps\hello\WEB-INF\web.xml").

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


2<web-app version="3.0"
3 xmlns="http://java.sun.com/xml/ns/javaee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-ap
6
7 <!-- To save as "hello\WEB-INF\web.xml" -->
8
9 <servlet>
10
<servlet-name>HelloWorld</servlet-name>
11
<servlet-class>HelloServlet</servlet-class>
12 </servlet>
13
14 <!-- Note: All <servlet> elements MUST be grouped together and
15
placed IN FRONT of the <servlet-mapping> elements -->
16
17 <servlet-mapping>
18
<servlet-name>HelloWorld</servlet-name>
19
<url-pattern>/sayhello</url-pattern>

20 </servlet-mapping>
21</web-app>
In the above configuration, a servlet having a class file " HelloServlet.class" is mapped to
request URL "/sayhello" (via an arbitrary servlet-name "HelloWorld"), under this web
application "hello". In other words, the complete request URL for this servlet is
"http://hostname:port/hello/sayhello".
This configuration file, saved under your webapp " hello", is applicable only to this
particular webapp "hello".
RESTART your Tomcat server to refresh the "web.xml" file.
IMPORTANT: For EACH servlet, you need to write a pair of <servlet> and <servletmapping> elements with a common but arbitrary <servlet-name>. Take note that all

the <servlet> elements MUST be grouped together and placed IN FRONT of the <servletmapping> elements.

Step 6(d) Invoke the Servlet


To run this servlet, start a browser, and issue the request URL configured earlier:
http://localhost:9999/hello/sayhello

You shall see the output of the servlet displayed in your web browser.
Refresh the browser, you shall see a new random number upon each refresh. In other
word, the doGet() method of the servlet runs once per request.
Try "View Source" to look at the output received by the web users. Take note that the
web
users
receive
only
the
output
of
the
servlet
(generated
via
the out.println() statements). They have no access to the servlet programs (which may
contain confidential information).
(For Mac OS X's Safari browser) You need to enable "Developer Menu" under the
"Preferences" to enable the "View Source" menu.
<html>
<head><title>Hello, World</title></head>
<body>
<h1>Hello, world!</h1>
<p>Request URI: /hello/sayhello</p>
<p>Protocol: HTTP/1.1</p>
<p>PathInfo: null</p>
<p>Remote Address: 127.0.0.1</p>
<p>A Random Number: <strong>0.3523682325749493</strong></p>
</body>

</html>

(Skip Unless...) The likely errors are "404 File Not Found" and "500 Internal Server
Error". Read "How to debug" Section.

2.7 STEP 7: Write a Database Servlet


This section assumes that you are familiar with "Java database programming" and
"MySQL database server". Otherwise, read "Java Database Program" and "How to Install
MySQL 5 and Get Started".

Step 7(a) Setup a Database on MySQL


Start your MySQL server. Take note of the server's port number. I shall assume that the
MySQL server is running on port 3306 (whereas the Tomcat is running on port 9999).
// For Windows
cd {path-to-mysql-bin} // Check your MySQL installed directory
mysqld --console
// For Mac OS X
// Use graphical control at "System Preferences" -> MySQL

Start a MySQL client. I shall assume that there is a user called " myuser" with password
"xxxx".
// For Windows
cd {path-to-mysql-bin} // Check your MySQL installed directory
mysql -u myuser -p
// For Mac OS X
cd /usr/local/mysql/bin
./mysql -u myuser -p

Run the following SQL statements to create a database called " ebookshop", with a table
called "books" with 5 columns: id, title, author, price, qty.
create database if not exists ebookshop;
use ebookshop;
drop table if exists books;
create table books (
id
int,
title varchar(50),
author varchar(50),
price float,
qty int,
primary key (id));
insert into books values (1001, 'Java for dummies', 'Tan Ah Teck', 11.11, 11);

insert
insert
insert
insert

into
into
into
into

books
books
books
books

values
values
values
values

(1002,
(1003,
(1004,
(1005,

'More Java for dummies', 'Tan Ah Teck', 22.22, 22);


'More Java for more dummies', 'Mohammad Ali', 33.33, 33);
'A Cup of Java', 'Kumar', 55.55, 55);
'A Teaspoon of Java', 'Kevin Jones', 66.66, 66);

select * from books;

Step 7(b) Install MySQL JDBC Driver


You need to download MySQL JDBC driver if you have not done so. Read "Installing the
MySQL JDBC Driver".
(For Advanced Users Only) You could also place the MySQL driver jar-file
"mysql-connector-java-5.1.{xx}-bin.jar" in Tomcat's "lib" directory.

Step 7(c) Write a Client-side HTML Form


Let's write an HTML script to create a query form with 3 checkboxes and a submit
button, as illustrated below. Save the HTML file as querybook.html in your application
root directory <TOMCAT_HOME>\webapps\hello.

1<html>
2<head>
3 <title>Yet Another Bookshop</title>
4</head>
5<body>
6 <h2>Yet Another Bookshop</h2>
7 <form method="get" action="http://localhost:9999/hello/query">
8 <b>Choose an author:</b>
9 <input type="checkbox" name="author" value="Tan Ah Teck">Ah Teck
10 <input type="checkbox" name="author" value="Mohammad Ali">Ali
11 <input type="checkbox" name="author" value="Kumar">Kumar
12 <input type="submit" value="Search">
13 </form>
14</body>
15</html>
You can browse the HTML page by issuing the following URL:
http://localhost:9999/hello/querybook.html

Check a box (e.g., "Tan Ah Teck") and click the "Search" button. An HTTP GET request
will be issued to the URL specified in the <form>'s "action" attribute. Observe the URL
of the HTTP GET request:
http://localhost:9999/hello/query?author=Tan+Ah+Teck

The request consists of two part: a URL corresponding to the " action" attribute of
the <form> tag, and the "name=value" pair extracted from the <input> tag, separated
by a '?'. Take note that blanks are replaced by '+' (or %20), because blanks are not
allowed in the URL.
If you check two boxes (e.g., "Tan Ah Teck" and "Mohammad Ali"), you will get this URL,
which has two "name=value" pairs separated by an '&'.
http://localhost:9999/hello/query?author=Tan+Ah+Teck&author=Mohammad+Ali

You are expected to get an error "404 File Not Found", as you have yet to write the
server-side program.

Step 7(d) Write the Server-side Database Query Servlet


The next step is to write a Java servlet, which responses to the clients request by
querying the database and returns the query results.

1// To save as "<TOMCAT_HOME>\webapps\hello\WEB-INF\classes\QueryServlet.java".


2import java.io.*;
3import java.sql.*;
4import javax.servlet.*;
5import javax.servlet.http.*;
6
7public class QueryServlet extends HttpServlet { // JDK 6 and above only
8
9 // The doGet() runs once per HTTP GET request to this servlet.
10 @Override
11 public void doGet(HttpServletRequest request, HttpServletResponse response)
12
throws ServletException, IOException {
13
// Set the MIME type for the response message
14
response.setContentType("text/html");
15
// Get a output writer to write the response message into the network socket
16
PrintWriter out = response.getWriter();
17
18
Connection conn = null;
19
Statement stmt = null;
20
try {
21
// Step 1: Allocate a database Connection object
22
conn = DriverManager.getConnection(
23
"jdbc:mysql://localhost:3306/ebookshop?useSSL=false", "myuser", "xxxx"); // <==
24
// database-URL(hostname, port, default database), username, password
25
26
// Step 2: Allocate a Statement object within the Connection
27
stmt = conn.createStatement();
28
29
// Step 3: Execute a SQL SELECT query

30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64}

String sqlStr = "select * from books where author = "


+ "'" + request.getParameter("author") + "'"
+ " and qty > 0 order by price desc";
// Print an HTML page as the output of the query
out.println("<html><head><title>Query Response</title></head><body>");
out.println("<h3>Thank you for your query.</h3>");
out.println("<p>You query is: " + sqlStr + "</p>"); // Echo for debugging
ResultSet rset = stmt.executeQuery(sqlStr); // Send the query to the server
// Step 4: Process the query result set
int count = 0;
while(rset.next()) {
// Print a paragraph <p>...</p> for each record
out.println("<p>" + rset.getString("author")
+ ", " + rset.getString("title")
+ ", $" + rset.getDouble("price") + "</p>");
count++;
}
out.println("<p>==== " + count + " records found =====</p>");
out.println("</body></html>");
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
out.close(); // Close the output writer
try {
// Step 5: Close the resources
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
}

Compile the source "QueryServlet.java" into "QueryServlet.class". See the previous


example in Step 6(b) on how to compile a servlet.

Step 7(e) Confi gure the Request URL for the Servlet
Open the configuration file " web.xml" of your application " hello" that you have created
earlier for the HelloServlet, i.e., "<TOMCAT_HOME>\webapps\hello\WEB-INF\web.xml". Add
the lines that are shown in red at the LOCATIONS INDICATED.
1<?xml version="1.0" encoding="ISO-8859-1"?>
2<web-app version="3.0"

3 xmlns="http://java.sun.com/xml/ns/javaee"
4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-ap
6
7 <!-- To save as "hello\WEB-INF\web.xml" -->
8
9 <servlet>
10
<servlet-name>HelloWorld</servlet-name>
11
<servlet-class>HelloServlet</servlet-class>
12 </servlet>
13
14 <servlet>
15
<servlet-name>UserQuery</servlet-name>
16
<servlet-class>QueryServlet</servlet-class>
17 </servlet>
18
19 <!-- Note: All <servlet> elements MUST be grouped together and
20
placed IN FRONT of the <servlet-mapping> elements -->
21
22 <servlet-mapping>
23
<servlet-name>HelloWorld</servlet-name>
24
<url-pattern>/sayhello</url-pattern>
25 </servlet-mapping>
26
27 <servlet-mapping>
28
<servlet-name>UserQuery</servlet-name>
29
<url-pattern>/query</url-pattern>
30 </servlet-mapping>
31</web-app>
The above lines configure the following URL to invoke QueryServlet:
http://localhost:9999/hello/query

Step 7(f) Invoke the Servlet from the Client-Side Form


Issue the following URL to browse the HMTL form " querybook.html" that you have
created earlier:
http://localhost:9999/hello/querybook.html

Select an author (e.g., "Tan Ah Teck") and click the submit button, which activates the
following URL coded in the <form>'s "action" attribute, together with the name=value
pair:
http://localhost:9999/hello/query?author=Tan+Ah+Teck

This URL "/query" triggers QueryServlet. The QueryServlet retrieves the name=value pair
of

"author=Tan+Ah+Teck".

Inside

the QueryServlet,

the

method request.getParameter("author") returns "Tan Ah Teck", which is inserted into the


SQL SELECT command to query the database. The processed query result is then written
to the client as an HTML document.

(Skip Unless...) The likely errors are "404 File Not Found" and "500 Internal Server
Error". Read "How to debug" Section.

2.8 (Advanced) Deploying Servlet


using @WebServlet (Servlet 3.0 on Tomcat 7)
Servlet 3.0, which is supported by Tomcat 7, introduces the @WebServlet annotation,
which greatly simplifies the deployment of servlets. You no longer need to write the
deployment descriptor in "web.xml". Instead, you can use the @WebServlet annotation
to specify the url mapping.
For example, let us write a new servlet called AnotherHelloServlet.java, by modifying
the HelloServlet.java written earlier, with url mapping of "sayhi".
1// To save as "<TOMCAT_HOME>\webapps\hello\WEB-INF\classes\AnotherHelloServlet.java"
2import java.io.*;
3import javax.servlet.*;
4import javax.servlet.http.*;
5import javax.servlet.annotation.*;
6
7@WebServlet("/sayhi")
8public class AnotherHelloServlet extends HttpServlet {
9 @Override
10 public void doGet(HttpServletRequest request, HttpServletResponse response)
11
throws IOException, ServletException {
12
13
// Set the response MIME type
14
response.setContentType("text/html;charset=UTF-8");
15
// Allocate a output writer to write the response message into the network socket
16
PrintWriter out = response.getWriter();
17
18
// Write the response message, in an HTML page
19
try {
20
out.println("<html>");
21
out.println("<head><title>Hello, World</title></head>");
22
out.println("<body>");
23
out.println("<h1>Hello world, again!</h1>"); // says Hello
24
// Echo client's request information
25
out.println("<p>Request URI: " + request.getRequestURI() + "</p>");
26
out.println("<p>Protocol: " + request.getProtocol() + "</p>");
27
out.println("<p>PathInfo: " + request.getPathInfo() + "</p>");
28
out.println("<p>Remote Address: " + request.getRemoteAddr() + "</p>");
29
// Generate a random number upon each request

30
out.println("<p>A Random Number: <strong>" + Math.random() + "</strong></p>");
31
out.println("</body></html>");
32
} finally {
33
out.close(); // Always close the output writer
34
}
35 }
36}
In Line 7, the annotation @WebServlet("/sayhi") is used to declare the URL mapping for
this servlet, i.e., http://localhost:9999/hello/sayhi. There is no need to provide any more
configuration in "web.xml"!

3. How to Debug?
"Everything that can possibly go wrong will go wrong." The most important thing to do is
to find the ERROR MESSAGE!!!

Always...
1.

Refresh your browser using Cntl-F5 (instead of refresh button or simply F5) to
get a fresh copy, instead of from the cache.

2.

You may re-start your Tomcat server. You may also re-start your browser to clear
the cache.

3.

Check your spelling! Always assume that all programs are case-sensitive. Don't
type, copy and paste if possible!

4.

and MOST IMPORTANTLY - Find the ERROR MESSAGE!!!


1.
Check the Error Messages on Tomcat's Console. Most of the error
messages have a few screens of lines. You need to scroll up slowly from the
last line to look for the FIRST LINE of the error messages.
2.

Check the Tomcat's log files, located at " <TOMCAT_HOME>\logs". The


"catalina.yyyy-mm-dd.log" shows the Tomcat's startup messages. Also check
the "localhost.yyyy-mm-dd.log".

b. If things were running fine until the lightning strikes, ask yourself "What have I
changed?"

Cannot Start Tomcat - Tomcat's Console Flashes and Disappears


1.

Try running the script " configtest.bat" (for Windows) or "./configtest.sh" (for Mac

OS X/Linux) to check your configuration files.


2. Check the Tomcat's log files for error messages. The log files are located at
"<TOMCAT_HOME>\logs". The "catalina.{yyyy-mm-dd}.log" shows the Tomcat's
startup messages. Also check the "localhost.{yyyy-mm-dd}.log".
3.

If the error messages indicate that another Tomcat instance is running


(java.net.BindException: Address already in use: JVM_Bind ), kill the Tomcat process
(see below); or try running the "shutdown" script at Tomcat's bin (For Windows,

simply double-click the "shutdown.bat" or issue "shutdown" from CMD. For Mac OS
X, issue "./shutdown.sh" from Terminal.)
4.

If the error messages indicate that another application is running on the Tomcat's
port numbers, then you need to change the Tomcat's port number in server.xml.

You can issue command "netstat -an" to check the status of all the ports.
5. Start the tomcat in the debugging mode by running " catalina debug"
(or ./catalina.sh debug) and type "run" in the "jdb" prompt. Look for the error
messages.

Locating/Killing Tomcat's Process

In windows, start "Task Manager", Tomcat run as a "process" named " java.exe".

You may need to kill the process.


In Mac OS X, start "Activity Monitor". Select "All Processes" and look for

"java.exe".
In Linux/Mac OS X, you may issue " ps aux | grep tomcat" to locate the Tomcat
process. Note down the process ID (pid). You can kill the Tomcat process via " kill
-9 pid".

(Firefox) Unable to Connect


(IE) Internet Explorer cannot display the webpage
(Chrome) Oops! Google Chrome could not connect to ...
(Safari) Safari can't connect to the server
Cause: You are simply not connecting to your Tomcat.
Solution:
1.
2.

Check if your Tomcat server has been started?


Check the hostname and port number, separated by a colon ':', of your URL
(http://localhost:9999/...).

Error 404 File Not Found


Cause: You have connected to your Tomcat. But Tomcat server cannot find the HTML file
or Servlet that your requested.
Solution:
1.

Check your spelling! The path is case-sensitive!

2.

For HTML file with URL http://localhost:9999/xxxx/filename.html:


1.
Open Tomcat's "webapps" directory, check if sub-directory "xxxx" exists. It
is case-sensitive.
2.
Open the "xxxx" directory, check if "filename.html" exists.

b. For Servlet with URL http://localhost:9999/xxxx/servletURL:


1.
Check the Tomcat's console for error message. Your application cannot be
deployed if you make a mistake in editing " web.xml", which triggered many
error messages.

2.

Check the Tomcat console to make sure that your application has been
deployed.

3.
4.

Open Tomcat's "webapps" directory, check if sub-directory "xxxx" exists.


Open the "xxxx" directory, check if sub-sub-directory " WEB-INF"

(uppercase with a dash) exists.


5.
Open the "WEB-INF", check if sub-sub-sub directory "classes" (lowercase,
plural) exists.
6.
Open the configuration file "WEB-INF\web.xml":
1.

Check that servletURL is defined in a <servlet-mapping> tag. Take


note of the name in <servlet-name> tag.

2.

Based on the name noted, look for the


class> tag. Take note of the ServletClassname.

3.

Open "WEB-INF\classes", check if "ServletClassname.class" that you


noted exists (Note: It is " .class", and NOT ".java". You need to compile

matching <servlet-

the ".java" to get the ".class".)

Error 500 Internal Server Error


Error 500 should have triggered many error message in the Tomcat's console. Go to the
Tomcat's console, find the error message. The error message spans tens of lines. You
need to scroll up slowly to look for the first line of the error message. The error message
should tell you the cuase of this error, e.g. SQL syntax error, wrong user/password, etc.
For database servlet, you may check the error messages at "Common Errors in JDBC
Programming".

For "No suitable driver found" (Windows) or NullPointerException (Mac OS X and


Linux): Read Step 7(b) again, again, and again

Apache Tomcat 7
More about the Cat
This article is meant for advanced programmers who is interested to know more about
Tomcat; or using Tomcat for production. For novices, read "How to Install and Get
Started with Tomcat".
The authoritative source of information on Tomcat is the Tomcat's documentation,
available under Tomcat's "webapps\docs" directory. You may also refer to the Java

Servlet, JSP and JSF specifications, as Tomcat is the Reference Implementation for these
technologies.
I shall assume that Tomcat is installed in d:\myproject\tomcat, and shall denote this
directory as <TOMCAT_HOME> or <CATALINA_HOME> - "Catalina" is the codename for
Tomcat 5 and above.

1. Tomcat Architecture and Configuration


1.1 Tomcat's Installed Directory Structure
Tomcat installation provides these directories:

bin : for Tomcat's binaries and startup scripts.


conf : global configuration applicable to all the webapps. The default installation

provides:
o
One Policy File: catalina.policy for specifying security policy.
Two Properties Files: catalina.properties and logging.properties,
Four Configuration XML Files: server.xml (Tomcat main configuration

o
o

file), web.xml (global

web

application

deployment

descriptors), context.xml (global


Tomcat-specific
configuration
options)
and tomcat-users.xml (a database of user, password and role for authentication
and access control).
The conf also contain a sub-directory for each engine, e.g., Catalina, which in turn
contains a sub-sub-directory for each of its hosts, e.g., localhost. You can place the
host-specific
context
information
(similar
to context.xml,
but
named

as webapp.xml for each webapp under the host).


lib : Keeps the JAR-file that are available to all webapps. The default installation
include servlet-api.jar (Servlet), jasper.jar (JSP) and jasper-el.jar (EL). You may also
keep the JAR files of external package here, such as MySQL JDBC driver ( mysqlconnector-java-5.1.{xx}-bin.jar) and JSTL (jstl.jar and standard.jar).

logs :

contains

the

engine

logfile Catalina.{yyyy-mm-dd}.log,

host

logfile localhost.{yyyy-mm-dd}.log,
and
other
application
logfiles
such
as manger and host-manager. The access log (created by the AccessLogValve) is also
kept here.

webapps : the default appBase - web applications base directory of the

host localhost.
work : contains the translated servlet source files and classes of JSP/JSF.

Organized in hierarchy of engine name ( Catalina), host name (localhost), webapp


name, followed by the Java classes package structure.
temp : temporary files.

1.2 Tomcat Architecture

Tomcat is an HTTP server. Tomcat is also a servlet container that can execute Java
Servlet, and converting JavaServer Pages (JSP) and JavaServerFaces (JSF) to Java Servlet.
Tomcat employs a hierarchical and modular architecture as illustrated:

1.3 Main Confi guration File "server.xml"


Tomcat's

main

configuration

file

is

the

"server.xml",

kept

under

the <CATALINA_HOME>\conf directory. The default "server.xml" is reproduced as follows


(after removing the comments and minor touch-ups):
1<?xml version='1.0' encoding='utf-8'?>
2<Server port="8005" shutdown="SHUTDOWN">
3 <Listener className="org.apache.catalina.core.JasperListener" />
4 <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
5 <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
6 <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
7 <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
8
9 <GlobalNamingResources>
10 <Resource name="UserDatabase" auth="Container"
11
type="org.apache.catalina.UserDatabase"
12
description="User database that can be updated and saved"
13
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
14
pathname="conf/tomcat-users.xml" />
15 </GlobalNamingResources>
16
17 <Service name="Catalina">
18 <Connector port="8080" protocol="HTTP/1.1"
19
connectionTimeout="20000"

20
redirectPort="8443" />
21 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
22
23 <Engine name="Catalina" defaultHost="localhost">
24
25
<Realm className="org.apache.catalina.realm.LockOutRealm">
26
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
27
resourceName="UserDatabase"/>
28
</Realm>
29
30
<Host name="localhost" appBase="webapps"
31
unpackWARs="true" autoDeploy="true">
32
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
33
prefix="localhost_access_log." suffix=".txt"
34
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
35
</Host>
36 </Engine>
37 </Service>
38</Server>

Server
Server (Line 2) is top component, representing an instance of Tomcat.It can contains one

or more Services, each with its own Engines and Connectors.


<Server port="8005" shutdown="SHUTDOWN"> ...... </Server>

Listeners
The Server contains several Listeners (Lines 3-7). A Listener listens and responses to
specific events.

The JasperListener enables the Jasper JSP engine, and is responsible for recompiling the JSP pages that have been updated.
<Listener className="org.apache.catalina.core.JasperListener" />

The GlobalResourcesLifecycleListener enables the global resources, and makes


possible the use of JNDI for accessing resources such as databases.
<Listener
className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

Global Naming Resources


The <GlobalNamingResources> element (Line 9-15) defines the JNDI (Java Naming and
Directory Interface) resources, that allows Java software clients to discover and look up
data and objects via a name.
The
default
configuration

defines

JNDI

name

called UserDatabase via

the <Resource> element (Line 10-14), which is a memory-based database for user
authentication loaded from "conf/tomcat-users.xml".

<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>

You can define other global resource JNDI such as MySQL database to implement
connection pooling.

Services
A Service associates one or more Connectors to a Engine. The default configuration
defines a Service called "Catalina", and associates two Connectors: HTTP and AJP to
the Engine.
<Service name="Catalina"> ...... </Service>

Connectors
A Connector is associated with a TCP port to handle communications between
the Service and the clients. The default configuration defines two Connectors:

HTTP/1.1: Handle HTTP communication and enable Tomcat to be an HTTP server.


Clients can issue HTTP requests to the server via this Connector, and receive the
HTTP response messages.
<Connector
port="8080"
redirectPort="8443" />

protocol="HTTP/1.1"

connectionTimeout="20000"

The default chooses TCP port 8080 to run the Tomcat HTTP server, which is different
from the default port number of 80 for HTTP production server. You can choose any
number between 1024 to 65535, which is not used by any application, to run your
Tomcat
server.
The connectionTimeout attribute
define
the
number
of
milliseconds
this connector will wait, after accepting a connection, for the request URI line

(request
message)
to
be
presented.
The
default
is
20
seconds.
The redirect attribute re-directs the SSL requests to TCP port 8443.
AJP/1.3: Apache JServ Protocol connector to handle communication between
Tomcat server and Apache HTTP server.
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

You could run Tomcat and Apache HTTP servers together, and let the Apache HTTP
server handles static requests and PHP; while Tomcat server handles the Java
Servlet/JSP. Read "How To Configure Tomcat to work with Apache".

Containers

Tomcat refers to Engine, Host, Context, and Cluster, as container. The highest-level
is Engine;
while
the
lowest-level
is Context.
Certain
components,
such
as Realm and Valve, can be placed in a container.

Engine
A Engine is the highest-level of a container. It can contains one or more Hosts. You could
configure a Tomcat server to run on several hostnames, known as virtual host.
<Engine name="Catalina" defaultHost="localhost">

The Catalina Engine receives HTTP requests from the HTTP connector, and direct them to
the correct host based on the hostname/IP address in the request header.

Realm
A Realm is a database of user, password, and role for authentication (i.e., access
control). You can define Realm for any container, such as Engine, Host, and Context,
and Cluster.
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm
className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>

The default configuration defines a Realm (UserDatabaseRealm) for the Catalina Engine,
to perform user authentication for accessing this engine.
name UserDatabase defined in theGlobalNamingResources.

It

uses

the

JNDI

Besides the UserDatabaseRealm, there are: JDBCRealm (for authenticating users to


connect to a relational database via the JDBC driver); DataSourceRealm (to connect to
a DataSource via JNDI; JNDIRealm(to connect to an LDAP directory); and MemoryRealm (to
load an XML file in memory).

Hosts
A Host defines a virtual
many Contexts (webapps).

host

under

the Engine,

which

can

in

turn

support

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">

The default configuration define one host called localhost. The appBase attribute defines
the base directory of all the webapps, in this case, <CATALINA_HOME>\webapps. By
default, each webapp's URL is the same as its directory name. For example, the default
Tomcat
installation
provides
four
webapps: docs, examples, hostmanager and manager under the webapps directory. The only exception is ROOT, which
is identified by an empty string. That is, its URL is http://localhost:8080/.
The unpackWARs specifies whether WAR-file dropped into the webapps directory shall be
unzipped. For unpackWARs="false", Tomcat will run the application from the WAR-file
directly, without unpacking, which could mean slower execution.
The autoDeploy attribute specifies whether
the webapps directory automatically.

Cluster

to

deploy

application

dropped

into

Tomcat supports server clustering. It can replicate sessions and context attributes
across the clustered server. It can also deploy a WAR-file on all the cluster.

Valve
A Valve can intercept HTTP requests before forwarding them to the applications, for preprocessing the requests. A Valve can be defined for any container, such as Engine, Host,
and Context, andCluster.
In the default configuration, the AccessLogValve intercepts an HTTP request and creates
a log entry in the log file, as follows:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />

Other valves include:

RemoteAddrValve: which blocks requests from certain IP addresses,

RequestDumperValve: which logs details of the requests,

RemoteHostValve: which blocks request based on hostnames,


SingleSignOn Valve: when placed under a <host>, allows single sign-on to access

all the webapp under the host.

1.4 Other Confi guration


Files: web.xml, context.xml, tomcat-users.xml
[TODO]
They are so many things that you can configured in Tomcat. I describe some of the
configurations that I found useful in this section.

Enabling Directory Listing


When the request URL refers to a directory instead of a file, e.g., http://host:port/hello/,
you can configure Tomcat to serve the directory listing, or a welcome file, or issue error
"404 Page Not Found". Enabling directory listing is handy for test server but NOT desire
for production server (as it reveal the directory structure and expose the entire directory
hierarchy).

Enabling Directory Listing for ALL Webapps


To enable directory listing for all the web applications, you could modify
the <CATALINA_HOME>\conf\web.xml, by changing "listings" from "false" to "true" for the
"default" servlet, as follows:
<!-- The default servlet for all web applications, that serves static
-->
<!-- resources. It processes all requests that are not mapped to other -->
<!-- servlets with servlet mappings.
-->
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>

<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- The mapping for the default servlet -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-====================
Default
Welcome
===================== -->
<!-- When a request URI refers to a directory, the default servlet looks -->
<!-- for a "welcome file" within that directory and, if present,
-->
<!-- to the corresponding resource URI for display. If no welcome file -->
<!-- is present, the default servlet either serves a directory listing, -->
<!-- or returns a 404 status, depending on how it is configured.
-->
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

File

List

The above configuration maps URL "\" (root directory of the web context) (in <urlpattern>) to Java class DefaultServlet (in <servlet-class>) via the common servlet name

of default (in <servlet-name>). We enable directory listing by changing the servlet's


initialization parameter listings to true.
If a user requests for a directory, and the directory listing is enabled and it contains one
of the files in the <welcome-file> list, the welcome file will be served; otherwise, the
directory listing will be served. On the other hand, if a directory request is received and
the directory listing is not enabled, the server returns an error "404 Page Not Found".

Enabling Directory Listing for a particular Webapp


If you wish to allow directory listing of a particular web application only, you could
disable the directory listing in " <CATALINA_HOME>\conf\web.xml" globally, and define the
following <servlet> and<servlet-mapping> in your application-specific WEB-INF\web.xml,
as follows. You need to use another <servlet-name> in place of DefaultServlet.
<servlet>
<servlet-name>DirectoryListing</servlet-name>

<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>DirectoryListing</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

Automatic Servlet Reload


To enable automatic servlet reload (whenever a servlet is re-compiled), you need to
specify <Context reloadable="true">...</Context>,
in
"<CATALINA_HOME>\conf\context.xml" for all web applications, or the <Context> element
in "<CATALINA_HOME>\conf\server.xml" for a particular web application.
The following messages appear on the Tomcat's console if you re-compile a servlet:
XXX X, XXXX XX:XX:XX XX org.apache.catalina.core.StandardContext reload
INFO: Reloading Context with path [/hello] has started
XXX X, XXXX XX:XX:XX XX org.apache.catalina.core.StandardContext reload
INFO: Reloading Context with path [/hello] is completed

Enabling automatic servlet reload is handy during application development, but it


requires significant runtime overhead to listen to the changes, and is not recommended
for production systems. Instead, you could use the "manager" to trigger reloads on
demand.

Setting the Context Root Directory and Request URL of a


Webapp
A server could run many web applications. A webapp is also called a web context.
The context root (or document base directory) refers to the base directory of a webapp.
They are a few ways to configure a context root and its request URL of a webapp:
1. (RECOMMENDED) Create a directory under <CATALINA_HOME>\webapps for your
webapp. A context will be created with request URL set to the name of the
directory. For example, if you create a directory called " hello" under Tomcat's
"webapps".
This application
URL http://host:port/hello.

can

be

accessed

by

web

users

via

To change the request URL of the webapp, create a " context.xml" configuration file,
as follows, and place it under "ContextRoot\META-INF":

<Context path="/yourURLPath" />

2.

Alternatively,

you

can

write

a <Context> element

in <CATALINA_HOME>\conf\server.xml, under the <Host> element. You can specify


both the URL and the base directory. For example,
3.

......

4.

......

5.
6.
7.
8.
9.

<Context path="/ws" docBase="d:/workshop" reloadable="true">


</Context>
</Host>
</Engine>
</Service>
</Server>

In the above example, we define a web context with URL " /ws", with context root
(docBase or document base directory) at "d:\workshop". This application can be
accessed
via
URLhttp://host:port/ws.
Take note that:
o
The configuration creates a mapping from the "URL Path" issued by the

web users to the "document base directory" in the server's file system, where
you store your webapp resources.
Place
the <Context> element
before
the
ending
tag
of

the <Host> element.


Use Unix-style forward

configuration file, instead of Window-style back slash '\'.


The attribute reloadable="true" asks Tomcat to monitor your servlets for

slash '/' as

the directory

separator in

the

changes, and automatically reload the servlets if changes is detected. This is


handy for a development system, but inefficient in a production system.
10. Write a configuration file with a <Context> element and place it under Tomcat's
"conf\Catalina\localhost". For example, suppose we wish to create a webapp with
URL "hello" in base directory "d:\myproject\myHello", create the following file
"hello.xml":
11. <?xml version="1.0" encoding="UTF-8"?>
<Context docBase="D:\myproject\myHello" path="/hello" />

Changing the Default "webapps" Directory


The default directory for deploying web applications is <CATALINA_HOME>\webapps. You
could
change
the
default
by
modifying
the
configuration
file "conf\server.xml" <Host> element's "appBase" attribute as follows:
<Host name="localhost" appBase="webapps"

unpackWARs="true" autoDeploy="true"
xmlValidation="false" xmlNamespaceAware="false">
......
</host>

2. Deploying Webapps
A web context is a single web application (webapp). It is the lowest-level container, that
you can define components such as Realm and Valve. By default, all webapps are kept
under
the<CATALINA_HOME>\webapps directory
(as
configured
in
the <host> element appBase attribute.
A Java webapp may contain many types of files, such as HTML, CSS, Scripts, images,
JSP, servlet, utility classes, external library jar-files. A Java webapp must follow a
strict directory structure as depicted in the Servlet/JSP specifications. This enables
deployment in a Java-capable web server (such as Apache Tomcat and Glassfish). The
resources must be kept in the correct directories and sub-directories.
The URL of a webapp, by default, is the same as the base directory name (or context
root) of the webapp.

2.1 Webapp's Directory Structure

The directory structure of a webapp is as follows:

"ContextRoot": contains the resources that are visible and accessible by the web
clients, such as HTML, CSS, Scripts and images. These resources will be delivered to

the clients as it is. You could create sub-directories such as images, css and scripts,
to further categories the various resources.
"ContextRoot\WEB-INF": This directory, although under the context root, is NOT

visible to the web users. In other words, it is NOT accessible by the clients directly
(for security reason). This is where you keep your application-specific configuration
files such as "web.xml". It's sub-directories contain program classes, source files,

and libraries.
"ContextRoot\WEB-INF\src": Keeps the Java program source files. It is optional but

a good practice to separate the source files and classes to facilitate deployment.
"ContextRoot\WEB-INF\classes": Keeps the Java classes (compiled from the source

codes). Classes defined in packages must be kept according to the Java package
directory structure.
"ContextRoot\WEB-INF\lib": Keeps the libraries (jar-files), which are provided by

other packages, specific and available to this webapp only.


"ContextRoot\META-INF\": This is also a hidden directory, to keep resources and
configurations (e.g., "context.xml") related to the server. In contrast, " WEB-INF" is for
resources related to this web application, independent of the server.

2.2 Webapp-Specifi c Confi guration Files


These are the configuration files specific to a webapp: (a) WEB-INF\web.xml; (b) METAINF\context.xml.

You

can

configure

webapp

in

many

ways:

(a)

Write

a <context> element

in server.xml under <Host> element,


(b) contextRoot\META-INF\context.xml,
and
(c)conf\Catalina\localhost\webapp.xml, and (d) conf\context.xml. See "Setting the Context
Root Directory and Request URL of a Webapp".

2.3 Web Application Deployment Descriptors "web.xml"


The "web.xml" contains the deployment descriptors. There are two sets of web.xml:
1. <CATALINA_HOME>\conf\web.xml: applicable to ALL webapps.
2.

ContextRoot\WEB-INF\web.xml: applicable to the specific web context. It overrides

the global setting, if any.


The complete specification for "web.xml" can be found in the "Java Servlet Specification"
under "Deployment Descriptor".
A sample configuration of a servlet with most of its sub-elements is as follows:
<web-app ......>
......
<servlet>
<icon>
<small-icon>/images/icon.jpg</small-icon>

</icon>
<servlet-name>MyServlat</servlet-name>
<display-name>My Servlet Display Name</display-name>
<description>My Testing Servlet long description</description>
<servlet-class>MyServletClassname</servlet-class>
<init-param>
<param-name>myParmName</param-name>
<param-value>myParmValue</param-value>
</init-param>
<load-on-startup>25</load-on-startup>
</servlet>
......
<servlet-mapping>
<servlet-name>MyServlat</servlet-name>
<url-pattern>/sayhello</url-pattern>
</servlet-mapping>
......
</web-app>

2.4 Deploying a Web Application in a WAR fi le


You could use the JDK's jar utility to "zip" up all the files of a web application to produce
a so-called WAR (Web Application Archive) file for deployment, or distribution.
.... Change current directory to the web application's context root
contextRoot> jar cvf test.war .

Drop the test.war into <CATALINA_HOME>\webapps. A context called test will be created
automatically. You can access the web application via URL http://host:port/test.
Tomcat

actually

unpacks

the test.war into

"test"

directory

in <CATALINA_HOME>\webapps. You need to remove this directory, if you reload a new


version.

3. Running Tomcat
3.1 Tomcat's Manager
References:
1.
2.

"Tomcat Web Application Manager How To" @ "webapps/docs/html-managerhowto.html".


"Tomcat Manager App How-To" @ "webapps/docs/manager-howto.html".

Tomcat "manager" webapp allows you to deploy a new web application; start, stop,
reload or un-deploy an existing one, without having to shut down and restart the server,
in a production environment.

To enable Tomcat's manager, edit "<CATALINA_HOME>\conf\tomcat-users.xml" to


include a role called " manager-gui" and a user with this role. You may also assign other
roles, such as admin-gui for accessing the Tomcat "Host Manager".
<role rolename="manager-gui" />
<role rolename="manager-status" />
<role rolename="manager-script" />
<role rolename="manager-jmx" />

<role rolename="admin-gui" />


<role rolename="admin-script" />

<user username="mymanager" password="xxxx" roles="manager-gui, admin-gui"/>

To invoke manager web application, use http://localhost:8080/manager/html. You can use


Tomcat's manager to:
1.

List all webapps.

2.

Start/Stop/Reload a particular webapp.

3.

Deploy a new webapp remotely, and undeploy a webapp without restarting the
container.

4.

Terminate (or Invalidate) sessions - a session has a pre-set expiry time (e.g., 30
sec).

5.

Analyze memory leaks.

6.

View JVM status and Server status.

Tomcat 7 provides separate manager roles for the GUI ( manager-gui), status (managerstatus),

scripting (manager-script) and JMX proxy (manager-jmx), defined in


"webapps/manager/WEB-INF/web.xml". This allows for fine-grained access control to
management tasks.

manager-gui - Access to the HTML "web" interface, via:


http://{host}:{port}/manager/html

manager-status - Access to the "Server Status" page only, via:


http://{host}:{port}/manager/status

manager-script - Access to the "plain-text" interface, and to the "Server Status"

page, via command in the form of:

http://{host}:{port}/manager/text/{command}?{parameters}

// Examples
http://{host}:{port}/manager/text/list

// List all webapps

http://{host}:{port}/manager/text/deploy?path=/testapp // Deploy webapp

manager-jmx - Access to JMX proxy interface and to the "Server Status" page, via:
http://{host}:{port}/manager/jmxproxy/?{command}={parameter}

For security reason, a user should NOT be given more than one of the following
roles: manager-gui, manager-script, and manager-jmx.

Tomcat's "Administration Tool"


The Tomcat "Adminstrative Tool" (or "Administrator Console") has been removed since
Tomcat 6. Use JMX manager instead.

3.2 Automatic Startup at Boot-time


(Windows) Running Tomcat as a Windows Service
You need to download the Windows-specific version of Tomcat (from Tomcat's download,
choose 32-bit or 64-bit Windows' zip version, e.g., apache-tomcat-7.0.{xx}-windowsx86.zip).
Read
"Windows
service
How-To"
in
the
Tomcat
(<CATALINA_HOME>\webapps\docs\windows-service-howto.html ).

documentation

In a production environment, it is more convenient to run Tomcat as a service, so that it


can start automatically whenever the system is started (or re-start automatically after
an unexpected interruption).
To install Tomcat as a service, start a CMD shell (with administrator right) and run
the <CATALINA_HOME>\bin\service.bat with install option:
... Change directory to <CATALINA_HOME>\bin ...
<CATALINA_HOME>\bin> service install
Installing the service 'Tomcat7' ...
......
The service 'Tomcat7' has been installed.

The Tomcat service called "Apache Tomcat 7" is installed and will start automatically
whenever the system is started. Check the "Services" under "Control Panel"
"Administrative Tools".
A GUI application called Tomcat7w is available for monitoring and configuring Tomcat
services. Launch Tomcat7w:
<CATALINA_HOME>\bin> Tomcat7w

You could put the Tomcat icon in the system tray via the MS (Monitor Service) option:

<CATALINA_HOME>\bin> Tomcat7w //MS//

You can start/stop the Tomcat service now via:


1.

Tomcat7w;

2.

"Control Panel" "Administrator Tools" "Services" "Apache Tomcat 7"


"Start";

3.

From CMD shell, Issue "net" command:

4.
5.
6.
7.
8.
9.
10.

prompt> net start tomcat7


The Apache Tomcat 7 service is starting..
The Apache Tomcat 7 service was started successfully.
......
......
prompt> net stop tomcat7
The Apache Tomcat 7 service is stopping..
The Apache Tomcat 7 service was stopped successfully.

To
uninstall
Tomcat
the <CATALINA_HOME>\bin\service.bat with remove option:

Service,

run

<CATALINA_HOME>\bin> service remove


The service 'Tomcat7' has been removed

You can also use Microsoft Management Console (MMC) to manage the services: Go to
"Start" Run enter "services.msc".
A flip side of running Tomcat as a service is you need to read the error messages
from <CATALINA_HOME>\logs instead of the Tomcat console.

(Linux and Mac OS) Automatic Startup on Reboots


To start Tomcat automatically when the machine boots up, you need to create a init
script in /etc/init.d, e.g., /etc/init.d/tomcat, as follows:
#!/bin/sh
# Tomcat init script for Linux.
#
JAVA_HOME={path-to-java-installed-directory}
CATALINA_HOME={path-to-Tomat-installed-directgory}
export JAVA_HOME CATALINA_HOME
exec $CATALINA_HOME/bin/catalina.sh $*

Save the script as "tomcat" in /etc/init.d.


$ cd /etc/init.d
$ sudo chown root.root tomcat // change owner to user root, group root

$ sudo chmod 755 tomcat

// change mode u+rwx, g+rx, a+rx

You can start|stop|restart Tomcat via:


$ service tomcat start|stop|restart

3.3 Tomcat's Startup Script


To start tomcat server, you could invoke the batch file " startup.bat" (for Windows) or
"startup.sh"
(for
Linux/Mac)
(in
directory
"<CATALINA_HOME>\bin",
where <CATALINA_HOME> refers to the Tomcat installed directory). The " startup.bat|
startup.sh" invokes "catalina.bat start|catalina.sh start".

Alternatively, you could call the " catalina.bat|catalina.sh" directly, which provides more
options of starting Tomcat. Enter "catalina" to view the options:
<CATALINA_HOME>/bin> catalina
Using CATALINA_BASE: D:\xxx\tomcat7.0.{xx}
Using CATALINA_HOME: D:\xxx\tomcat7.0.{xx}
Using CATALINA_TMPDIR: D:\xxx\tomcat7.0.{xx}\temp
Using JRE_HOME:
d:\xxx\jdk1.6
Usage: catalina ( commands ... )
commands:
debug
Start Catalina in a debugger
debug -security Debug Catalina with a security manager
jpda start
Start Catalina under JPDA debugger
run
Start Catalina in the current window
run -security
Start in the current window with security manager
start
Start Catalina in a separate window
start -security Start in a separate window with security manager
stop
Stop Catalina
configtest
Run a basic syntax check on server.xml
version
What version of tomcat are you running?

Study the source codes of " catalina.bat|catalina.sh". Take note that the environment
variable JAVA_HOME is needed in this script.
The other scripts provided are:

shutdown.bat|shutdown.sh: for shuting down the Tomcat server.

configtest.bat|configtest.sh: for checking the configuration file server.xml, same

as "catalina configtest".
version.bat|version.sh: for displaying the versions, same as "catalina version".
digest.bat|digest.sh: making password hash and encrypting password.
Internal

used: setclasspath.bat|setclasspath.sh, cpappend.bat (classpath

append), tool-wrapper.bat|tool-wrapper.sh, daemon.sh.

4. Security
4.1 Realm and User Authentication in Tomcat

References:
1.

"Realm

Configuration

HOW-TO"

(@

"<CATALINA_HOME>\webapps\docs\realm-

howto.html").

2.

"Java EE 5 Tutorial", Part IV "Services", Chapters 28-30 on Security.

In Information Security:

Access control deals with identifying which resources require protection, and

which users (roles) are authorized to access the protected resources.


Authentication deals with verifying users' credential, i.e., ensuring the user is
"who he said he is". User's credential is typically provided in the form of
username/password and possibly IP address (hostname). Other means include

biometrics (finger-print, face recognition, retina) and digital certificates.


Confidentiality deals with the encryption of the transmitted data over the

network. This is often carried out via employing HTTP over SSL (Secure Socket
Layer), known as HTTPS.
Message Integrity ensures that messages are not tempered during transmission.

This is done via message digest or hash.


Non-repudiation: If he/she has sent a message, he/she cannot deny. This is done
via digital certificate and public/private keys.

Security can be managed by the webapps themselves (called applicationmanaged security) or via the Tomcat container (called container-managed security). In
container-managed security, security is handled by the server. The server-side programs
(servlets, JSPs) do not need any security-aware code. That is, the security control is
totally transparent to the server-side programs. This section shall deal with containermanaged security for access control and authentication.
In Tomcat, a user is identified via username/password. A user is assigned role(s) (e.g.,
manager, admin, user, etc). Tomcat grants access for webapps to role(s), instead of
individual users.
A realm is a collection of usernames/passwords and roles. Tomcat supports the following
types of realms:

UserDatabaseRealm: kept in a XML file " conf\tomcat-users.xml", accessed via JDNI

(Java Naming and Directory Interface).


JDBCRealm: kept in a relational database such as MySQL, accessed via JDBC.
others: JNDIRealm (uses

LDAP directory), JAASRealm (Java

Authentication

and

Authorization Service).
You
can
used
the <realm> element
to
configure
a
realm
in
"conf\server.xml". <realm> element can be placed in <engine>, <host>, or <context>,
which determines the scope of the realm: all virtual hosts under the engine, a particular
host, or a particular web application.

4.2 UserDatabaseRealm
UserDatabaseRealm stores user information in a XML file and accessed via JNDI (Java

Naming

and

Directory

Interface).

By

default,

the

XML

file

is

"<CATALINA_HOME>\conf\tomcat-users.xml".UserDatabaseRealm is loaded into memory


from the specified file, and kept in memory until Tomcat is shut down.
Tomcat
provide
a
JSP
example
called
"FORM
Authentication"
(@
http://localhost:8080/examples/jsp/security/protected/index.jsp"),
which
uses UserDatabaseRealm. Let us study this example. But before we get into the codes,
let's look at the Tomcat's configurations.

"conf\server.xml"
You can specify the type of realm to be used via <Realm> element in server.xml. In this
case, UserDatabaseRealm. The <Realm> is defined within the <Engine> elements, and
thus applicable to all the virtual hosts and webapps, under this server.
To specify the file used in UserDatabaseRealm, a JDNI resource named "UserDatabase" is
defined, which maps to the file "conf\tomcat-users.xml".
<Server ...... >
<!-- Global JNDI resources -->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users -->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Engine name="Catalina" defaultHost="localhost">
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase" />
</Realm>
<Host name="localhost" ......
......
</Host>
</Engine>
</Service>
</Server>

"conf\tomcat-users.xml"
Recall that a user is identified via username/password. A user is assigned role(s).
Accesses for web applications are granted to role(s) instead of individual users. " Tomcat-

users.xml" contains the following roles and username/password, but commented-out.

Uncomment them for testing the example. Two roles, tomcat and role1, and three
users, tomcat, role1 and both are defined.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<tomcat-users>
<role rolename="tomcat" />
<role rolename="role1" />

<user username="tomcat" password="tomcat" roles="tomcat" />


<user username="both" password="tomcat" roles="tomcat,role1" />
<user username="role1" password="tomcat" roles="role1" />
</tomcat-users>

Take note that the passwords are stored in clear text, which is not really desirable.

"ContextRoot\WEB-INF\web.xml"
For Tomcat's webapp called " examples", the security roles are defined using <securityconstraint> element in "webapps\examples\WEB-INF\web.xml" as follows. The URL
patterns/jsp/security/protected/* are
of tomcat and role1 only.

accessible

by

users

<web-app ......>
......
<security-constraint>
<display-name>Example Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<!-- Define the context-relative URL(s) to be protected -->
<url-pattern>/jsp/security/protected/*</url-pattern>
<!-- If you list http methods, only those methods are protected -->
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
</web-resource-collection>
<auth-constraint>
<!-- Anyone with one of the listed roles may access this area -->
<role-name>tomcat</role-name>
<role-name>role1</role-name>
</auth-constraint>
</security-constraint>

having

roles

<!-- Default login configuration uses form-based authentication -->


<login-config>
<auth-method>FORM</auth-method>
<realm-name>Example Form-Based Authentication Area</realm-name>
<form-login-config>
<form-login-page>/jsp/security/protected/login.jsp</form-login-page>
<form-error-page>/jsp/security/protected/error.jsp</form-error-page>
</form-login-config>
</login-config>
<!-- Security roles referenced by this web application -->
<security-role>
<role-name>role1</role-name>
</security-role>
<security-role>
<role-name>tomcat</role-name>
</security-role>

4.3 HTML FORM-based Authentication Method


The example uses HTML FORM-based authentication method, defined in element <loginconfig>.
All
accesses
to
the
protected
URLs
(http://localhost:8080/examples/jsp/security/protected/*)
will
be
redirected
to
the login.jsp page (defined in <form-login-page>), which prompts user for the credential.
For
example,
if
a
user
requests
forhttp://localhost:8080/examples/jsp/security/protected/index.jsp,
the login.jsp will
be
displayed.
The login.jsp page contain a html <form> (thus called FORM-based authentication):
<html>
<head><title>Login Page for Examples</title></head>
<body>
<form method="POST" action='<%= response.encodeURL("j_security_check") %>' >
Username:<input type="text" name="j_username">
Password:<input type="password" name="j_password">
<input type="submit" value="Log In">
</form>
</body>
</html>

The

login

page

submits

the

username

and

password

in

parameters j_username and j_password to j_security_check. <input type="password" ...> is


used
for
password
text
field,
which
displays
the
password
as
*'s.
The response.encodeURL(URL) encodes the URL j_security_check by including the session
ID if URL-rewriting is used for session tracking; it returns the URL unchanged if cookie is

used. For robust session tracking, all URLs emitted by server-side programs (servlet/JSP)
should be run through this method.
If login fails, user will be redirected to error.jsp page, as follows,
<html>
<head><title>Error Page For Examples</title></head>
<body>
Invalid username and/or password, please try again
<a href='<%= response.encodeURL("index.jsp") %>'>again</a>.
</body>
</html>

If login succeeds, the user will get the page he requested for. Study the
"examples\jsp\security\protected\index.jsp" source.

To logoff, terminate the current session via session.invalidate().

You

can

use request.getRemoteUser() to

get

the

authenticated

login

username; request.getUserPrincipal() to get a java.security.Principal object containing


the name of the current authenticated user; request.isUserInRole(role) to check if the
authenticated user is included in the specified role.

4.4 HTTPS
In FORM-based authentication, the username/password are sent in clear text, and
susceptible to eavesdropping. Hence, it is important to encrypt the transport by turning
on SSL (HTTPS). Read "Tomcat with SSL" on how to setup Tomcat with SSL.
To
enforce
user
to
use
secure
transport
(HTTPS),
add
a <transportguarantee>CONFIDENTIAL</transport-guarantee>,

inside

the <security-constraint>,

follows:
<security-constraint>
<display-name>Example Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/jsp/security/protected/*</url-pattern>
......
</web-resource-collection>
<auth-constraint>
<role-name>tomcat</role-name>
......
</auth-constraint>
<!-- must use SSL for secure transport -->

as

<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>

All
accesses
to
HTTP
at
port
8080
(e.g.,
http://localhost:8080/examples/jsp/security/protected/index.jsp) will be redirected to
HTTPS
at
port
8443
https://localhost:8443/examples/jsp/security/protected/index.jsp).

(e.g.,

4.5 HTTP BASIC Authentication


HTTP defines two access authentication schemes to request for username/password:
Basic and Digest. Read "HTTP Authentication".
To use BASIC authentication, change the <login-config>'s <auth-method> to BASIC.
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Basic Authentication Area</realm-name>
<!-- Removed, no applicable for BASIC authentication
<form-login-config>
<form-login-page>/jsp/security/protected/login.jsp</form-login-page>
<form-error-page>/jsp/security/protected/error.jsp</form-error-page>
</form-login-config>
-->
</login-config>

In BASIC authentication, Tomcat uses the HTTP Basic Authentication to ask for username
and password. Try http://localhost:8080/examples/jsp/security/protected/index.jsp, you will
be prompted for username/password automatically. There is no redirect to login.jsp and
no need to write the login.jsp.
Again, the HTTP Basic Authentication sends the username and password in clear text
(password is encoded in Base64, but not encrypted). It is totally insecure, unless you
use a secure transport (HTTPS) or VPN (Virtual Private Network).
The Tomcat's webapp manager (under webapps/manager) uses BASIC authentication.

4.6 HTTP DIGEST Authentication


To use DIGEST authentation, change the <login-config>'s <auth-method> to DIGEST. In
DIGEST authentication, Tomcat uses HTTP Digest Authentication Scheme to ask for
username/password. Instead of sending password in clear text, the digest of password is
send to the server. Although DIGEST authentication is more secure than BASIC
authentication, HTTPS is much more secure.
<login-config>
<auth-method>DIGEST</auth-method>

<realm-name>Digest Authentication Area</realm-name>


</login-config>

4.7 JDBCRealm
UserDatabaseRealm is not meant for serious production environment, as it is hard to

maintain. JDBCRealm is more appropriate.


In JDBCRealm, user information is kept in a relational database, such as MySQL,
accessed via JDBC, instead of an XML file. The information can be secured thruough
proper database security.

Setting up Database
We shall set up our user database in MySQL. Read "How to Install MySQL and Get
Started" if you are new to MySQL.
The following script can be used to set up the user database. Two tables are required:
a users table containing username and password, and a user_roles containing username
and the role assigned.
create database tomcat_users;

use tomcat_users;

create table users (


username varchar(15) not null,
password varchar(15) not null,
primary key (username)
);

create table user_roles (


username varchar(15) not null,
role

varchar(15) not null,

primary key (username, role)


);

insert into users values


('tomcat', 'tomcat'),
('both', 'tomcat'),
('role1', 'tomcat');

insert into user_roles values


('tomcat', 'tomcat'),
('role1', 'role1'),
('both', 'tomcat'),
('both', 'role1');

JDBC Driver
Next, copy the MySQL's JDBC driver ("mysql-connector-java-5.1.{xx}-bin.jar") into
Tomcat's lib ("<CATALINA_HOME>\lib"). Read "How to Install MySQL and Get Started"

"conf\server.xml"
Again, the realm is defined in server.xml via a <Realm> element. In this case,
a JDBCRealm, with a connectionURL providing a MySQL database connection.
<Realm className="org.apache.catalina.realm.JDBCRealm"
driverName="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:{port}/tomcat_users"
connectionName="{dbuser}"
connectionPassword="{dbpassword}"
userTable="users" userNameCol="username" userCredCol="password"
userRoleTable="user_roles" roleNameCol="role" />

Replace
the {port} with
your
MySQL
server
port
and {dbuser} and {dbpass} with an authorized MySQL username/password.

number,

"ContextRoot\WEB-INF\web.xml"
Same as UserDatabaseRealm.

Authentication Methods
Same

as UserDatabaseRealm,

you

can

use FORM, BASIC or DIGEST authentication

method.

Testing
You need to start MySQL server before starting the Tomcat Server.

4.8 Single Login


By default, each protected webapp would request for login during the first access. You
can enable single login to all webapps under the host by uncommenting the single-login
valve, as follows:
<Host ......>
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
</Host>

4.9 Tomcat with SSL

SSL (Secure Socket Layer), allows web browsers and web servers to communicate over
a secured (encrypted) connection. Tomcat provides built-in support for SSL.
Read:

"SSL

Configuration

How-to"

of

Tomcat

Documentation

"<CATALINA_HOME>\webapps\docs\ssl-howto.html".

"keytool - Key and Certificate Management Tool" @ JDK documentation.

The steps to turn on SSL support are:

Step 1: Check your JDK version. Tomcat's SSL uses Java Secure Socket Extension
(JSSE), which has been integrated into JDK since 1.4.
Step 2: Prepare the Tomcat's server certificate, using the JDK's Key and Certificate
Management Tool called "keytool" (in "<JAVA_HOME>\bin" ), as follows:
> keytool
... display the help menu ...
// Generate a self-signed certificate for Tomcat
>
keytool
-genkey
-alias
tomcat
-keyalg
RSA
-keystore
{TOMCAT_HOME}\conf\.keystore
Enter keystore password: xxxxxxxx
Re-enter new password: xxxxxxxx
What is your first and last name?
[Unknown]:
What is the name of your organizational unit?
[Unknown]:
What is the name of your organization?
[Unknown]:
What is the name of your City or Locality?
[Unknown]:
What is the name of your State or Province?
[Unknown]:
What is the two-letter country code for this unit?
[Unknown]:
Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
correct?
[no]: y
Enter key password for <tomcat>
(RETURN if same as keystore password):

The "-genkey" option is used to generate a public-private key pair. The public key
is wrapped into an X.509 v1 self-signed certificate. The certificate and the private

key are stored in a new keystore entry identified by the alias. In our case, the alias
name must be "tomcat".
The "-keyalg" option specifies the key generation algorithm. RSA public key
algorithm is used in this case.

The "-keystore" option specifies the name and location of the key store file.
The password for alias tomcat must be the same as the keystore (i.e., hit enter

for the last question).


Step 3: Enable SSL support for Tomcat. SSL is built into Tomcat. The Tomcat's
configuration file commented out the SSL configuration directive. Uncomment them by
removing the <!-- and --> around the SSL Coyote HTTP/1.1 Connector as follows:
<!-- Define a SSL HTTP/1.1 Connector on port 8443
This connector uses the JSSE configuration, when using APR, the
connector should be using the OpenSSL style configuration
described in the APR documentation -->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
SSLEnabled="true" maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="{TOMCAT_HOME}\conf\.keystore"
keystorePass="passwordOfKeyStore" />

Note that the SSL (or HTTPS) is running on port 8443 instead of its default port number
443.
Add in the keystoreFile and keyStorePass attributes. The keystoreFile attribute specified
the location of the keystore file. The keyStorePass provides the password for accessing
the keystore file.
Step 4: Start your tomcat (run "<CATALINA_HOME>\bin\startup.bat"). After that, start a
web browser and issue an HTTPS request as follows:
https://localhost:8443

5. Clustering
[TODO]

5.1 Confi guring Virtual Hosts


To set up a virtual host called "www.mytest.com" (suppose that you have registered this
hostname with at static IP address). Include the following <Host> element
in server.xml under the Engine Catalina:
<Engine name="Catalina" >
<Host name="localhost .....>
......
</Host>
<Host name="www.mytest.com" appBase="webapps_mytest.com"
unpackWARs="true" autoDeploy="true" >
<Alias>mytest.com</Alias>
<Valve className="org.apache.catalina.valves.AccessLogValve"

directory="logs"
prefix="mytest.com_access_log." suffix=".log"
pattern="%h %l %u %t &quot;%r&quot; %s %b"
resolveHosts="false" />
</Host>
</Engine>

The above lines configure a virtual host with hostname " www.mytest.com", with
webapps base directory at "<CATALINA_HOME>\webapps_mytest.com". We also define a
alias
called
"mytest.com".
That
is,
this
host
can
be
accessed
via http://www.mytest.com:port or http://mytest.com:port. We also define a Valve, which
intercepts the request message to write a log entries (similar to localhost).
Next:
1.

Create a directory "webapps_mytest.com" under <CATALINA_HOME>, according to


the appBase.

2.

Create a web application called ROOT, by creating a directory ROOT under the
"webapps_mytest.com". Recall that ROOT was configured with an empty string URL.

In other words,http://www.mytest.com:port/ accesses the ROOT application.


3. Create a directory "www.mytest.com" under "conf\Catalina".
4.

Write
a
welcome
page
"webapps_mytest.com\ROOT".

called

"index.html"

5.

<html>

6.

<head><title>Testing Virtual Host</title></head>

7.

<body>

8.
9.

<h1>It's work on virtual host</h1>


</body>

and

save

it

in

</html>

To test the virtual host, without registering the hostname with an ISP, edit
"C:\Windows\System32\drivers\etc\hosts"
administrative authority):

to

include

the

following

lines

(required

127.0.0.1 www.mytest.com
127.0.0.1 mytest.com

These lines maps host names www.mytest.com and mytest.com to IP address 127.0.0.1,
which is the localhost. As the IP software checks the host file before asking Domain
Name Service (DNS) to resolve a host name, you willl be able to test your virtual host.
Now, you are ready to test the virtual hosts. Start the Tomcat server and issue these
URL:

http://www.mytest.com:8080
http://mytest.com:8080
http://www.mytest.com:8080/
http://mytest.com:8080/
http://www.mytest.com:8080/index.html
http://mytest.com:8080/index.html

5.2 Tomcat Host Manager for Clustering and Admin


Roles
Reference:

"Clustering/Session

Replication

HOW-TO"

" webapps/docs/cluster-

howto.html".

The Tomcat "host-manager" webapp allows you to manage Tomcat clusters. To


access host-manager, you need to define a user with admin role.
The admin role has been separated out as admin-gui and admin-script, in Tomcat 7, as
defined in webapps/host-manager/WEB-INF/web.xml.
The "Host Manager" web application can be accessed via http://{host}:{port}/hostmanager/html.

You might also like