← Back to all projects

LEARN APACHE TOMCAT DEEP DIVE

Learn Apache Tomcat: From Zero to Servlet Container Master

Goal: Deeply understand the Apache Tomcat servlet container—from the Servlet and JSP specifications to its core architecture, security, and advanced features.


Why Learn Apache Tomcat?

Apache Tomcat is the most widely used Java web server and servlet container in the world. It powers countless applications, from small websites to large enterprise systems. Understanding Tomcat is not just about deploying a .war file; it’s about understanding the foundation of the Java web ecosystem.

After completing these projects, you will:

  • Understand the Java Servlet lifecycle inside and out.
  • Master JSP for dynamic view generation.
  • Configure and tune Tomcat for production environments.
  • Grasp Tomcat’s architecture: Catalina, Coyote, and Jasper.
  • Implement custom components like Valves and Realms to extend Tomcat’s functionality.
  • Be able to build and debug complex Java web applications with confidence.

Core Concept Analysis

1. The Servlet Container Model

Tomcat is a Servlet Container. It manages the lifecycle of Java objects called Servlets, which handle HTTP requests.

┌──────────────────────────┐      ┌───────────────────────────┐      ┌──────────────────────────┐
│        Web Browser       │      │       Apache Tomcat       │      │      Your Web App        │
│                          │      │                           │      │                          │
│   GET /hello HTTP/1.1    │─────▶│  Coyote (HTTP Connector)  │─────▶│  Catalina (The Engine)   │
│                          │      │     Parses Request        │      │                          │
└──────────────────────────┘      │                           │      │      Finds correct...    │
                              │                           │      │         Servlet        │
                              │                           │      │           │            │
                              │                           │      │           ▼            │
                              │                           │      │  ┌──────────────────┐  │
                              │                           │      │  │   Your Servlet   │  │
                              │                           │      │  │  doGet(req,res)  │  │
                              │                           │      │  └──────────────────┘  │
                              │      Generates Response     │      │                          │
                              │                           │      │                          │
◀─────────────────────────────│                           │◀─────│                          │
      HTTP/1.1 200 OK        │                           │      │                          │
       "Hello, World!"       │                           │      │                          │
                              └───────────────────────────┘      └──────────────────────────┘

2. Core Components

  • Catalina: The servlet container itself. The core engine that implements the Servlet specification, managing servlets, requests, and responses.
  • Coyote: The Connector. It listens for HTTP requests on a specific port and forwards them to Catalina. It’s the bridge between the raw network socket and your Java code.
  • Jasper: The JSP Engine. It parses .jsp files and compiles them into executable Java Servlets on the fly.

3. Configuration Hierarchy (server.xml)

Tomcat’s configuration is hierarchical and defined primarily in conf/server.xml.

<Server>
  <Service>
    <Connector port="8080" protocol="HTTP/1.1" />
    <Engine>
      <Host name="localhost" appBase="webapps">
        <Context path="/my-app" docBase="my-app.war">
          <!-- Your Web App's Specific Config -->
        </Context>
        <Valve className="org.apache.catalina.valves.AccessLogValve" />
      </Host>
    </Engine>
  </Service>
</Server>
  • Server: The entire Tomcat instance.
  • Service: A grouping of Connectors and a single Engine.
  • Connector: Defines how Tomcat receives requests (e.g., HTTP on port 8080).
  • Engine: The request processing pipeline for a Service.
  • Host: A virtual host (like localhost or yourdomain.com).
  • Context: A single web application.
  • Valve: A component that intercepts requests in the processing pipeline, like an access log recorder.

4. The Web Application (web.xml and programmatic)

Each web application is a Context. Its behavior is defined by the Servlet Specification, traditionally configured in a WEB-INF/web.xml file.

  • Servlet Declarations: <servlet>
  • Servlet Mappings: <servlet-mapping> (maps a URL pattern to a servlet)
  • Filters: Intercept requests and responses.
  • Listeners: React to application lifecycle events (e.g., startup, shutdown).
  • Modern Approach: Since Servlet 3.0, you can do all of this programmatically with annotations (@WebServlet) and programmatic configuration.

5. ClassLoading

Tomcat has a complex classloader hierarchy to isolate web applications from each other. This is crucial but can be a source of confusion.

Bootstrap (JRE classes)
   |
System (Tomcat's own classes)
   |
Common (Shared libraries for all webapps)
   |
WebApp1 (Your app's classes in WEB-INF/classes and WEB-INF/lib)
   |
WebApp2 (Isolated from WebApp1)

Project List

The following 10 projects will guide you from basic web app development to deeply understanding Tomcat’s internal workings.


Project 1: The Classic Servlet & JSP Guestbook

  • File: LEARN_APACHE_TOMCAT_DEEP_DIVE.md
  • Main Programming Language: Java
  • Alternative Programming Languages: Groovy, Kotlin (on the JVM)
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: Java Servlets, JSP, Web Fundamentals
  • Software or Tool: Apache Tomcat, Maven/Gradle
  • Main Book: “Head First Servlets & JSP, 2nd Edition” by Bryan Basham, Kathy Sierra, Bert Bates

What you’ll build: A simple web application where users can post messages to a public guestbook. The form submission will be handled by a Servlet, and the messages will be displayed using a JSP.

Why it teaches Tomcat: This is the “Hello, World!” of Java web development. It forces you to understand the most fundamental concepts: the servlet lifecycle, request dispatching, form handling, and the relationship between Servlets (controllers) and JSPs (views).

Core challenges you’ll face:

  • Creating a Servlet → maps to understanding HttpServlet, doGet(), and doPost()
  • Configuring web.xml → maps to mapping a URL path to your servlet class
  • Passing data from Servlet to JSP → maps to using RequestDispatcher and setting request attributes
  • Displaying dynamic data in a JSP → maps to using scriptlets (<% %>) and expressions (<%= %>)

Key Concepts:

  • Servlet Lifecycle: “Head First Servlets & JSP” Chapter 3
  • web.xml descriptor: “Head First Servlets & JSP” Chapter 4
  • Model-View-Controller (MVC): “Head First Servlets & JSP” Chapter 2
  • JSP Scripting Elements: Oracle JSP Docs

Difficulty: Beginner Time estimate: Weekend Prerequisites: Basic Java knowledge, familiarity with the command line.

Real world outcome: You will have a functional web application running on your local Tomcat server. You can access it in your browser, submit a form, and see the content update immediately. This provides a tangible result and a foundation for all future Java web projects.

Implementation Hints:

  1. Servlet Logic:
    • In doGet(), forward the request to your guestbook.jsp file.
    • In doPost(), retrieve the submitted message from the HttpServletRequest parameters.
    • Store the messages in a simple ArrayList held in the ServletContext (application scope) for this basic version.
    • After adding a new message, use a redirect (response.sendRedirect()) back to the guestbook page to prevent duplicate form submissions.
  2. JSP Logic:
    • Create a simple HTML form that POSTs to your servlet’s URL.
    • Use a scriptlet to retrieve the list of messages from the application scope.
    • Loop through the list and print each message.

Learning milestones:

  1. Servlet responds to a GET request → You understand the basic servlet lifecycle and URL mapping.
  2. Form submission is processed by the Servlet → You can handle POST requests and read parameters.
  3. Data is displayed dynamically on the JSP → You understand how to pass data from the backend to the frontend.
  4. Application state persists between requests → You grasp the concept of application scope.

Project 2: Build a Custom Request Logging Valve

  • File: LEARN_APACHE_TOMCAT_DEEP_DIVE.md
  • Main Programming Language: Java
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Tomcat Architecture, Request Pipeline
  • Software or Tool: Apache Tomcat
  • Main Book: “Tomcat: The Definitive Guide, 2nd Edition” by Jason Brittain & Ian F. Darwin

What you’ll build: A custom Tomcat Valve that intercepts every incoming request to log the URL, processing time, and response status to a file.

Why it teaches Tomcat: This project pulls back the curtain on Tomcat’s internal request processing pipeline. You’ll learn that Tomcat is more than just a servlet runner; it’s an extensible framework of components. You’ll see how to add your own functionality directly into the server itself.

Core challenges you’ll face:

  • Extending the ValveBase class → maps to understanding the Valve contract and its invoke method
  • Compiling and packaging the Valve → maps to creating a JAR file and placing it in Tomcat’s lib directory
  • Configuring the Valve in server.xml → maps to understanding how to insert your component into the Host or Engine pipeline
  • Measuring request time accurately → maps to the importance of calling getNext().invoke(request, response)

Key Concepts:

  • Tomcat Pipeline and Valves: “Tomcat: The Definitive Guide” Chapter 9
  • server.xml configuration: Official Tomcat Documentation on server.xml
  • Java Classloading: How Tomcat finds your Valve class from its lib directory.

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Project 1, basic understanding of Java project builds (JARs).

Real world outcome: After configuring your Valve, you’ll see a new log file appear in your Tomcat’s logs directory. For every request you make to any web app on the server, a new line will be appended with details like [2025-12-20 14:30:00] GET /my-app/index.jsp - 200 OK (15ms). This provides a powerful, real-time debugging and monitoring tool that you built yourself.

Implementation Hints:

  1. Your Valve class must extend org.apache.catalina.valves.ValveBase.
  2. The core logic goes into the invoke(Request request, Response response) method.
  3. The invoke method is a chain of responsibility. You must call getNext().invoke(request, response) to pass the request down the pipeline.
  4. To measure time, record System.currentTimeMillis() before calling getNext().invoke() and after it returns. The difference is the processing time.
  5. You can get the response status from the response.getStatus() method.
  6. Place your compiled JAR file in $CATALINA_HOME/lib.
  7. Add your valve to server.xml inside a <Host> or <Engine> element: <Valve className="com.mycompany.MyLoggingValve" />.

Learning milestones:

  1. Valve loads without errors on Tomcat startup → You’ve correctly packaged and deployed a custom server component.
  2. Basic request info is logged → You understand how to access request and response objects within the pipeline.
  3. Accurate timing is logged → You understand the chain-of-responsibility pattern.
  4. The Valve can be configured with parameters → You’ve learned how to make your server components configurable from server.xml.

Project 3: A Webapp without web.xml

  • File: LEARN_APACHE_TOMCAT_DEEP_DIVE.md
  • Main Programming Language: Java
  • Alternative Programming Languages: Kotlin, Groovy
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Modern Servlet API (Servlet 3.0+)
  • Software or Tool: Apache Tomcat 7+
  • Main Book: “Java EE 7: The Big Picture” by Dr. Danny Coward

What you’ll build: A complete web application (like the Guestbook from Project 1) that is configured entirely through Java code, with no web.xml file at all.

Why it teaches Tomcat: This project teaches the modern way of building Java web applications. You’ll learn that Tomcat (since version 7) supports the Servlet 3.0 specification, which allows for programmatic configuration. This reduces “XML hell” and keeps configuration closer to the code it affects.

Core challenges you’ll face:

  • Using the @WebServlet annotation → maps to replacing <servlet> and <servlet-mapping> tags
  • Implementing a ServletContextListener → maps to getting a hook into the application’s startup phase
  • Programmatically adding Filters and other Servlets → maps to using the ServletContext object to build your application pipeline in code
  • Understanding the web application startup sequence → maps to how Tomcat discovers and runs your listener

Key Concepts:

  • Servlet 3.0 Annotations: @WebServlet, @WebFilter, @WebListener (Baeldung Tutorial)
  • Programmatic Configuration: Official Oracle Java EE Tutorial on the topic.
  • ServletContextListener: “Head First Servlets & JSP” Chapter 10

Difficulty: Intermediate Time estimate: 1-2 days Prerequisites: Project 1, understanding of Java Annotations.

Real world outcome: You’ll have a clean, modern web application project. The entire configuration is co-located with your Java code, making it easier to read, refactor, and maintain. This is how many modern Java frameworks like Spring Boot build on top of the Servlet ecosystem.

Implementation Hints:

  1. To replace a <servlet> and <servlet-mapping>, simply add @WebServlet("/your/url") to your servlet class.
  2. Create a class that implements ServletContextListener.
  3. Annotate this class with @WebListener.
  4. Tomcat will automatically find this listener and run its contextInitialized() method on startup.
  5. Inside contextInitialized(ServletContextEvent sce), you can get the ServletContext object via sce.getServletContext().
  6. Use methods like servletContext.addServlet(...) and servletContext.addFilter(...) to build up your application dynamically. This is useful for more complex scenarios not handled by simple annotations.

Learning milestones:

  1. A servlet is accessible via an @WebServlet annotation → You’ve successfully replaced web.xml for simple cases.
  2. A @WebListener runs code on application startup → You understand the entry point for programmatic configuration.
  3. A Filter is added programmatically and intercepts requests → You can build a complete, dynamic pipeline in Java.
  4. Your application runs correctly with an empty (or no) web.xml → You have mastered modern, XML-free web app configuration.

Project 4: Configure a JNDI Database Connection Pool

  • File: LEARN_APACHE_TOMCAT_DEEP_DIVE.md
  • Main Programming Language: Java
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 1: Pure Corporate Snoozefest
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: JNDI, Database Connectivity, Resource Management
  • Software or Tool: Apache Tomcat, a database like H2 or PostgreSQL
  • Main Book: “Tomcat: The Definitive Guide, 2nd Edition” by Jason Brittain & Ian F. Darwin

What you’ll build: A servlet that performs a database query by looking up a DataSource from Tomcat’s JNDI context, instead of creating the database connection itself.

Why it teaches Tomcat: This project teaches a critical skill for enterprise Java development: decoupling your application from resource configuration. You’ll learn how to let Tomcat manage a pool of database connections, which is far more efficient and robust than managing them in your application code. This is a key feature of a real application server.

Core challenges you’ll face:

  • Configuring a Resource in context.xml → maps to telling Tomcat how to connect to the database (URL, user, pass, driver)
  • Adding the JDBC driver JAR → maps to making the database driver available to Tomcat’s classloader
  • Using JNDI to look up the DataSource → maps to the InitialContext and lookup("java:comp/env/...") pattern
  • Linking the resource in web.xml → maps to the <resource-ref> tag that connects your code to the server’s resource

Key Concepts:

  • JNDI (Java Naming and Directory Interface): What it is and why it’s used for resource lookups.
  • Connection Pooling: Why it’s critical for performance. (Baeldung on HikariCP is a great explanation).
  • Tomcat JNDI Resources HOW-TO: Official Tomcat Documentation.
  • context.xml vs server.xml: Where to place environment-specific configuration.

Difficulty: Intermediate Time estimate: 1-2 days Prerequisites: Project 1, basic SQL knowledge.

Real world outcome: Your application code will be cleaner and more portable. It will no longer contain database credentials. You can move the application from a development to a production environment just by changing the context.xml file, without touching your code. You can monitor the connection pool in Tomcat’s Manager App, seeing active and idle connections.

Implementation Hints:

  1. Download a JDBC driver (e.g., for PostgreSQL) and place the JAR in $CATALINA_HOME/lib.
  2. Define the JNDI resource in your webapp’s META-INF/context.xml. This is the preferred location.
    <Context>
      <Resource name="jdbc/myDB" auth="Container" type="javax.sql.DataSource"
                maxTotal="100" maxIdle="30" maxWaitMillis="10000"
                username="dbuser" password="dbpassword"
                driverClassName="org.postgresql.Driver"
                url="jdbc:postgresql://localhost:5432/mydatabase"/>
    </Context>
    
  3. In your web.xml, add a resource reference:
    <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/myDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
    </resource-ref>
    
  4. In your servlet code, look up the DataSource:
    Context initContext = new InitialContext();
    Context envContext  = (Context)initContext.lookup("java:comp/env");
    DataSource ds = (DataSource)envContext.lookup("jdbc/myDB");
    Connection conn = ds.getConnection();
    // ... use the connection ...
    

Learning milestones:

  1. Tomcat starts without JNDI errors → Your context.xml is correct and the JDBC driver is found.
  2. Servlet successfully looks up the DataSource → Your JNDI lookup code and web.xml reference are correct.
  3. Database query succeeds → The entire chain, from servlet to Tomcat to the database, is working.
  4. You can see the connection pool stats in the Manager App → You have tangible proof that Tomcat is managing the resource pool.

Project 5: Implement a Custom Security Realm

  • File: LEARN_APACHE_TOMCAT_DEEP_DIVE.md
  • Main Programming Language: Java
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Java EE Security, Tomcat Architecture, Authentication
  • Software or Tool: Apache Tomcat
  • Main Book: “Java EE Security for Architects” by Tomitribe

What you’ll build: A custom Tomcat Realm that authenticates users against a simple properties file (users.properties) and assigns them roles. You will then use this Realm to protect a web application.

Why it teaches Tomcat: This project dives deep into Tomcat’s security architecture. You’ll replace one of Tomcat’s core pluggable components. You’ll learn how Tomcat separates security policy (who can access what) from security mechanism (how users are authenticated).

Core challenges you’ll face:

  • Extending RealmBase → maps to implementing the authenticate() and getName() methods
  • Parsing a custom user store → maps to reading your users.properties file and caching credentials securely
  • Implementing the authenticate() method → maps to validating passwords and returning a GenericPrincipal with correct roles
  • Configuring server.xml and web.xml → maps to telling Tomcat to use your Realm and defining protected resources

Key Concepts:

  • Tomcat Realms: Official Tomcat Documentation on Realms.
  • Java EE Declarative Security: Using web.xml to define security constraints, login methods, and roles.
  • Principal and Authentication: The core objects representing a user and the process of verifying them.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Project 2 and 4, solid understanding of Java.

Real world outcome: You’ll be able to protect a page in your web app. When an unauthenticated user tries to access it, they will be redirected to a login form. After authenticating against your custom Realm, they will be granted access. You’ll have built a fundamental component for any serious application.

Implementation Hints:

  1. Your Realm class must extend org.apache.catalina.realm.RealmBase.
  2. The most important method is authenticate(String username, String credentials). In it, you’ll look up the user in your properties file. If the password matches, you return a GenericPrincipal object containing the username and a list of their roles.
  3. You also need to implement getPrincipal(String username).
  4. Package your Realm as a JAR and place it in $CATALINA_HOME/lib.
  5. In server.xml, configure your Realm inside the <Host> or <Engine>:
    <Realm className="com.mycompany.MyCustomRealm" userFile="/path/to/users.properties" />
    
  6. In your web app’s web.xml, define the security constraint:
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Protected Area</web-resource-name>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>administrator</role-name>
        </auth-constraint>
    </security-constraint>
    
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/login-error.jsp</form-error-page>
        </form-login-config>
    </login-config>
    
    <security-role>
        <role-name>administrator</role-name>
    </security-role>
    

Learning milestones:

  1. Tomcat loads your Realm on startup → Packaging and server.xml configuration are correct.
  2. Unauthenticated access to a protected URL is blocked → The security constraint in web.xml is working.
  3. A user can log in successfully via a form → Your authenticate method works correctly.
  4. A user with the wrong role is denied access → Your role handling and GenericPrincipal creation are correct.

Project 6: A Real-time Chat App with WebSockets

  • File: LEARN_APACHE_TOMCAT_DEEP_DIVE.md
  • Main Programming Language: Java, JavaScript
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: WebSockets, Asynchronous Communication
  • Software or Tool: Apache Tomcat 7+
  • Main Book: “Java WebSocket Programming” by Danny Coward

What you’ll build: A simple web-based chat room where multiple users can connect and exchange messages in real-time, powered by Tomcat’s native WebSocket support.

Why it teaches Tomcat: This project teaches you how Tomcat handles persistent, stateful connections beyond the simple request-response model of HTTP. You will learn how to manage the lifecycle of WebSocket connections and broadcast messages to multiple clients efficiently.

Core challenges you’ll face:

  • Creating a WebSocket Endpoint → maps to using the @ServerEndpoint annotation and implementing lifecycle methods like @OnOpen, @OnMessage, @OnClose
  • Managing Client Sessions → maps to keeping a collection of active Session objects to broadcast messages to
  • Handling Concurrency → maps to ensuring your collection of sessions is accessed in a thread-safe manner
  • Writing the JavaScript client → maps to using the browser’s WebSocket API to connect to your endpoint and exchange messages

Key Concepts:

  • Java API for WebSocket (JSR 356): The standard API implemented by Tomcat.
  • WebSocket Lifecycle: The @OnOpen, @OnMessage, @OnClose, @OnError events.
  • Session Management: Tracking connected clients.
  • Broadcasting: Sending a message to all connected clients.

Difficulty: Intermediate Time estimate: Weekend Prerequisites: Project 1, basic JavaScript.

Real world outcome: You’ll have a functioning real-time chat application. When you open the chat page in two different browser windows, messages typed in one will instantly appear in the other. This demonstrates a powerful, modern web capability and your ability to implement it.

Implementation Hints:

  1. Create a Java class and annotate it with @ServerEndpoint("/chat").
  2. This class is a singleton by default. You need a static, thread-safe collection (like Collections.synchronizedSet(new HashSet<>())) to store Session objects.
  3. In the @OnOpen method, add the new Session to your collection.
  4. In the @OnClose method, remove the Session from your collection.
  5. In the @OnMessage method, iterate over your collection of sessions and use session.getBasicRemote().sendText(message) to broadcast the received message to every connected client. Be mindful of concurrency issues here.
  6. The client-side JavaScript is simple:
    const socket = new WebSocket("ws://localhost:8080/your-app/chat");
    socket.onmessage = function(event) {
        // append event.data to your chat log
    };
    function sendMessage() {
        socket.send(message);
    }
    

Learning milestones:

  1. JavaScript client successfully connects to the Java endpoint → Your @ServerEndpoint is correctly deployed and configured.
  2. Messages sent from the client are received by the server → Your @OnMessage method is working.
  3. A message sent by one client is broadcast to all other clients → You have successfully implemented session management and broadcasting.
  4. The server correctly handles clients disconnecting → Your @OnClose logic is robust.

Project 7: Build a Tiny Servlet Container from Scratch

  • File: LEARN_APACHE_TOMCAT_DEEP_DIVE.md
  • Main Programming Language: Java
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 4: Expert
  • Knowledge Area: Networking, HTTP, Java Reflection, Classloading
  • Software or Tool: Just a Java compiler and a dream.
  • Main Book: “How Tomcat Works: A Guide to Developing Your Own Java Servlet Container” by Budi Kurniawan and Paul Deck

What you’ll build: A simple program that acts like Tomcat. It will open a server socket, listen for HTTP requests, parse them, and pass them to a hard-coded servlet. It will then take the servlet’s output and format it as a valid HTTP response.

Why it teaches Tomcat: This is the ultimate project for understanding Tomcat. By building a (very) simplified version of it, you demystify the entire process. You will finally understand what a “container” truly is: a program that manages the lifecycle of other programs according to a specific contract (the Servlet API).

Core challenges you’ll face:

  • Opening a ServerSocket and parsing raw HTTP → maps to implementing a miniature Coyote
  • Creating mock HttpServletRequest and HttpServletResponse objects → maps to understanding the Servlet API from the container’s perspective
  • Loading a servlet class using reflection → maps to dynamically loading and instantiating servlets
  • Managing the servlet lifecycle → maps to calling init() once and service() for each request

Key Concepts:

  • Socket Programming: java.net.ServerSocket and java.net.Socket.
  • HTTP/1.1 Protocol: The structure of a raw request and response (Request Line, Headers, Body).
  • Java Reflection: Class.forName(), newInstance().
  • The Servlet API contract: The methods and objects a container must provide.

Difficulty: Expert Time estimate: 1-2 weeks Prerequisites: Project 1, strong Java skills, basic understanding of the HTTP protocol.

Real world outcome: You will run a single Java main method. You can then open your web browser to http://localhost:8080 and see the output of a servlet you wrote, served by your own container. You’ve essentially built a micro-Tomcat.

Implementation Hints:

Phase 1: A Static Web Server

  1. Create a main method that opens a ServerSocket on a port (e.g., 8080).
  2. Create an infinite loop that calls serverSocket.accept() to get a Socket for each new connection.
  3. For each Socket, get its InputStream and OutputStream.
  4. Read the first line of the InputStream (the HTTP request line, e.g., GET /index.html HTTP/1.1).
  5. Based on the requested path, find a local file.
  6. Write a valid HTTP response to the OutputStream (e.g., HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n) followed by the file’s content.

Phase 2: Add Servlet Support

  1. Modify the request parsing. If the URL matches a servlet path (e.g., /servlet/MyServlet), don’t look for a file.
  2. Create simple implementations of the HttpServletRequest and HttpServletResponse interfaces. You’ll need to parse headers and parameters from the InputStream to populate your request object.
  3. Use reflection (Class.forName("com.mycompany.MyServlet").newInstance()) to create an instance of the servlet.
  4. Call its service() method, passing your mock request and response objects.
  5. After the service() method returns, take the content written to your response object’s writer/stream and wrap it in an HTTP response.

Learning milestones:

  1. Your server can serve a static HTML file → You understand basic socket programming and the HTTP protocol.
  2. Your server can receive a request and instantiate the correct servlet → You’ve mastered reflection and request routing.
  3. The servlet can read request parameters and headers → Your HttpServletRequest implementation is working.
  4. The servlet’s output is correctly displayed in the browser → Your HttpServletResponse implementation and response formatting are correct.

Summary of Projects

Project Main Language Difficulty Time Estimate Core Concept Taught
1. Classic Servlet & JSP Guestbook Java Beginner Weekend Servlet Lifecycle, JSP, web.xml
2. Custom Request Logging Valve Java Intermediate Weekend Tomcat Pipeline, server.xml
3. A Webapp without web.xml Java Intermediate 1-2 days Servlet 3.0+ Programmatic API
4. JNDI Database Connection Pool Java Intermediate 1-2 days JNDI, Resource Management, Connection Pools
5. Implement a Custom Security Realm Java Advanced 1-2 weeks Tomcat Security, Authentication, Realms
6. Real-time Chat App with WebSockets Java, JavaScript Intermediate Weekend WebSockets, Asynchronous Communication
7. Build a Tiny Servlet Container Java Expert 1-2 weeks The entire container model from scratch

I recommend starting with Project 1: The Classic Servlet & JSP Guestbook. It’s the quintessential starting point that covers 80% of what you’ll do in day-to-day Java web development and builds the foundation needed for all the other projects. After that, move to Project 3: A Webapp without web.xml to modernize your knowledge before tackling more advanced topics like Valves and Realms. Good luck!