Apache Tomcat Overview

The world's most popular Java servlet container

← Back to Index

What is Apache Tomcat?

Apache Tomcat is the world's most widely used Java servlet container and web server. It's an open-source implementation of the Jakarta Servlet, Jakarta Server Pages (JSP), and Jakarta WebSocket specifications, developed under the Apache Software Foundation.

When people say they're "deploying to Tomcat," they mean they're using Tomcat as the runtime environment for their Java web applications. It's the "home" where your web app lives and runs.

Why Tomcat is So Popular

Quick Facts about Tomcat:

  • Created: 1999, originally by Sun Microsystems, donated to Apache
  • Current Version: Tomcat 10.1.x (Jakarta EE 10), Tomcat 11 (Jakarta EE 11)
  • Written In: Java (so it runs on any platform with JVM)
  • Default Port: 8080 (HTTP), 8443 (HTTPS), 8005 (shutdown)
  • Implements: Servlet 6.0, JSP 3.1, EL 5.0, WebSocket 2.1

Tomcat Version History (What You Need to Know)

Tomcat Version Java Version Servlet Spec Package Names
Tomcat 8.5 Java 7+ Servlet 3.1 javax.servlet.*
Tomcat 9 Java 8+ Servlet 4.0 javax.servlet.*
Tomcat 10 Java 11+ Servlet 5.0/6.0 jakarta.servlet.*
Tomcat 11 Java 17+ Servlet 6.1 jakarta.servlet.*
Important: javax vs jakarta

Tomcat 10+ uses jakarta.servlet.* package names instead of javax.servlet.*. This is due to Oracle transferring Java EE to the Eclipse Foundation. If your app uses javax.servlet, you need Tomcat 9 or earlier, OR you need to migrate your imports to jakarta.servlet.

Tomcat Directory Structure

Understanding Tomcat's directory layout is essential for configuration and troubleshooting. Here's what each folder contains:

apache-tomcat-10.1.x/
├── bin/                 ← Startup/shutdown scripts
│   ├── startup.sh          (Linux/Mac start)
│   ├── startup.bat         (Windows start)
│   ├── shutdown.sh         (Linux/Mac stop)
│   ├── shutdown.bat        (Windows stop)
│   ├── catalina.sh         (Main script with more options)
│   └── setenv.sh           (YOUR custom JVM options - create this!)
│
├── conf/                ← Configuration files
│   ├── server.xml          (Main server configuration)
│   ├── web.xml             (Default web app settings)
│   ├── context.xml         (Default context settings)
│   ├── tomcat-users.xml    (User accounts for manager)
│   └── logging.properties (Logging configuration)
│
├── lib/                 ← Tomcat's own JAR files + shared libraries
│   ├── servlet-api.jar     (Servlet API)
│   ├── jsp-api.jar         (JSP API)
│   └── ...                 (Tomcat implementation JARs)
│
├── logs/                ← Log files (check here for errors!)
│   ├── catalina.out        (Main log - all console output)
│   ├── catalina.YYYY-MM-DD.log (Daily server logs)
│   ├── localhost.YYYY-MM-DD.log (Application logs)
│   └── localhost_access.YYYY-MM-DD.log (HTTP access logs)
│
├── temp/                ← Temporary files (can be cleared)
│
├── webapps/             ← YOUR APPLICATIONS GO HERE!
│   ├── ROOT/               (Default app at http://localhost:8080/)
│   ├── manager/            (Web-based management interface)
│   ├── host-manager/       (Virtual host management)
│   ├── examples/           (Example servlets - remove in production!)
│   └── myapp.war           (Your app! Auto-deploys when dropped here)
│
└── work/                ← Compiled JSPs and session data
    └── Catalina/           (Generated files - can be cleared)

The Most Important Directories

Installing and Running Tomcat

Method 1: Download and Extract

# 1. Download from https://tomcat.apache.org/
# 2. Extract the archive

# Linux/Mac:
tar -xzf apache-tomcat-10.1.18.tar.gz
cd apache-tomcat-10.1.18

# 3. Make scripts executable (Linux/Mac)
chmod +x bin/*.sh

# 4. Start Tomcat
./bin/startup.sh
# Or: ./bin/catalina.sh run (to see output in terminal)

# 5. Open browser: http://localhost:8080
# You should see the Tomcat welcome page!

# 6. Stop Tomcat
./bin/shutdown.sh

Method 2: Using Package Manager

# Ubuntu/Debian
sudo apt install tomcat10

# macOS with Homebrew
brew install tomcat

# Windows with Chocolatey
choco install tomcat

Method 3: IDE Integration (Development)

// IntelliJ IDEA:
// 1. Run → Edit Configurations
// 2. + → Tomcat Server → Local
// 3. Configure Tomcat Home directory
// 4. Add your artifact (WAR) to deploy

// Eclipse:
// 1. Window → Preferences → Server → Runtime Environments
// 2. Add → Apache Tomcat v10.1
// 3. Create new Server in Servers view

Setting JVM Options

# Create bin/setenv.sh (Linux/Mac) or bin/setenv.bat (Windows)
# This file is the RIGHT place for your custom settings

# bin/setenv.sh example:
#!/bin/bash

# Memory settings
CATALINA_OPTS="$CATALINA_OPTS -Xms512m"      # Initial heap
CATALINA_OPTS="$CATALINA_OPTS -Xmx2048m"     # Maximum heap

# Garbage collection (for Java 11+)
CATALINA_OPTS="$CATALINA_OPTS -XX:+UseG1GC"

# Remote debugging (development only!)
CATALINA_OPTS="$CATALINA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"

# Application properties
CATALINA_OPTS="$CATALINA_OPTS -Dspring.profiles.active=production"

export CATALINA_OPTS

Key Configuration Files

server.xml - The Main Configuration

<!-- conf/server.xml - Core Tomcat configuration -->
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">

    <Service name="Catalina">

        <!-- HTTP Connector - where requests come in -->
        <Connector
            port="8080"              <!-- Listen on this port -->
            protocol="HTTP/1.1"
            connectionTimeout="20000"
            maxThreads="200"         <!-- Max concurrent requests -->
            minSpareThreads="10"
            redirectPort="8443" />

        <!-- HTTPS Connector (uncomment and configure for SSL) -->
        <!--
        <Connector
            port="8443"
            protocol="org.apache.coyote.http11.Http11NioProtocol"
            maxThreads="150"
            SSLEnabled="true">
            <SSLHostConfig>
                <Certificate
                    certificateKeystoreFile="conf/keystore.jks"
                    certificateKeystorePassword="changeit"
                    type="RSA" />
            </SSLHostConfig>
        </Connector>
        -->

        <!-- Engine processes requests -->
        <Engine name="Catalina" defaultHost="localhost">

            <!-- Virtual host -->
            <Host name="localhost"
                  appBase="webapps"        <!-- Where apps are -->
                  unpackWARs="true"        <!-- Extract WAR files -->
                  autoDeploy="true">       <!-- Auto-deploy new WARs -->

                <!-- Access logging -->
                <Valve className="org.apache.catalina.valves.AccessLogValve"
                       directory="logs"
                       prefix="localhost_access_log"
                       suffix=".txt"
                       pattern="%h %l %u %t "%r" %s %b" />
            </Host>
        </Engine>
    </Service>
</Server>

tomcat-users.xml - User Authentication

<!-- conf/tomcat-users.xml - Users for Manager app -->
<?xml version="1.0" encoding="UTF-8"?>
<tomcat-users>
    <!-- Roles -->
    <role rolename="manager-gui"/>     <!-- Access manager web UI -->
    <role rolename="manager-script"/>  <!-- Deploy via script/API -->
    <role rolename="admin-gui"/>       <!-- Host manager web UI -->

    <!-- Users -->
    <user username="admin"
          password="secretpassword"
          roles="manager-gui,manager-script,admin-gui"/>
</tomcat-users>

<!-- WARNING: Change the password in production!
     Consider using a more secure authentication mechanism -->

context.xml - Default Context Settings

<!-- conf/context.xml - Default settings for all web apps -->
<?xml version="1.0" encoding="UTF-8"?>
<Context>

    <!-- Database connection pool (shared by all apps) -->
    <Resource
        name="jdbc/mydb"
        auth="Container"
        type="javax.sql.DataSource"
        driverClassName="org.postgresql.Driver"
        url="jdbc:postgresql://localhost:5432/mydb"
        username="dbuser"
        password="dbpassword"
        maxTotal="100"
        maxIdle="30"
        maxWaitMillis="10000"/>

    <!-- Prevent session persistence across restarts -->
    <Manager pathname="" />

    <!-- Watch web.xml for changes (development only) -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>

</Context>

Deploying Applications to Tomcat

Method 1: Drop WAR File (Simplest)

# Just copy your WAR file to webapps/
cp myapp.war /opt/tomcat/webapps/

# Tomcat automatically:
# 1. Detects the new WAR file
# 2. Extracts it to webapps/myapp/
# 3. Deploys the application
# 4. Makes it available at http://localhost:8080/myapp

# To undeploy: delete the WAR and the extracted folder
rm /opt/tomcat/webapps/myapp.war
rm -rf /opt/tomcat/webapps/myapp

Method 2: Manager Web Interface

# 1. Access: http://localhost:8080/manager/html
# 2. Login with credentials from tomcat-users.xml
# 3. Scroll to "WAR file to deploy"
# 4. Choose file and click "Deploy"

# Manager also lets you:
# - Start/Stop/Reload applications
# - Undeploy applications
# - View session statistics
# - Check server status

Method 3: Maven Plugin

<!-- pom.xml - Tomcat Maven Plugin -->
<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <url>http://localhost:8080/manager/text</url>
        <server>tomcat-server</server>  <!-- Reference to settings.xml -->
        <path>/myapp</path>
    </configuration>
</plugin>

<!-- In ~/.m2/settings.xml -->
<servers>
    <server>
        <id>tomcat-server</id>
        <username>admin</username>
        <password>secretpassword</password>
    </server>
</servers>

# Deploy command:
mvn tomcat7:deploy      # First deployment
mvn tomcat7:redeploy    # Update existing
mvn tomcat7:undeploy    # Remove

Understanding Context Paths

// The WAR filename determines the context path (URL)

myapp.war           → http://localhost:8080/myapp
myapp##2.war        → http://localhost:8080/myapp (version 2, parallel deploy)
ROOT.war            → http://localhost:8080/ (root context)
my#app.war          → http://localhost:8080/my/app (nested path)

// Examples:
webapps/
├── ROOT.war        → http://localhost:8080/
├── api.war         → http://localhost:8080/api
├── admin.war       → http://localhost:8080/admin
└── v2#api.war      → http://localhost:8080/v2/api

Tomcat Architecture

Understanding Tomcat's internal architecture helps with configuration and troubleshooting:

// Tomcat Component Hierarchy

┌─────────────────────────────────────────────────────────────────────┐
│                            SERVER                                    │
│  (Top-level container - one per Tomcat instance)                    │
│                                                                      │
│  ┌───────────────────────────────────────────────────────────────┐  │
│  │                         SERVICE                                │  │
│  │  (Groups Connectors with an Engine)                           │  │
│  │                                                                │  │
│  │  ┌─────────────┐  ┌─────────────┐                            │  │
│  │  │ CONNECTOR   │  │ CONNECTOR   │   (Multiple connectors)     │  │
│  │  │ (HTTP:8080) │  │ (HTTPS:8443)│   (HTTP, HTTPS, AJP)        │  │
│  │  └──────┬──────┘  └──────┬──────┘                            │  │
│  │         │                │                                    │  │
│  │         └────────┬───────┘                                    │  │
│  │                  │                                            │  │
│  │         ┌────────▼────────┐                                   │  │
│  │         │     ENGINE      │  (Request processing)             │  │
│  │         │   "Catalina"    │                                   │  │
│  │         └────────┬────────┘                                   │  │
│  │                  │                                            │  │
│  │         ┌────────▼────────┐                                   │  │
│  │         │      HOST       │  (Virtual host: localhost)        │  │
│  │         │  "localhost"    │  (Can have multiple hosts)        │  │
│  │         └────────┬────────┘                                   │  │
│  │                  │                                            │  │
│  │    ┌─────────────┼─────────────┐                             │  │
│  │    │             │             │                              │  │
│  │    ▼             ▼             ▼                              │  │
│  │ ┌──────┐    ┌──────┐    ┌──────┐                            │  │
│  │ │CONTXT│    │CONTXT│    │CONTXT│  (Your applications)        │  │
│  │ │/app1 │    │/app2 │    │ ROOT │                             │  │
│  │ └──────┘    └──────┘    └──────┘                            │  │
│  │                                                                │  │
│  └───────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────┘

Component Descriptions

Component Purpose Configuration
Server Top-level, represents entire Tomcat instance server.xml (root element)
Service Groups Connectors with one Engine server.xml (<Service>)
Connector Handles network connections (HTTP, HTTPS) server.xml (<Connector>)
Engine Processes requests, routes to correct Host server.xml (<Engine>)
Host Virtual host (domain handling) server.xml (<Host>)
Context Individual web application context.xml, META-INF/context.xml

Troubleshooting Common Issues

1. Tomcat Won't Start

# Check if port is already in use
lsof -i :8080           # Linux/Mac
netstat -ano | findstr 8080  # Windows

# Check logs for errors
tail -f logs/catalina.out

# Common causes:
# - Another Tomcat or app using port 8080
# - JAVA_HOME not set
# - Insufficient permissions
# - Corrupted WAR file

2. Application Not Loading

# Check application-specific log
tail -f logs/localhost.YYYY-MM-DD.log

# Check if WAR was extracted
ls -la webapps/

# Common causes:
# - Missing dependencies in WEB-INF/lib
# - web.xml errors
# - Jakarta vs javax package mismatch (Tomcat 10+)
# - Database connection failures

3. Out of Memory Errors

# Increase heap size in setenv.sh
CATALINA_OPTS="-Xms1024m -Xmx4096m"

# Check for memory leaks
# Manager app → "Find leaks" button

# Enable heap dump on OOM
CATALINA_OPTS="$CATALINA_OPTS -XX:+HeapDumpOnOutOfMemoryError"
CATALINA_OPTS="$CATALINA_OPTS -XX:HeapDumpPath=/opt/tomcat/logs/"

4. Slow Performance

# Increase thread pool
<Connector port="8080" maxThreads="500" />

# Enable connection pooling for database
# Check slow queries in application

# Monitor with JMX
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote"
CATALINA_OPTS="$CATALINA_OPTS -Dcom.sun.management.jmxremote.port=9090"

Production Best Practices

Security:

  • Remove default apps: Delete examples/, docs/, manager/ (or restrict access)
  • Change shutdown port: Or disable it entirely
  • Use HTTPS: Configure SSL/TLS connector
  • Hide server info: Set server="Apache" in Connector
  • Restrict manager access: IP-based restrictions in context.xml

Performance:

  • Tune thread pool: Match maxThreads to expected load
  • Enable compression: Add compression="on" to Connector
  • Use NIO connector: protocol="org.apache.coyote.http11.Http11NioProtocol"
  • Configure connection pooling: Proper min/max connections

Reliability:

  • Set up monitoring: JMX, metrics endpoint, health checks
  • Configure logging: Log rotation, appropriate log levels
  • Graceful shutdown: Use proper shutdown scripts
  • Backup configurations: Version control your conf/ directory

Summary

  • Tomcat: World's most popular Java servlet container, open source, lightweight
  • Directory Structure: webapps/ (apps), conf/ (config), logs/ (troubleshooting)
  • Key Config Files: server.xml (main), tomcat-users.xml (auth), context.xml (resources)
  • Deployment: Drop WAR in webapps/, use Manager, or Maven plugin
  • Context Path: WAR filename determines URL (myapp.war → /myapp)
  • Architecture: Server → Service → Connector + Engine → Host → Context
  • Tomcat 10+: Uses jakarta.* packages (not javax.*)