refcard cover
Refcard #212

Getting Started With Apache Tomcat

Learn the Tomcat Pure Java Open-Source Web Server

Learn Apache Tomcat, a pure Java open-source web server that implements the Java Servlet, JavaServer Pages, and Expression Language specifications.

Free PDF for Easy Reference
refcard cover

Written By

author avatar Alex Soto
Software Engineer, Red Hat
author avatar Romain Manni-bucau
Software Engineer, Tomitribe
Section 1

Introduction to Apache Tomcat

Apache Tomcat is a pure Java open-source web server that implements the Java Servlet, JavaServer Pages, and Expression Language specifications .

According to the JRebel report, Tomcat is one of the most used web servers in the Java world with more than 50% of the market share.

Section 2

Apache Tomcat Installation


The quickest way to run Tomcat is to download and run a compiled version. Go to http://tomcat.apache.org/ and in the Download section choose the Tomcat version that fits your requirements and package file depending on your OS.

Tomcat Version


Tomcat 8.0.x

Servlet 3.1 / JSP 2.3 / EL 3.0 / WebSocket 1.1 / Java 7 and later

Tomcat 7.0.x

Servlet 3.0 / JSP 2.2 / EL 2.2 / WebSocket 1.1 / Java 6 and later (WebSocket requires Java 7)

Tomcat 6.0.x

Servlet 2.5 / JSP 2.1 / EL 2.1 / Java 5 and later

To run Tomcat, you have to first install a Java Runtime Environment (JRE). Make sure to install the right version depending on the Tomcat version you want to run (see table above).

$ wget http://repo.maven.apache.org/maven2/org/apache/tomcat/tomcat/8.0.24/tomcat-8.0.24.tar.gz
$ tar -zxvf apache-tomcat-8.0.24.tar.gz
$ cd apache-tomcat-8.0.24

The root directory is known as CATALINA_HOME. Optionally, Tomcat may be configured for multiple instances by defining CATALINA_BASE for each instance. For a single installation, CATALINA_BASE is the same as CATALINA_HOME.


The main script to start Tomcat is ${CATALINA_HOME}/bin/catalina.sh and the most used start-up commands are:



debug [-security]

Starts in a debugger

start [-security]

Starts in a separate window (or in the background)

run [-security]

Starts in the current window (in the foreground)

stop [-force]

Stops server waiting up to 5 seconds

-force option kills the process if not stopped after 5 seconds

jpda start

Starts under JPDA debugger – Environment variable JPDA_ADDRESS defines the debug address (often just a port) and JPDA_SUSPEND to suspend execution immediately after start-up

When Tomcat is started in the foreground, it can be stopped by pressing Ctrl+C.

There is a Windows package distribution that installs Tomcat as a Service on Windows operation systems. Most Linux distributions have their own packaging.

Directory Layout




Stores executable files for Windows/*nix systems to start and stop server.


Stores configuration files.


Stores libraries to share between all applications. By default, only Tomcat libraries are in this directory.


Stores Tomcat log files.


Stores temporary files created using the Java File API.


Deploys .war files or exploded web applications.


Stores intermediate files (such as compiled JSP files) during its work.


In the case of web applications, and according to Servlet specifications, when a classloader is asked to load a class or resource, it will first try in its own classloader, and then in its parent classloader(s).


An embedded Tomcat instance can be started within the same JVM of the running application.

Some dependencies must be added to a class path.

Gradle file with dependencies required:

dependencies {
//Minimal dependencies
compile 'org.apache.tomcat.embed:tomcat-embed-core:8.0.9'
compile 'org.apache.tomcat.embed:tomcat-embed-logging-juli:8.0.9'

//Optional dependency for JSP
compile 'org.apache.tomcat.embed:tomcat-embed-jasper:8.0.9'
compile 'org.eclipse.jdt.core.compiler:ecj:4.4'

Then you can instantiate a new Tomcat instance as any other Java class and call Tomcat operations such as registering Servlet, setting a webapp directory, or configuring resources programmatically.

//creates a Tomcat instance to listen on 8080 port
Tomcat tomcat = new Tomcat();

//adds a new context pointing to current directory as base dir.
Context ctx = tomcat.addContext("/", new File(".").getAbsolutePath());

//registers a servlet with name hello
Tomcat.addServlet(ctx, "hello", new HttpServlet() {
protected void service(HttpServletRequest req, HttpServletResponse resp) throws Exception {
Writer w = resp.getWriter();
w.write("Hello World");

//adds a new mapping for the “hello” Servlet matching any URL.
ctx.addServletMapping("/*", "hello");

//starts Tomcat instance

//waits current thread indefinitely
Section 3

Apache Tomcat Configuration

Apache Tomcat’s main configuration is composed of four files: server.xml, context.xml, web.xml, and logging.properties.


server.xml is located in ${CATALINA_BASE}/conf and represents the server itself. Here is an example:

<?xml ?>
<Server port="8005" shutdown="SHUTDOWN">

<Listener className="xxxxx" />
<Resource name="UserDatabase" auth="Container" type="org.apache.catalina.UserDatabase" description="User database" factory="org.apache.catalina.users.MemoryUserDatabaseFactory"pathname="conf/tomcat-users.xml" />

<Service name="Catalina">
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="..." />
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Valve className="..." />


The XML file represents almost a 1:1 layout of the server itself, which conforms with Tomcat’s hierarchical design.

The Tomcat Digester Rules processes the XML files. Each node can get an attribute className to specify which implementation you want to use, as well as a set of attributes which will be set on the created instance.

These are the most important tags to know to use Tomcat:




The server (aggregate instance) and admin configuration (mainly shutdown socket definition) and hierarchy


Tomcat internal events listener (see org.apache.catalina.LifecycleListener)


Defines a set of container-wide resources (as opposed to application ones)


Defines a JNDI resource


A set of connectors and an engine


Defines a protocol to use and its configuration (most common ones are HTTP and AJP)


The “processor” of an incoming request from a connector (a pipeline starting from the host, going through authentication if needed, the webapp and finally the servlet)


The thread pool associated with a Service to handle the request


Security repository (login/password/roles), 0 or 1 can be linked to Host, Engine, and/or Context


Virtual host representation (“domain”). It is a container of Contexts (explicit or implicit using appBase).


A web application


An element of the request pipeline (can be added on Engine, Host, or Context)


context.xml is a configuration file for a web application. You can also use a Context element under the Host tag in server.xml, but it is recommended (if necessary) that you provide them either in the web application in META-INF/context.xml or (if the configuration is local to the Tomcat instance) in ${CATALINA_BASE}/conf/<engine name>/<hostname>/<warname>.xml.

This last option overrides the META-INF file if both exist. This is convenient for overriding a packaged version, for instance overriding a DataSource.

A shared web application configuration (across all applications) is done in ${CATALINA_BASE}/conf/context.xml (global) and ${CATALINA_BASE}/conf/<engine name>/<hostname>/context.xml.default (specific to a host).

The following are the main children tags of Context:




Internal events listener specific to filters/servlets


Tomcat internal events listener (see org.apache.catalina.LifecycleListener) but “Context scoped”


Defines the classloader to use for the webapp


Defines the session configuration


Defines a context parameter

Resources (PreResources, JarResources, PostResources)

Where resources (JS, CSS, HTML, …., .class) are taken from.


Link to a global JNDI entry


Same as in server.xml


If the defined resource changes Context will be reloaded (undeploy/deploy)


LifecycleListener for each wrapper (servlet)


ContainerListener for each wrapper


The application scanner implementation (which classloader to scan and how to get jar paths, ...)


Which paths should be scanned/ignored, should tag libraries (TLDs) be scanned....


Named values that will be made visible to the web application as environment entry resources.


This section does not refer to WEB-INF/web.xml, which is a standard deployment descriptor of the Servlet specification, but about ${CATALINA_BASE}/conf/web.xml.

This is a standard web.xml where mime types, default servlets/filters, default welcome files, and default session timeouts are defined.

This configuration is inherited by all web applications.

Here are the default servlets and some examples of why you might need to update them:




Serves static resources.Encoding, is listing folder allowed are configurable.


Serves (and compiles if needed) JSP.Compiling information, should JSP be watched for updates (development), and pooling are configurable.

SSL (exists as filter too)

Supports server side includes on HTML pages; disabled by default.


Can execute an external binary to acquire content; disabled by default.

Section 4

Apache Tomcat Logging

Tomcat uses an enhanced version of the Java Util Logging (JUL) API built into the JVM. As a container, Tomcat needs to support logging configuration at the container level for itself, but it also needs to support application specific configurations.


Tomcat uses a custom LogManager to be able to more finely configure the logging: org.apache.juli.ClassLoaderLogManager

The default configuration is in ${CATALINA_BASE}/conf/logging.properties. Each web application can embed its own configuration by defining a logging.properties file under WEB-INF/classes directory of the webapp.

Configuration Overview

my.logger.name.level = FINEST # a java.util.logging.Level
my.logger.name.handlers = myHandler1,myHandler2,...
my.logger.name.useParentHandlers = true # false by default


You can prefix a logger name with a String starting with a digit and ending with a dot (for instance 1prefix.my.logger.name). This is useful to simultaneously configure the same handler (a file, for instance) with different settings.

Dynamic Values

You can use place holders like ${xxx}. They get replaced automatically at runtime with the value of the Java system property with the key xxx.

Root Logger

Root logger is configured using an empty name:

.handlers = ….


Tomcat provides several additional handlers like org.apache.juli.FileHandler, which supports log buffering; AsyncFileHandler, which is asynchronous; and some formatters like JdkLoggerFormatter, which uses the log4j equivalent format %r %-15.15c{2} %-1.1p %m %n.

ServletContext Logging

ServletContext.log(...) output is configurable using property org.apache.catalina.core.ContainerBase.[${engine}].[${host}].[${context}].

Replace JUL

You can use log4j for Tomcat itself. To do this, you need to add log4j.jar, tomcat-juli-adapters.jar, log4j.properties in ${CATALINA_HOME}/lib and replace tomcat-juli.jar from bin/ directory with tomcat-juli.jar from extras modules (See Tomcat download page). Don't forget to remove the conf/logging.properties file so that JUL does not create empty files.


Tomcat supports clustering (session distribution and deployments) out of the box. To activate it, add a Cluster tag in your Host or Engine.

The cluster tag supports these configurations:




Defines the cluster class and configuration.


Session replication strategy (by default it uses DeltaManager to send delta to nodes, synchronously or not).


How cluster nodes are connected together (backed by Apache Tribes).

Channel has sub tags like Membership (discovery of nodes), Sender (send message on the cluster), Receiver (how cluster messages are received) and Interceptor (listen for/send cluster messages).


Creates and replicates files when needed within the cluster (end of request by default).


Allows deploy/undeploy actions across the entire cluster applications.


Observes cluster messages.

Here is the most basic example:

<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>

NOTE: Don't forget your session attributes need to be Serializable. This is also a requirement if you want the session to survive Tomcat cycles (a.k.a. HTTP session serialization).

Section 5

IDEs with Apache Tomcat Support

Apache Tomcat is supported by major IDE vendors.


To register Tomcat in Eclipse WTP (Web Tools Platform):

- Open Window -> Preferences -> Server -> Installed Runtimes

- Click on Add and in New Server Runtime, select Apache -> Apache Tomcat v8.0

- Click Next and fill in your Tomcat installation directory

IntelliJ IDEA

To register Tomcat in IntelliJ IDEA Ultimate Edition (community edition is not supported)

- Open File -> Settings -> (IDE Settings) Application Servers

- Click on + symbol and select Tomcat Server

- In the dialog box fill Tomcat Home with your Tomcat installation directory


Netbeans Java EE comes with Apache Tomcat already installed, but you can use register Tomcat as well.

- Open Windows -> Services

- Right-Click on Servers -> Add Server

- In the dialog box choose Apache Tomcat

- Click Next -> fill Server Location with your Tomcat installation directory

Section 6

Apache Tomcat I/O

Following today's needs Tomcat proposes several I/O solutions.


As explained in the Configuration section, Tomcat handles I/O thanks to connectors. Most of them share a common configuration, the full details of which are available at http://tomcat.apache.org/tomcat-8.0-doc/config/http.html.


The NIO and NIO2 connectors allow you to use Java NIO to handle incoming requests. With the release of Tomcat 8, they are now the default connectors to handle HTTP requests.

Note that to use NIO2 you need to specify the class org.apache.coyote.http11.Http11Nio2Protocol on your Connector tag in the class-name attribute. Keep in mind it is still a “beta” connector, but it can bring your application some significant speed enhancements.


The BIO connector allows you to use the old blocking I/O. It was the default connector to handle HTTP requests for prior Tomcat 8 versions.

The main difference between NIO and BIO is that with the BIO connector you generally need more threads to handle requests concurrently, and they don’t guarantee better performances. These connectors impose you to get one thread by connection!

For Tomcat 9+ versions, the BIO connector has been completely removed.


AJP is a protocol like HTTP. Its main goal is to get higher performances. It is a binary version of HTTP, and also a connected protocol as opposed to HTTP. It can be used with httpd (a.k.a Apache Web Server) and most of the time with mod_jk or mod_proxy_ajp httpd modules. If you are using SSL or have a lot of static resources, this is the fastest connector!


CometD is the old way to handle asynchronous I/O (i.e. let the container call you when data are available). This only works with APR or NIO connectors.

To use CometD, you first need to implement it within a servlet org.apache.catalina.comet.CometProcessor (eliminating portability) and then handle events in event(CometEvent):

public class MyCometDServlet extends HttpServlet implements CometProcessor {
public void event(final CometEvent event) throws IOException, ServletException {

final HttpServletRequest request = event.getHttpServletRequest();
final HttpServletResponse response = event.getHttpServletResponse();

if (event.getEventType() == CometEvent.EventType.BEGIN) { //keep the response to bulk send data to everybody
} else

if (event.getEventType() == CometEvent.EventType.ERROR || event.getEventType() == CometEvent.EventType.END) {
// state cleanup if needed
         // we are done
} else

if (event.getEventType() == CometEvent.EventType.READ) {
final InputStream is = request.getInputStream();
do {
// read is
} while (is.available() > 0);


WebSockets (RFC 6455) have been supported by Tomcat since version 7, but only versions 7.0.43 and later implement the specification (a.k.a JSR-356). Before ( version 7.0.27 and earlier) Tomcat was using a proprietary API and implementation didn't scale as much as today -- so ensure you are using an up-to-date version.

The Tomcat WebSocket implementation needs at least Java 7. If you are running on Java 7, it is activated by default and you just need to deploy your code inside Tomcat:

public class TchatEndpoint {

public void onMessage(Session session, String msg) {
try {
} catch (IOException e) { ... }

WebSocket doesn't require you to use an APR or NIO connector like CometD does, but it is highly recommended, as you will likely have a high number of connections.


Tomcat provides a JNDI InitialContext implementation instance for each web application. As mentioned in the Configuration section, JNDI resources can be registered in conf/server.xml, conf/web.xml, or any context.xml file. But Tomcat also follows the Java EE standard for /WEB-INF/web.xml file to reference/define resources.

In order to use a JNDI resource, specify the JNDI name defined in the web application's deployment descriptor:

<context ...>
<!-- Definition of DataSource in context.xml -->
<Resource name="jdbc/employeeDB" type="javax.sql.DataSource" global="jdbc/employeeDB" .../>

<!-- Declaring a reference to DataSource in web.xml -->
<description>Employee Datasource</description>
<env-entry-value>Hello World</env-entry-value>

Java Code

Context initCtx = new InitialContext();
DataSource ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/EmployeeDB");
String message = (String)initCtx.lookup("java:comp/env/message");
Section 7

Apache Tomcat Listeners

A Listener element defines a component that performs actions when specific events occur, usually Tomcat starting or Tomcat stopping.

Listeners are registered inside conf/server.xml inside Server, Engine, Host, and Context tags.

Each Listener must implement org.apache.catalina.LifecycleListener interface.

Custom Listener
public class PrintLifecycleStatesListener implements LifecycleListener {
public void lifecycleEvent(LifecycleEvent e) {

The JAR file containing this class is stored at $CATALINA_BASE/lib directory.

And add the next line at conf/server.xml.

<Server ...>
<Listener className="org.superbiz.PrintLifecycleStatesListener"/>

Shipped Listeners




Checks for the presence of the APR/native library and loads the library if it is present.


Initializes the Global JNDI resources defined in server.xml as part of the Global Resources element.


Prevents memory leaks by providing workarounds for instances where the JRE uses the context classloader to load a singleton.


Performs a number of security checks when Tomcat starts and prevents Tomcat from starting if they fail; not enabled by default.


Triggers the renewal of threads in Executor pools when a Context is being stopped to avoid ThreadLocal-related memory leaks.


Map a request URI starting with a tilde character ("~") and a username to a directory in that user's home directory on the serve; not enabled by default.


Fixes the ports used by the JMX/RMI Server; not enabled by default.

Section 8

Deploying Apache Tomcat

After installing and configuring Tomcat, you will need to deploy web applications.

Drop-In WAR

Deploying an application to Tomcat can be as simple as dropping a WAR file inside the $CATALINA_BASE/webapps directory; this will deploy the application.

Hot Deployment

To deploy a new application, you must restart the server in order for the application to function. To fix this problem, Tomcat provides a hot deployment option, which deploys an application without the need to restart.

To enable hot deployment, the autoDeploy attribute from host tag in server.xml must be set to true. See the configuration section for an example.

Tomcat Manager

Web Application

Tomcat also comes with a manager that allows for deploying an application from the web console. To use the manager, you need to add a username and password to conf/tomcat-users.xml with role manager-gui.

<role rolename="manager-gui"/>
<user username="tomcat" password="s3cret" roles="manager-gui"/>

Next, access http://<host>:<port>/manager to access the web console.


The Tomcat Manager also provides URI commands to upload applications. They follow this schema:


Some examples of deploying an application using URI commands:


The above uploads to the remote server, the war with path /foo. The war is provided as the body of the HTTP PUT.


This deploys application stored in the server directory path/to/foo.war.


Arquillian is an integration and functional testing platform that can be used for Java middleware testing. The main goal of Arquillian is to make tests that require a server to be as simple as writing unit tests.

You can use Arquillian Tomcat adapters to write integration/functional tests.

Arquillian Tomcat 8 adapter release is coming soon.

Maven coordinates can be found at:





When using the embedded adapter, Tomcat embedded dependencies are required as well.

When using the remote adapter, the Tomcat instance has to expose a remote JMX MbeanConnection.

JAVA_OPTS=”$JAVA_OPTS -Dcom.sun.management.jmxremote.port=8089 “
JAVA_OPTS=”$JAVA_OPTS -Dcom.sun.management.jmxremote.ssl=false “
JAVA_OPTS=”$JAVA_OPTS -Dcom.sun.management.jmxremote.authenticate=false”


Maven is still one of the most used build tools and therefore Tomcat integration is available.

This integration is mainly (in addition to deploying artifacts on central) a Maven plugin.

Today, there are two plugins, tomcat-maven-plugin for Tomcat 6 and tomcat7-maven-plugin for Tomcat 7; tomcat8-maven-plugin is coming soon.

Their usage is more or less the same:


Here are the main configurations of the Maven plugin:




Tomcat manager URL (to deploy/undeploy/start/stop/reload)


Use settings.xml server for authentication on Tomcat manager application


Encoding to use to communicate with manager application


Credential of the manager application

Once these configurations are set up,  the available goals are as follows:



deploy / undeploy / redeploy

(Un)deploys a WAR

Exec-war / standalone-war

Create a runnable JAR or WAR running Tomcat and your application (java -jar mytomcatapp.jar)


Start Tomcat embedded with current project deployed as dynamic project


Same as run, using a WAR instead of resources


Stop started servers (useful if using pre-integration-test phase to start Tomcat and post-integration-test to stop it)

Note: Often goals will exist with the "-only" suffix. For example, the deploy-only goal will not fork a Maven package lifecycle.

Each goal has further configurations, for example the “context” path within the “deploy” application goal.

You can find more details at: http://tomcat.apache.org/maven-plugin-trunk/tomcat7-maven-plugin/plugin-info.html.

Java EE and Beyond

Tomcat is a Servlet container that implements the Servlet/JSP/EL specifications. If you are required to use any other Java EE specification like CDI, JPA, EJB, JAX-RS, or Bean Validation, you can integrate it by yourself (assuming you understand the perils of doing it yourself), or you can use Apache TomEE. TomEE (pronounced "Tommy") is the Java Enterprise Edition of Apache Tomcat (Tomcat + Java EE = TomEE) and is Java EE 6 Web Profile certified. It maintains the light weight and simplicity of Tomcat but with the full power of Java EE.


Apache Tomcat site:http://tomcat.apache.org

Tomcat server.xml: http://tomcat.apache.org/tomcat-8.0-doc/config/server.html

Tomcat Logging:http://tomcat.apache.org/tomcat-8.0-doc/logging.html

Tomcat Clustering:http://tomcat.apache.org/tomcat-8.0-doc/cluster-howto.html

Tomcat Listeners:http://tomcat.apache.org/tomcat-8.0-doc/config/listeners.html

Tomcat WebSocket:http://tomcat.apache.org/tomcat-8.0-doc/web-socket-howto.html

Tomcat Maven Plugin:http://tomcat.apache.org/maven-plugin.html

Arquillian and Tomcat:https://docs.jboss.org/author/display/ARQ/Tomcat+7.0+-+Embedded

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}