Tomcat
Posts
-
Digging into Tomcat's Source 1: How I Read It with AI, and the Map
The first post of a series that reads the Tomcat source — it starts by showing what Tomcat is, how it works and what it is for, with diagrams and a 3-minute hands-on run. It covers which version is read (the main branch, 12.0.0-M1) and how it differs from the stable 11.0.x, which Servlet spec version it implements, how to get the same source and build it with Ant in Docker, a folder map of the roughly 740,000-line codebase, the big road one request travels from the Acceptor to your servlet, and how AI-written notes are re-checked against the source.
-
Digging into Tomcat's Source 2: The Big Picture — Server, Service, Connector and the Four Containers
A map for anyone opening the Tomcat source for the first time. We look at which class each server.xml element (Server, Service, Connector, Engine, Host) turns into, how the four containers Engine, Host, Context and Wrapper are linked as parents and children, why the connector (Coyote) and the servlet container (Catalina) are kept apart and joined by a single Adapter, and where Jasper, EL, JULI and Naming live — all checked against the real source and examples I actually ran.
-
Digging into Tomcat's Source 3: Lifecycle and Startup — What Happens After catalina.sh start
We follow the source from catalina.sh start to a running server — Bootstrap building class loaders, Catalina turning server.xml into a tree of objects with the Digester, and every component being initialized and started by the same Lifecycle state machine. With a listener and small examples we check the order in which parents start their children, why the server still comes up when a connector fails, and what the shutdown port 8005 does.
-
Digging into Tomcat's Source 4: Class Loaders — Each Web App Sees Its Own Classes
Why can two web apps in a single Tomcat process use different classes with the same name? We find the answer in the source — the common, server and shared loaders that Bootstrap builds from catalina.properties, the per-app WebappClassLoaderBase whose loadClass() turns parent delegation around, filter() which picks out exceptions such as jakarta.servlet, the delegate setting, and reloadable reloads with their thread-leak warnings — and check each one on a Tomcat built from the reference commit.
-
Digging into Tomcat's Source 5: The Connector and the NIO Endpoint — Which Threads Take a Connection
We follow in the source how one line of server.xml, <Connector port="8080">, becomes three objects — Connector, Http11NioProtocol and NioEndpoint — and how the Acceptor, the Poller and the worker threads share the work of a single connection inside them. With jstack and a raw-socket client we check how a keep-alive connection lets go of its thread between requests, how Tomcat's thread pool (TaskQueue) behaves differently from the JDK's, and where maxConnections, acceptCount and maxThreads take effect. We also compare with 11.0.x and see that the NIO2 connector is gone from the main branch.
-
Digging into Tomcat's Source 6: Reading an HTTP/1.1 Request — From Bytes to a coyote Request
We follow, through the real source, how bytes read from a socket are split into a request line and headers inside the service() loop of Http11Processor and become a coyote Request. By sending raw requests we also see MessageBytes, which delays making Strings, the maxHttpHeaderSize and maxHeaderCount limits, how a bad request turns into an HTML 400 page, and where keep-alive and chunked responses are decided.
-
Digging into Tomcat's Source 7: CoyoteAdapter and the Mapper — Which Servlet Gets the Request
We follow CoyoteAdapter, the bridge that carries a fully read HTTP request from Coyote into Catalina; postParseRequest(), which decodes and normalizes the URI on the way; and the order of rules the Mapper uses to pick a Host, a Context and a Wrapper. Six servlets show the mapping priorities, curl shows what happens to %2F, .. and ;jsessionid, and a request object held too long shows why RequestFacade exists.
-
Digging into Tomcat's Source 8: Pipelines and Valves — The Processing Chain on Every Container
What does one <Valve> line in server.xml become in the source? We look at the pipeline each of Engine, Host, Context and Wrapper owns, the four basic valves at the ends that pick the next container, how a valve stops a request by not calling the next one, ErrorReportValve that draws the error page, the access log that is only written after the response has gone out, and the RemoteIpValve trap — checking it all against the source with our own valves hung on three containers.
-
Digging into Tomcat's Source 9: The Filter Chain and the Servlet Call — Until service() Runs
At the very end of the valve chain, Tomcat takes out a servlet instance, picks the filters that match this request, puts them in an array, and walks that array one step at a time until it finally calls service(). We follow this in the source, and use examples to check when a servlet's init() runs, how filter order is decided, how forward differs from include, and how an exception becomes an error page.
-
Digging into Tomcat's Source 10: Deploying a Web App — From a WAR to a Running Context
We follow in the source what happens inside Tomcat when you drop a WAR file into the webapps folder. HostConfig checks the folder every 10 seconds and creates a Context, ContextConfig merges web.xml, conf/web.xml and annotations and finds ServletContainerInitializers, and StandardContext.startInternal() wakes up SCIs, listeners, filters and servlets in a fixed order. We also look, from Tomcat's side, at where Spring's SpringServletContainerInitializer gets called.
-
Digging into Tomcat's Source 11: Sessions — How JSESSIONID Is Made and Removed
We follow, in the source, what Tomcat does behind one call to request.getSession() — where it reads the session ID, how it makes a new one, and when it throws it away. Cookies and ;jsessionid, the 32-character ID built from SecureRandom, the two kinds of expiry (on a request and on a background thread), and StandardManager saving sessions to a file across restarts, each checked with a small example.
-
Digging into Tomcat's Source 12: Async Servlets and Non-Blocking I/O — Letting Go of the Thread
A servlet that calls startAsync() returns without finishing its response, and the request thread goes back to the pool. We follow, in Tomcat's source and with examples that print thread names, the AsyncStateMachine that holds the request in the meantime, the path complete() and dispatch() take back to a container thread, the timeout check that runs once a second, and how a ReadListener works together with the Poller.
-
Digging into Tomcat's Source 13: Jasper — How a JSP Becomes a Servlet
What happens inside Tomcat the first time you request hello.jsp? We follow the Jasper source as JspServlet takes the request, reads the JSP file into a node tree, writes it out as Java source, compiles it with ecj, leaves a .class in the work directory, and then calls that class like any servlet. We open the generated .java file, and use examples to see when an edited JSP gets recompiled (development, modificationTestInterval, checkInterval).
-
Digging into Tomcat's Source 14: Authentication and Realms — How security-constraint Is Enforced
We follow how web.xml's security-constraint and login-config, server.xml's Realm and tomcat-users.xml connect in the source. Where the Authenticator valve is plugged in when a web app starts, the order of checks in AuthenticatorBase.invoke(), the four searches that pick the constraints for a URL, how BASIC and FORM differ, and what the Realm and the CredentialHandler do — all checked against the real source and real 401, 403 and 303 responses.
-
Digging into Tomcat's Source 15: HTTP/2 and WebSocket — Protocols Reached by Upgrading
We follow, through Tomcat's source, how a connection that started as HTTP/1.1 turns into HTTP/2 or WebSocket. UpgradeProtocol and UpgradeToken, the upgrade handling in Http11Processor, Http2UpgradeHandler carrying many streams on one connection, and WebSocket's WsFilter and WsHttpUpgradeHandler, which come in through a single filter — all checked by hand with h2c requests and the JDK WebSocket client.
-
Digging into Tomcat's Source 16: Embedded Tomcat, JMX and Logging — and Wrapping Up the Series
What the startup/Tomcat class builds for you when you start Tomcat from code without server.xml, and what it does not; how every component registers an MBean for JMX; and how JULI's ClassLoaderLogManager gives each web app its own logging configuration — all checked against the source and with examples, followed by a look back over the 16-part series.