Tomcat Container Architecture: A Deep Dive into Source Code

The previous article explored Tomcat's two main components: the connector that handles incoming requests and the container that processes them. This piece examines the container architecture through its source code implementation.

Container Hierarchy

Tomcat defines four levels of containers arranged in a parent-child relationship:

  • Engine: Represents the servlet engine, managing multiple virtual hosts. Each Service contains exactly one Engine.
  • Host: Represents a virtual host within the engine.
  • Context: Represents a single web application.
  • Wrapper: Represents an individual servlet.

Container Structure and Interfaces

These four container types share a common parant interface while maintaining their specific responsibilities. All containers implement the Container interface, which establishes the foundation for the composite pattern used throughout the architecture:

Pipeline obtainPipeline();

Container retrieveParent();

void assignParent(Container container);

void executeBackgroundTasks();

void attachChild(Container child);

Container locateChild(String name);

Container[] fetchChildren();

void detachChild(Container child);

}


</div> This unified interface enables the composite pattern, allowing containers to be composed and orchestrated consistently regardless of their specific type.

Pipeline and Valve: The Container Execution Chain
-------------------------------------------------

 The `Container` interface references a `Pipeline`, which represents the execution chain for that particular container. When request processing reaches a container, it delegates to its pipeline to perform the actual work.

### Pipeline Interface Definition

<div> ```
public interface Pipeline {
    
    Valve obtainBasic();

    void configureBasic(Valve valve);

    void registerValve(Valve valve);

    Valve[] retrieveValves();

    void unregisterValve(Valve valve);

    Valve accessFirst();

    boolean supportsAsync();

    Container fetchContainer();

    void linkContainer(Container container);
}

Valve Interface Definition

Valve accessNext();

void defineNext(Valve valve);

void performBackgroundTask();

void execute(Request request, Response response)
    throws IOException, ServletException;

}


</div> Each Valve completes its processing and then invokes `accessNext()` to pass control to the subsequent Valve in the chain.

### Execution Flow

 A critical aspect of this mechanism is the BasicValve. It serves as the terminal Valve in every pipeline, and its implementation delegates to the first Valve of the child container. This creates a cascading effect where requests flow through each level of the container hierarchy.

 The request propagation begins when the connector's adapter invokes the Engine's first Valve. From there, the request travels through the container chain: Engine → Host → Context → Wrapper, with each level potentially having custom Valves that perform preprocessing or postprocessing logic before delegating to child containers.

 The pipeline implementation guarantees that BasicValve remains the final element in the chain through the `configureBasic()` method, ensuring predictable request flow through the container hierarchy.

Posted on Fri, 03 Jul 2026 16:33:38 +0000 by dotti