Tomcat 6.0 Developer’s Guide
Current books on Tomcat are primarily focused on the application deployer
or administrator. As a result, they invariably focus on the issues related to
managing a Tomcat installation, configuring the runtime environment, and on
deploying web applications.
On the other hand, while books on servlet programming are targeted at Java web
developers, they often provide a container-agnostic view of the servlet specification.
Tomcat is often a bit player in these books and has very few speaking lines.
This book fills the void between these two approaches.
It will take you on a guided tour of a living implementation of an industrial-strength
Along the way, you will learn how various elements of the Servlet 2.5 specification as
well as how the HTTP RFCs are implemented.
By the end of your journey, you will have acquired specialist grade skills in a range of
technologies that contribute to the arena of Java server-side development.
This book intended to provide Tomcat administrators, deployers, and developers an
introduction into the internal workings of the Tomcat servlet container.
At the same time, it provides Java web programmers with a deep appreciation of the
Servlet APiby exploring its reference implementation—the Tomcat container.
While this book provides you with the conceptual background of all that is necessary to
take your skills to the next level, it assumes that the reader has a general understanding of
the Java programming language and Java web programming.
What This Book Covers
Chapter 1—Introduction to Tomcat introduces you to the Tomcat container and provides
you with the tools necessary to begin to take it apart. The key objective of this chapter is
to allow you to make a current source distribution of Tomcat active in a development
environment (Eclipse Galileo) so that you can trace the path that a request takes through
the container’s code.
Chapter 2—Servlet APiOverview provides the prerequisite information necessary to
navigate the remainder of the book. It describes the Java Enterprise Edition Platform, the
HTTP protocol, and the Servlet API, and serves as a refresher for those who are already
familiar with Java EE web development.
Chapter 3—Servlet Container Overview introduces the reader to the Tomcat container.
This is the 10,000 foot overview of the container that provides a backdrop to the chapters
that follow. All the components of Tomcat are described with just enough detail, so as
not to overwhelm the reader with too much information, too early in the process.
Chapter 4—Starting up Tomcat takes a closer look at the startup process for Tomcat. This
is also where you will be first introduced to the Apache Digester project—a key
component that we will revisit in later chapters. The chapter ends with an example that
demonstrates how a web application can be deployed to a dissected Tomcat container
living within an Integrated Development Environment.
Chapter 5—The Server and Service Components discusses the Server component and
investigates one of its key services—an implementation of the Java Naming and
Directory Interface (JNDI) API. We are also introduced to the Lifecycle interface
that almost every component within Tomcat implements in order to participate in a
standardized event based listener mechanism. To show JNDiin action, our example
considers connecting to a MySQL database to retrieve data.
Chapter 6—The Connector Component introduces our first Tomcat luminary, the Coyote
Connector. We take a closer look at the standard Java I/O implementation of an HTTP
connector. In this chapter, we get a closer look at socket programming, advanced
elements of the HTTP protocol, and the internals of the request processing mechanism.
Chapter 7—The Engine Component describes the first request processing ‘Container’
within Tomcat and gives us an inkling of things to come. We are also introduced to the
Pipeline and its Valves, which are the standard request processing mechanism for
Chapter 8—The Host Component discusses the Tomcat implementation of a Virtual Host.
This is the key component responsible for the deployment of web application contexts, as
well as for the error page mechanism.
Chapter 9—The Context Component is at the central core of this book. You get an upclose-
and-personal look at how a Context is configured, how it accesses its resources,
and how it implements its class loading magic.
Chapter 10—The Wrapper Component takes us to the workhorse of the Tomcat
component hierarchy. This component wraps an actual servlet, and as a result is close
to a web developer’s heart. In addition to reviewing the mapping rules dictated by the
Servlet API, we also look at the implementation of servlet filters and the request
Chapter 11—The Session Component discusses how sessions are implemented in Tomcat
to enable stateful behavior over the stateless HTTP protocol. In addition to looking at
some core concepts, such as Java serialization and entropy gathering for random number
generation, we look at the standard memory based session implementation, as well as an
implementation that uses files to persist sessions.
Servlet Container Overview
In the last chapter, we noted that the Java Enterprise Edition can be considered to be
nothing more than a set of specifications, or interfaces, for which service providers
are required to provide implementations.
While it is the actual implementation that does all the work, these specifications
ensure that each implementation can assume that all its other collaborating
pieces work as described by their interfaces. In theory, this allows complex
software platforms (such as application servers) to be assembled from
constituent implementations, each of which is sourced from a different vendor.
In practice, it is highly unlikely that you will interface an EJB container from
WebSphere and a JMS implementation from WebLogic, with the Tomcat servlet
container from the Apache foundation, but it is at least theoretically possible.
Note that the term ‘interface’, as it is used here, also encompasses abstract classes.
The specification’s APimight provide a template implementation whose operations
are defined in terms of some basic set of primitives that are kept abstract for the
service provider to implement. For instance, in Chapter 2, we noted that the servlet
hierarchy is made up of the Servlet interface, and the GenericServlet and
HttpServlet abstract classes within the javax.servlet package.
A service provider is required to make available concrete implementations of
these interfaces and abstract classes. For example, the HttpSession interface
is implemented by Tomcat in the form of org.apache.catalina.session.
Let’s return to the image of the Tomcat container that we saw in Chapter 1.
As was stated in Chapter 1, the objective of this book is to cover the primary request
processing components that are present in this image. Advanced topics, such as
clustering and security, are shown as shaded in this image and are not covered.
In this image, the ‘+’ symbol after the Service, Host, Context, and Wrapper
instances indicate that there can be one or more of these elements. For instance, a
Service may have a single Engine, but an Engine can contain one or more Hosts.
In addition, the whirling circle represents a pool of request processor threads.
In this chapter, we will fl y over the architecture of Tomcat from a 10,000-foot
perspective taking in the sights as we go.
Tomcat’s architecture follows the construction of a Matrushka doll from Russia. In
other words, it is all about containment where one entity contains another, and that
entity in turn contains yet another.
In Tomcat, a ‘container’ is a generic term that refers to any component that can
contain another, such as a Server, Service, Engine, Host, or Context.
Of these, the Server and Service components are special containers, designated as
Top Level Elements as they represent aspects of the running Tomcat instance. All
the other Tomcat components are subordinate to these top level elements.
The Engine, Host, and Context components are officially termed Containers, and
refer to components that process incoming requests and generate an appropriate
Nested Components can be thought of as sub-elements that can be nested inside
either Top Level Elements or other Containers to configure how they function.
Examples of n ested components include the Valve, which represents a reusable unit
of work; the Pipeline, which represents a chain of Valves strung together; and a
Realm which helps set up container-managed security for a particular container.
Other nested components include the Loader which is used to enforce the
specification’s guidelines for servlet class loading; th e Manager that supports session
management for each web application; the R esources component that represents the
web application’s static resources and a mechanism to access these resources; and
the Listener th at allows you to insert custom processing at important points in a
container’s life cycle, such as when a component is being started or stopped.
Not all nested components can be nested within every container.
A final major component, which falls into its own category, is the Connector. It
represents the connection end point that an external client (such as a web browser)
can use to connect to the Tomcat container.
Before we go on to examine these components, let’s take a quick look at how they are
Note that this diagram only shows the key properties of each container.
When Tomcat is started, the Java Virtual Machine (JVM) instance in which it
runs will contain a singleton Server top level element, which represents the entire
Tomcat server. A Server will usually containjust one Service object, which is a
structural element that combines one or more Connectors (for example, an HTTP
and an HTTPS connector) that funnel incoming requests through to a single
Catalina servlet Engine.
The Engine represents the core request processing code within Tomcat and supports
the definition of multiple Virtual Hosts within it. A virtual host allows a single
running Tomcat engine to make it seem to the outside world that there are multiple
separate domains (for example, www.my-site.com and www.your-site.com) being
hosted on a single machine.
Each virtual host can, in turn, support multiple web applications known as
Contexts that are deployed to it. A context is represented using the web application
format specified by the servlet specification, either as a single compressed WAR
(Web Application Archive) file or as an uncompressed directory. In addition, a
context is configured using a web.xml file, as defined by the servlet specification.
A context can, in turn, contain multiple servlets that are deployed into it, each of
which is wrapped in a Wrapper component.
The Server, Service, Connector, Engine, Host, and Context elements that
will be present in a particular running Tomcat instance are configured using the
server.xml configuration file.
Things are a bit more complicated than this. However, we’ll defer the
complexity until later chapters when we deal with each component in a
lot more detail.
This architecture has a couple of useful features. It not only makes it easy to manage
component life cycles (each component manages the life cycle notifications for its
children), but also to dynamically assemble a running Tomcat server instance that
is based on the information that has been read from configuration files at startup.
In particular, the server.xml file is parsed at startup, and its contents are used to
instantiate and configure the defined elements, which are then assembled into a
running Tomcat instance.
The server.xml file is read only once, and edits to it will not be picked
up until Tomcat is restarted.
This architecture also eases the configuration burden by allowing child containers
to inherit the configuration of their parent containers. For instance, a Realm defines
a data store that can be used for authentication and authorization of users who
are attempting to access protected resources within a web application. For ease of
configuration, a realm that is defined for an engine applies to all its children hosts
and contexts. At the same time, a particular child, such as a given context, may
override its inherited realm by specifying its own realm to be used in place of its