Jakarta Servlets Interview Questions and Answers

Master Jakarta Servlets with production-ready interview questions covering the Servlet lifecycle, HTTP methods, request and response handling, filters, listeners, sessions, cookies, dispatching, thread safety, async processing, and senior-level best practices.


Introduction

Jakarta Servlet is the foundational web specification for handling HTTP requests and responses in Jakarta EE applications.

Servlets provide the low-level web programming model used by many higher-level frameworks and specifications.

A Servlet can:

  • Receive HTTP requests
  • Read headers, parameters, cookies, and body content
  • Execute application logic
  • Set response status and headers
  • Write HTML, JSON, files, or binary data
  • Forward or include requests
  • Manage sessions
  • Start asynchronous processing
  • Participate in filters and listeners
  • Integrate with security and container services

Modern applications often use Jakarta REST, JSF, or frameworks built on top of the Servlet API. However, understanding Servlets remains important because the Servlet container controls:

  • Request lifecycle
  • Threading model
  • Session lifecycle
  • Filters
  • Security integration
  • Async dispatch
  • Web application deployment

Servlets are widely discussed in Java web, Jakarta EE, Spring MVC, security, and backend interviews.

This guide covers the 15 most frequently asked Jakarta Servlet interview questions with code examples, Mermaid diagrams, production scenarios, common mistakes, and senior-level recommendations.


Q1. What is a Servlet?

Answer

A Servlet is a server-side Java component managed by a Servlet container to process client requests and generate responses.

Most Servlets extend HttpServlet.

Example

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/hello")
public class HelloServlet
    extends HttpServlet {

    @Override
    protected void doGet(
        HttpServletRequest request,
        HttpServletResponse response
    ) throws IOException {

        response.setContentType(
            "text/plain"
        );

        response
            .getWriter()
            .write(
                "Hello from Jakarta Servlet"
            );
    }
}

Request Flow

flowchart TD
    A[Browser] --> B[Servlet Container]
    B --> C[URL Mapping]
    C --> D[Servlet Instance]
    D --> E[doGet or doPost]
    E --> F[HTTP Response]
    F --> A

Why Interviewers Ask This

Servlets are the foundation of Jakarta web applications and help explain how higher-level web frameworks operate.

Production Example

A Servlet may stream a large export file or act as a low-level callback endpoint.

Common Mistake

Describing a Servlet as a standalone web server.

Senior Follow-up

The Servlet is managed by a container that provides request dispatching, lifecycle, threading, security, session handling, and resource management.


Q2. Explain the Servlet lifecycle.

Answer

The Servlet container manages the complete Servlet lifecycle.

The main phases are:

  1. Class loading
  2. Instantiation
  3. Initialization
  4. Request processing
  5. Destruction

Lifecycle Methods

  • init()
  • service()
  • destroy()

Lifecycle Diagram

stateDiagram-v2
    [*] --> ClassLoaded
    ClassLoaded --> ServletCreated
    ServletCreated --> Initialized: init()
    Initialized --> Processing: service()
    Processing --> Processing: More requests
    Processing --> Destroyed: destroy()
    Destroyed --> [*]

Lifecycle Flow

flowchart TD
    A[Deploy Application] --> B[Load Servlet Class]
    B --> C[Create Servlet Instance]
    C --> D[Call init Once]
    D --> E[Receive HTTP Requests]
    E --> F[Call service for Each Request]
    F --> E
    E --> G[Application Shutdown or Redeploy]
    G --> H[Call destroy Once]

Important Behavior

Typically:

  • One Servlet instance handles many requests.
  • init() runs once.
  • service() runs for every request.
  • destroy() runs once before removal.

Common Mistake

Assuming a new Servlet instance is created for each request.

Senior Follow-up

Because one instance may handle concurrent requests, mutable instance fields create thread-safety risks.


Q3. What are init(), service(), and destroy()?

Answer

These methods define the Servlet lifecycle.

init()

Called once after the container creates the Servlet.

Use it for lightweight initialization.

@Override
public void init()
    throws ServletException {

    // Initialize configuration
}

service()

Called for each incoming request.

For HttpServlet, service() routes the request to methods such as:

  • doGet()
  • doPost()
  • doPut()
  • doDelete()
  • doHead()
  • doOptions()

destroy()

Called once before the Servlet is removed.

@Override
public void destroy() {

    // Release owned resources
}

Invocation Flow

sequenceDiagram
    participant Container
    participant Servlet
    Container->>Servlet: Constructor
    Container->>Servlet: init()
    loop Every request
        Container->>Servlet: service()
        Servlet-->>Container: response
    end
    Container->>Servlet: destroy()

Best Practices

  • Keep init() fast.
  • Do not open unmanaged database connections and keep them forever.
  • Use container-managed resources.
  • Release only resources owned by the Servlet.
  • Do not place per-request state in instance fields.

Common Mistake

Performing slow remote calls in init() and delaying application startup.

Senior Follow-up

Use dependency injection and container-managed services instead of building large custom lifecycle logic inside a Servlet.


Q4. What is the difference between doGet() and doPost()?

Answer

doGet() handles HTTP GET requests.

doPost() handles HTTP POST requests.

Comparison

GET POST
Retrieves data Submits or creates data
Should be safe May change server state
Should be idempotent Not necessarily idempotent
Parameters often in URL Data usually in request body
Can be cached Usually not cached by default
Can be bookmarked Usually not bookmarked
URL length limitations Supports larger payloads

GET Example

@Override
protected void doGet(
    HttpServletRequest request,
    HttpServletResponse response
) throws IOException {

    String customerId =
        request.getParameter(
            "customerId"
        );

    response
        .getWriter()
        .write(
            "Customer: "
                + customerId
        );
}

POST Example

@Override
protected void doPost(
    HttpServletRequest request,
    HttpServletResponse response
) throws IOException {

    String name =
        request.getParameter("name");

    response.setStatus(
        HttpServletResponse.SC_CREATED
    );

    response
        .getWriter()
        .write(
            "Created customer: "
                + name
        );
}

HTTP Semantics

flowchart LR
    A[GET] --> B[Read Resource]
    C[POST] --> D[Create or Process Resource]
    E[PUT] --> F[Replace Resource]
    G[PATCH] --> H[Partially Update Resource]
    I[DELETE] --> J[Remove Resource]

Common Mistake

Using GET for operations that modify data.

Senior Follow-up

HTTP method selection should preserve semantic safety, idempotency, caching behavior, and retry expectations.


Q5. Servlet vs JSP?

Answer

A Servlet is a Java class used for request processing and response generation.

JSP was historically used as a server-side view technology for generating HTML.

Comparison

Servlet JSP
Java class Template-style page
Better for control flow Better for presentation
Handles request logic Renders HTML
Compiled by developer Translated into Servlet
Harder to write large HTML Easier to write markup
Controller-style role View-style role

Traditional MVC Flow

flowchart TD
    A[Browser Request] --> B[Servlet Controller]
    B --> C[Service Layer]
    C --> D[Model Data]
    D --> B
    B --> E[JSP View]
    E --> F[HTML Response]

Request Forward

request.setAttribute(
    "customer",
    customer
);

request
    .getRequestDispatcher(
        "/WEB-INF/views/customer.jsp"
    )
    .forward(
        request,
        response
    );

Common Mistake

Embedding business logic directly inside JSP pages.

Senior Follow-up

Modern APIs frequently return JSON rather than JSP views, but the Servlet MVC model remains important for understanding framework architecture.


Q6. What is HttpServletRequest?

Answer

HttpServletRequest represents the incoming HTTP request.

It provides access to:

  • HTTP method
  • URL
  • Headers
  • Query parameters
  • Form parameters
  • Cookies
  • Request body
  • Session
  • Request attributes
  • Authentication information
  • Locale
  • Network information

Example

protected void doGet(
    HttpServletRequest request,
    HttpServletResponse response
) throws IOException {

    String method =
        request.getMethod();

    String userAgent =
        request.getHeader(
            "User-Agent"
        );

    String page =
        request.getParameter(
            "page"
        );

    HttpSession session =
        request.getSession(false);
}

Request Data Sources

flowchart TD
    A[HttpServletRequest] --> B[Path]
    A --> C[Query Parameters]
    A --> D[Headers]
    A --> E[Cookies]
    A --> F[Body]
    A --> G[Session]
    A --> H[Security Principal]
    A --> I[Request Attributes]

Request Attributes

Attributes allow server-side components to share data during one request.

request.setAttribute(
    "correlationId",
    correlationId
);

Common Mistake

Confusing request parameters with request attributes.

Senior Follow-up

Parameters originate from the client request, while attributes are server-side values attached during processing.


Q7. What is HttpServletResponse?

Answer

HttpServletResponse represents the outgoing HTTP response.

It allows the Servlet to configure:

  • Status code
  • Headers
  • Cookies
  • Content type
  • Character encoding
  • Response body
  • Redirects
  • Errors
  • File downloads

JSON Example

protected void doGet(
    HttpServletRequest request,
    HttpServletResponse response
) throws IOException {

    response.setStatus(
        HttpServletResponse.SC_OK
    );

    response.setContentType(
        "application/json"
    );

    response.setCharacterEncoding(
        "UTF-8"
    );

    response
        .getWriter()
        .write(
            """
            {
              "status": "UP"
            }
            """
        );
}

Download Example

response.setContentType(
    "text/csv"
);

response.setHeader(
    "Content-Disposition",
    "attachment; filename=\"customers.csv\""
);

Response Flow

flowchart TD
    A[Servlet] --> B[Set Status]
    B --> C[Set Headers]
    C --> D[Set Content Type]
    D --> E[Write Body]
    E --> F[Container Commits Response]
    F --> G[Client Receives Response]

Committed Response

After the response is committed, changing status or headers may no longer be possible.

Common Mistake

Writing part of the body and then attempting a redirect.

Senior Follow-up

Buffering and commit timing matter for exception handling and streaming responses.


Q8. What are Servlet filters?

Answer

Filters intercept requests and responses before or after a Servlet or resource processes them.

Common uses include:

  • Authentication
  • Authorization
  • Logging
  • Correlation IDs
  • CORS
  • Compression
  • Request wrapping
  • Response headers
  • Metrics
  • Input sanitization

Filter Example

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.util.UUID;

@WebFilter("/*")
public class CorrelationIdFilter
    implements Filter {

    @Override
    public void doFilter(
        ServletRequest request,
        ServletResponse response,
        FilterChain chain
    ) throws IOException,
             ServletException {

        HttpServletRequest httpRequest =
            (HttpServletRequest) request;

        HttpServletResponse httpResponse =
            (HttpServletResponse) response;

        String correlationId =
            UUID.randomUUID()
                .toString();

        httpRequest.setAttribute(
            "correlationId",
            correlationId
        );

        httpResponse.setHeader(
            "X-Correlation-ID",
            correlationId
        );

        chain.doFilter(
            request,
            response
        );
    }
}

Filter Chain

sequenceDiagram
    participant Client
    participant Filter1
    participant Filter2
    participant Servlet
    Client->>Filter1: Request
    Filter1->>Filter2: chain.doFilter()
    Filter2->>Servlet: chain.doFilter()
    Servlet-->>Filter2: Response
    Filter2-->>Filter1: Response
    Filter1-->>Client: Final response

Important Rule

A filter must call:

chain.doFilter(
    request,
    response
);

unless it intentionally stops processing.

Common Mistake

Forgetting to call the filter chain and unintentionally blocking requests.

Senior Follow-up

Filter order is important because authentication, tracing, exception handling, and CORS may depend on execution sequence.


Q9. What are Servlet listeners?

Answer

Servlet listeners observe lifecycle events related to:

  • Web application context
  • HTTP sessions
  • Requests
  • Attributes

Common Listener Interfaces

Listener Purpose
ServletContextListener Application startup and shutdown
HttpSessionListener Session creation and destruction
ServletRequestListener Request lifecycle
ServletContextAttributeListener Context attribute changes
HttpSessionAttributeListener Session attribute changes
ServletRequestAttributeListener Request attribute changes

Application Listener Example

@WebListener
public class ApplicationLifecycleListener
    implements ServletContextListener {

    @Override
    public void contextInitialized(
        ServletContextEvent event
    ) {

        System.out.println(
            "Application started"
        );
    }

    @Override
    public void contextDestroyed(
        ServletContextEvent event
    ) {

        System.out.println(
            "Application stopped"
        );
    }
}

Listener Flow

flowchart TD
    A[Application Starts] --> B[ServletContextListener]
    C[Request Begins] --> D[ServletRequestListener]
    E[Session Created] --> F[HttpSessionListener]
    G[Session Destroyed] --> F
    H[Application Stops] --> B

Common Mistake

Using listeners to implement large business workflows.

Senior Follow-up

Listeners are suitable for lifecycle and infrastructure concerns, but business operations should remain in services or message-driven components.


Q10. How is session management handled?

Answer

HTTP is stateless, so the server uses session mechanisms to associate multiple requests with one client.

The Servlet API provides HttpSession.

Create or Retrieve Session

HttpSession session =
    request.getSession();

Retrieve Existing Session Only

HttpSession session =
    request.getSession(false);

Store Session Attribute

session.setAttribute(
    "cartId",
    cartId
);

Invalidate Session

session.invalidate();

Session Flow

sequenceDiagram
    participant Browser
    participant Container
    participant SessionStore
    Browser->>Container: First request
    Container->>SessionStore: Create session
    SessionStore-->>Container: Session ID
    Container-->>Browser: Set session cookie
    Browser->>Container: Next request with session cookie
    Container->>SessionStore: Lookup session
    SessionStore-->>Container: Existing session

Session Risks

  • Excessive memory usage
  • Session fixation
  • Session hijacking
  • Cluster replication overhead
  • Stale data
  • Concurrent requests from same user
  • Large serialized objects

Common Mistake

Storing large entity graphs or files in the HTTP session.

Senior Follow-up

Use sessions sparingly and keep important business state in durable backend storage.


Q11. Cookies vs HTTP sessions?

Answer

Cookies are small pieces of data stored by the browser.

HTTP sessions store state on the server and commonly use a cookie to carry the session identifier.

Comparison

Cookies HTTP Session
Stored on client Stored on server or external session store
Sent with requests Identified through session ID
Small size Can hold larger server-side state
Can persist beyond browser session Usually expires after inactivity
Visible to browser Actual data remains server-side
Security flags required Session ID security required
Cookie preference =
    new Cookie(
        "theme",
        "dark"
    );

preference.setHttpOnly(true);
preference.setSecure(true);
preference.setMaxAge(
    60 * 60 * 24 * 30
);

response.addCookie(
    preference
);
flowchart LR
    A[Browser] -->|Session ID Cookie| B[Servlet Container]
    B --> C[Server-Side Session Data]
  • HttpOnly
  • Secure
  • SameSite
  • Path
  • Domain
  • Expiration

Common Mistake

Storing sensitive information directly inside a plain-text cookie.

Senior Follow-up

Store only minimal client-side data and protect session identifiers against XSS, interception, fixation, and cross-site request attacks.


Q12. What is request dispatching?

Answer

Request dispatching allows one server-side resource to forward to or include another resource.

Forward

Transfers request processing to another resource.

RequestDispatcher dispatcher =
    request.getRequestDispatcher(
        "/WEB-INF/views/customer.jsp"
    );

dispatcher.forward(
    request,
    response
);

Include

Includes output from another resource in the current response.

dispatcher.include(
    request,
    response
);

Forward vs Redirect

Forward Redirect
Server-side Client-side
Same request New request
URL usually unchanged Browser URL changes
Request attributes preserved Request attributes lost
No extra network round trip Extra round trip
Usually same application Can target external URL

Forward Flow

sequenceDiagram
    participant Browser
    participant ServletA
    participant ServletB
    Browser->>ServletA: Request
    ServletA->>ServletB: Forward same request
    ServletB-->>Browser: Response

Redirect Flow

sequenceDiagram
    participant Browser
    participant Servlet
    Browser->>Servlet: Request
    Servlet-->>Browser: 302 Location
    Browser->>Browser: Follow new URL
    Browser->>Servlet: New request

Common Mistake

Using forward after the response has already been committed.

Senior Follow-up

Use the Post/Redirect/Get pattern after successful form submission to prevent duplicate resubmission.


Q13. Are Servlets thread-safe?

Answer

Servlet instances are not automatically thread-safe.

The container typically uses one Servlet instance to process many concurrent requests using multiple threads.

Unsafe Servlet

@WebServlet("/counter")
public class CounterServlet
    extends HttpServlet {

    private int counter;

    @Override
    protected void doGet(
        HttpServletRequest request,
        HttpServletResponse response
    ) throws IOException {

        counter++;

        response
            .getWriter()
            .write(
                String.valueOf(counter)
            );
    }
}

The increment is not atomic and requests can interfere.

Concurrency Flow

sequenceDiagram
    participant Thread1
    participant Servlet
    participant Thread2
    Thread1->>Servlet: Read counter = 10
    Thread2->>Servlet: Read counter = 10
    Thread1->>Servlet: Write counter = 11
    Thread2->>Servlet: Write counter = 11
    Note over Servlet: One increment lost

Safer Stateless Servlet

@Override
protected void doGet(
    HttpServletRequest request,
    HttpServletResponse response
) throws IOException {

    String customerId =
        request.getParameter(
            "customerId"
        );

    response
        .getWriter()
        .write(customerId);
}

Use:

  • Local variables
  • Immutable shared state
  • Thread-safe collaborators
  • Container-managed services

Common Mistake

Storing request, response, user, or session information in Servlet instance fields.

Senior Follow-up

The best Servlet design is usually stateless, with request-specific values stored in local variables or request scope.


Q14. What are common Servlet mistakes?

Answer

Common mistakes include:

  • Storing request data in instance fields.
  • Assuming one Servlet instance per request.
  • Forgetting to call chain.doFilter().
  • Using GET for state-changing operations.
  • Returning sensitive stack traces.
  • Writing response content before setting status and headers.
  • Mixing getWriter() and getOutputStream().
  • Creating unmanaged database connections.
  • Keeping sessions too large.
  • Storing entities in sessions.
  • Ignoring session fixation.
  • Not setting character encoding.
  • Trusting request parameters without validation.
  • Failing to escape HTML output.
  • Performing long blocking work on request threads.
  • Creating unmanaged threads.
  • Failing to close request-body streams when manually handled.
  • Redirecting after response commit.
  • Ignoring content type.
  • Hardcoding authentication logic in multiple Servlets.

Unsafe Shared State

@WebServlet("/profile")
public class ProfileServlet
    extends HttpServlet {

    private String currentUser;
}

Safe Request State

protected void doGet(
    HttpServletRequest request,
    HttpServletResponse response
) {

    String currentUser =
        request.getRemoteUser();
}

Mistake Impact

flowchart TD
    A[Mutable Servlet Field] --> B[Concurrent Requests]
    B --> C[Race Condition]
    C --> D[Wrong User Data]
    D --> E[Security Incident]

Interview Tip

Strong candidates explain Servlet threading and lifecycle rather than only method names.


Q15. What are senior-level Servlet best practices?

Answer

Senior developers should keep Servlets thin, stateless, secure, and focused on HTTP concerns.

Best Practices

  • Keep Servlets stateless.
  • Store request data in local variables.
  • Delegate business logic to services.
  • Use filters for cross-cutting web concerns.
  • Use listeners only for lifecycle concerns.
  • Validate all input.
  • Set correct content type and encoding.
  • Use meaningful status codes.
  • Avoid leaking stack traces.
  • Protect cookies and sessions.
  • Regenerate session IDs after authentication.
  • Limit session size.
  • Use container-managed resources.
  • Avoid unmanaged threads.
  • Use async processing only when appropriate.
  • Stream large files instead of loading them fully.
  • Apply timeouts and request-size limits.
  • Add correlation IDs.
  • Monitor request latency and thread-pool usage.
  • Prefer Jakarta REST for resource-oriented APIs.

Servlet Design Flow

flowchart TD
    A[HTTP Request] --> B[Filter Chain]
    B --> C[Servlet]
    C --> D[Validate Input]
    D --> E[Call Application Service]
    E --> F[Create Response Model]
    F --> G[Set Status and Headers]
    G --> H[Write Response]
    H --> I[Monitoring]

Senior Follow-up

Servlets should remain protocol adapters. Business rules, transaction management, and persistence should live in dedicated application layers.


Servlet Mapping

Annotation Mapping

@WebServlet(
    name = "CustomerServlet",
    urlPatterns = {
        "/customers",
        "/customers/*"
    },
    loadOnStartup = 1
)
public class CustomerServlet
    extends HttpServlet {
}

XML Mapping

<servlet>
    <servlet-name>
        CustomerServlet
    </servlet-name>

    <servlet-class>
        com.codewithvenu.CustomerServlet
    </servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>
        CustomerServlet
    </servlet-name>

    <url-pattern>
        /customers/*
    </url-pattern>
</servlet-mapping>

Mapping Flow

flowchart LR
    A[/customers/101] --> B[Servlet Container]
    B --> C[URL Pattern Match]
    C --> D[CustomerServlet]

Servlet Request Lifecycle

sequenceDiagram
    participant Client
    participant Connector
    participant FilterChain
    participant Servlet
    participant Service
    Client->>Connector: HTTP request
    Connector->>FilterChain: Create request and response
    FilterChain->>Servlet: Invoke service()
    Servlet->>Service: Execute use case
    Service-->>Servlet: Result
    Servlet-->>FilterChain: Write response
    FilterChain-->>Connector: Complete processing
    Connector-->>Client: HTTP response

HTTP Method Dispatch

flowchart TD
    A[HttpServlet service] --> B{HTTP Method}
    B -->|GET| C[doGet]
    B -->|POST| D[doPost]
    B -->|PUT| E[doPut]
    B -->|DELETE| F[doDelete]
    B -->|HEAD| G[doHead]
    B -->|OPTIONS| H[doOptions]
    B -->|TRACE| I[doTrace]

Request Data Model

flowchart TD
    A[HTTP Request] --> B[Method]
    A --> C[URI]
    A --> D[Query String]
    A --> E[Headers]
    A --> F[Cookies]
    A --> G[Body]
    A --> H[Session ID]
    A --> I[Security Principal]

    B --> J[HttpServletRequest]
    C --> J
    D --> J
    E --> J
    F --> J
    G --> J
    H --> J
    I --> J

Response Data Model

flowchart TD
    A[HttpServletResponse] --> B[Status Code]
    A --> C[Headers]
    A --> D[Cookies]
    A --> E[Content Type]
    A --> F[Character Encoding]
    A --> G[Response Body]

Character Encoding

For form or body data, set encoding before reading parameters where needed.

request.setCharacterEncoding(
    "UTF-8"
);

response.setCharacterEncoding(
    "UTF-8"
);

response.setContentType(
    "application/json"
);

Common Problem

Incorrect encoding can corrupt:

  • International names
  • Special symbols
  • Non-English messages
  • JSON payloads

Error Handling

Sending Error

response.sendError(
    HttpServletResponse
        .SC_BAD_REQUEST,
    "Invalid customer ID"
);

Structured JSON Error

response.setStatus(
    HttpServletResponse
        .SC_BAD_REQUEST
);

response.setContentType(
    "application/json"
);

response
    .getWriter()
    .write(
        """
        {
          "code": "INVALID_REQUEST",
          "message": "Customer ID is required"
        }
        """
    );

Error Flow

flowchart TD
    A[Request Processing] --> B{Exception?}
    B -->|No| C[Return Success]
    B -->|Yes| D[Map Exception]
    D --> E[Set HTTP Status]
    E --> F[Return Safe Error Body]
    F --> G[Log Internal Details]

Post/Redirect/Get Pattern

sequenceDiagram
    participant Browser
    participant Servlet
    participant Database
    Browser->>Servlet: POST form
    Servlet->>Database: Save data
    Database-->>Servlet: Success
    Servlet-->>Browser: 303 Redirect
    Browser->>Servlet: GET result page
    Servlet-->>Browser: Render response

Benefit

Refreshing the final page does not repeat the original POST.


Session Fixation Protection

After successful authentication, change the session ID.

request.changeSessionId();

Flow

flowchart TD
    A[Unauthenticated Session ID] --> B[User Logs In]
    B --> C[Regenerate Session ID]
    C --> D[Authenticated Session]

Cookie Security Example

Cookie sessionPreference =
    new Cookie(
        "language",
        "en"
    );

sessionPreference.setHttpOnly(true);
sessionPreference.setSecure(true);
sessionPreference.setPath("/");

response.addCookie(
    sessionPreference
);

SameSite handling may require response-header configuration depending on runtime support.


Servlet Filters by Concern

Filter Type Purpose
Authentication Filter Verify identity
Authorization Filter Check permission
CORS Filter Cross-origin policy
Logging Filter Request and response logs
Correlation Filter Distributed tracing ID
Compression Filter Compress response
Security Header Filter Add CSP and related headers
Encoding Filter Force UTF-8
Rate-Limit Filter Limit request frequency
Exception Filter Convert failures to safe responses

Filter Ordering

flowchart LR
    A[Request] --> B[Correlation Filter]
    B --> C[Security Header Filter]
    C --> D[Authentication Filter]
    D --> E[Authorization Filter]
    E --> F[Servlet]
    F --> G[Response]

Order affects behavior and must be defined intentionally.


Request Wrapper Example

A filter can wrap a request to customize behavior.

HttpServletRequestWrapper wrapper =
    new HttpServletRequestWrapper(
        httpRequest
    ) {

        @Override
        public String getHeader(
            String name
        ) {

            if (
                "X-Tenant-ID"
                    .equalsIgnoreCase(name)
            ) {
                return normalizedTenantId;
            }

            return super.getHeader(name);
        }
    };

Use wrappers carefully so they do not hide important security or protocol behavior.


Response Wrapper Use Cases

Response wrappers can support:

  • Response caching
  • Audit capture
  • Compression
  • Body transformation
  • Metrics
  • Security-header enforcement

Avoid buffering huge responses in memory.


Asynchronous Servlet Processing

Servlet async support allows the request thread to be released while work continues.

Enable Async

@WebServlet(
    value = "/reports",
    asyncSupported = true
)
public class ReportServlet
    extends HttpServlet {
}

Example

@Override
protected void doGet(
    HttpServletRequest request,
    HttpServletResponse response
) {

    AsyncContext asyncContext =
        request.startAsync();

    asyncContext.setTimeout(
        30_000
    );

    asyncContext.start(
        () -> {

            try {
                HttpServletResponse asyncResponse =
                    (HttpServletResponse)
                        asyncContext
                            .getResponse();

                asyncResponse
                    .setContentType(
                        "text/plain"
                    );

                asyncResponse
                    .getWriter()
                    .write(
                        "Report completed"
                    );
            } catch (IOException exception) {
                throw new RuntimeException(
                    exception
                );
            } finally {
                asyncContext.complete();
            }
        }
    );
}

Async Lifecycle

sequenceDiagram
    participant Client
    participant RequestThread
    participant AsyncTask
    participant Response
    Client->>RequestThread: Request
    RequestThread->>AsyncTask: startAsync()
    RequestThread-->>RequestThread: Return thread to pool
    AsyncTask->>AsyncTask: Perform work
    AsyncTask->>Response: Write result
    AsyncTask->>Response: complete()
    Response-->>Client: Final response

Important Warning

Asynchronous processing does not automatically make blocking work efficient. It changes thread usage and requires correct timeout, error, and context handling.


Async Listener

asyncContext.addListener(
    new AsyncListener() {

        @Override
        public void onComplete(
            AsyncEvent event
        ) {
        }

        @Override
        public void onTimeout(
            AsyncEvent event
        ) {
        }

        @Override
        public void onError(
            AsyncEvent event
        ) {
        }

        @Override
        public void onStartAsync(
            AsyncEvent event
        ) {
        }
    }
);

Blocking vs Async Processing

Synchronous Servlet Async Servlet
Request thread held Request thread can be released
Simpler flow More lifecycle complexity
Suitable for fast work Suitable for deferred response
Easier transaction context Context propagation must be handled
Blocking remote call holds thread Work can continue separately

Async Servlet is not the same as a fully non-blocking reactive architecture.


File Upload Considerations

Servlet applications can handle multipart requests.

@MultipartConfig(
    maxFileSize = 10 * 1024 * 1024,
    maxRequestSize =
        20 * 1024 * 1024
)
@WebServlet("/upload")
public class UploadServlet
    extends HttpServlet {
}

Best Practices

  • Enforce file size limits.
  • Validate content type.
  • Generate safe storage names.
  • Never trust original file names.
  • Scan files where required.
  • Stream to storage.
  • Prevent path traversal.
  • Apply authentication and authorization.

Large File Download

try (
    InputStream input =
        fileService.openStream(fileId);

    ServletOutputStream output =
        response.getOutputStream()
) {

    input.transferTo(output);
}

Avoid loading the complete file into a byte array for large downloads.


Session Concurrency

The same HTTP session may receive concurrent requests.

sequenceDiagram
    participant Tab1
    participant SessionBean
    participant Tab2
    Tab1->>SessionBean: Update cart
    Tab2->>SessionBean: Update cart
    Note over SessionBean: Concurrent access possible

Session-scoped mutable state may still require concurrency control.


Servlet Context

ServletContext represents the web application.

Common Uses

  • Access initialization parameters
  • Share immutable application metadata
  • Retrieve resources
  • Register components programmatically
  • Log application events
ServletContext context =
    getServletContext();

String applicationName =
    context.getInitParameter(
        "applicationName"
    );

Warning

Mutable objects stored in ServletContext are shared across the application and must be thread-safe.


Request vs Session vs Context Scope

Scope Lifetime Shared By
Request attribute One request Components in same request
Session attribute User session Requests using same session
ServletContext attribute Application lifetime All application requests

Servlet Thread Model

flowchart TD
    A[Incoming Requests] --> B[Container Thread Pool]
    B --> C[Thread 1]
    B --> D[Thread 2]
    B --> E[Thread N]

    C --> F[Same Servlet Instance]
    D --> F
    E --> F

This is why Servlet instance fields must be handled carefully.


Low-Level Servlet Architecture

flowchart TD
    A[Client] --> B[HTTP Connector]
    B --> C[Servlet Container]
    C --> D[Filter Chain]
    D --> E[Servlet Mapping]
    E --> F[HttpServlet]
    F --> G[Application Service]
    G --> H[Database or External Service]
    H --> G
    G --> F
    F --> D
    D --> C
    C --> B
    B --> A

Servlet vs Jakarta REST

Servlet Jakarta REST
Low-level HTTP API Resource-oriented REST API
Manual status and body handling Annotation-driven HTTP mapping
Manual parameter extraction Parameter injection
Useful for streaming and low-level control Better for standard JSON APIs
Foundation of web container Higher-level abstraction
More boilerplate Cleaner REST design

Production Monitoring

Monitor:

  • Request count
  • Response status distribution
  • Request latency
  • Active request threads
  • Queue length
  • Session count
  • Session size
  • Async timeout count
  • Upload and download throughput
  • Filter latency
  • Error count
  • Thread-pool saturation

Monitoring Flow

flowchart TD
    A[Servlet Request] --> B[Metrics Filter]
    B --> C[Servlet Processing]
    C --> D[Record Status and Duration]
    D --> E[Monitoring Platform]
    E --> F[Dashboard and Alerts]

Senior Servlet Checklist

Stateless Servlet
      │
      ▼
Validated Input
      │
      ▼
Correct HTTP Method
      │
      ▼
Thin Protocol Logic
      │
      ▼
Service Delegation
      │
      ▼
Safe Session Handling
      │
      ▼
Correct Status and Headers
      │
      ▼
Monitoring and Security

Interview Quick Revision

Concept Purpose
Servlet Processes HTTP requests
init() One-time initialization
service() Dispatches each request
destroy() Final cleanup
doGet() Handles GET
doPost() Handles POST
Request Incoming HTTP data
Response Outgoing HTTP data
Filter Intercepts request and response
Listener Observes lifecycle events
Session Server-side user state
Cookie Client-side HTTP state
Forward Server-side dispatch
Redirect Client-side new request
AsyncContext Deferred Servlet response

Key Takeaways

  • Jakarta Servlet is the foundational HTTP request and response specification in Jakarta EE.
  • The Servlet container manages class loading, initialization, request processing, concurrency, and destruction.
  • init() runs once, service() runs per request, and destroy() runs before removal.
  • HttpServlet.service() dispatches requests to methods such as doGet(), doPost(), doPut(), and doDelete().
  • GET should be safe and idempotent, while POST is commonly used for non-idempotent processing or resource creation.
  • HttpServletRequest exposes client request data, while HttpServletResponse configures status, headers, cookies, and body content.
  • Filters are appropriate for cross-cutting web concerns such as authentication, logging, CORS, tracing, and security headers.
  • Listeners observe application, request, session, and attribute lifecycle events.
  • HTTP sessions maintain server-side state across requests but must remain small, secure, and concurrency-aware.
  • Cookies store client-side data and require secure flags and careful content selection.
  • Forwarding reuses the same request on the server, while redirecting creates a new client request.
  • One Servlet instance commonly handles many concurrent requests, so mutable instance fields are dangerous.
  • Servlets should remain stateless and use local variables for request-specific data.
  • Asynchronous Servlet processing can release request threads but introduces additional lifecycle, timeout, and context complexity.
  • Large uploads and downloads should be streamed and protected by size, type, and authorization controls.
  • Important business logic should live in services rather than Servlets, filters, listeners, or JSP pages.
  • Senior developers design Servlets as thin HTTP adapters with explicit security, observability, resource management, and thread-safety guarantees.