Solving Servlet Session Management and Filter-Based Problems – Detailed Notes
Course: Advance Java Training
Topic: Solving Servlet Session Management and Filter-Based Problems
Course Link: Advance Java Training at JustAcademy
Demo Link: Register for a Course Demo
Website: JustAcademy Official Website
1. Introduction
Servlet session management and filter-based processing are important concepts in Java web application development. They help developers maintain user information across multiple HTTP requests, control access to protected pages, validate incoming requests, log activity, and apply common processing rules before requests reach servlets or other web resources.
HTTP is a stateless protocol. Each request is generally processed independently, so the server does not automatically remember the user or data from a previous request. Servlet session management provides mechanisms to maintain state between requests, while servlet filters intercept requests and responses to perform reusable processing tasks.
For example, an e-commerce application may use a session to remember a user's shopping cart. An authentication filter can check whether the user is logged in before allowing access to the checkout page. A logging filter can record request details for troubleshooting and monitoring.
Learning Objectives
- Understand HTTP statelessness and the purpose of session management.
- Use the
HttpSession interface to store and retrieve user information.
- Configure session timeout, invalidation, and session tracking.
- Understand cookies, session identifiers, and session lifecycle.
- Create servlet filters using the Jakarta Servlet API.
- Implement authentication checks, logging, request validation, and response headers.
- Configure filter mappings using annotations and
web.xml.
- Identify and solve common session and filter-related problems.
- Apply security and performance best practices to Java web applications.
2. Understanding HTTP Statelessness
HTTP does not inherently maintain conversational state between requests. If a user opens a page, submits a form, and then opens another page, the server needs a mechanism to associate those requests with the same user interaction.
2.1 Example of the Problem
Imagine a user logs in successfully. The login servlet verifies the username and password, then returns a successful response. When the user requests a protected page, the server receives another HTTP request. Without a state-management mechanism, the application cannot automatically know that the user authenticated earlier.
Session management solves this problem by associating requests with a session. The server can store appropriate information in that session and retrieve it during subsequent requests that belong to the same session.
2.2 Common State Management Techniques
| Technique |
Description |
Typical Use |
| Cookies |
Small pieces of data stored by the browser and sent with matching requests. |
Session identifiers and user preferences. |
| HttpSession |
Server-side storage associated with a client session. |
Login state, shopping carts, temporary workflow data. |
| URL Rewriting |
Encodes a session identifier into URLs when required and supported. |
Session tracking when cookies are unavailable. |
| Hidden Form Fields |
Passes values through form submissions. |
Simple multi-step forms, when appropriate. |
| Database Storage |
Stores persistent information outside the HTTP session. |
Orders, customer records, and long-term application data. |
| Tokens |
Uses signed or opaque tokens to represent authentication or other claims. |
APIs and distributed authentication designs. |
These mechanisms serve different purposes. For example, a cookie can carry a session identifier, while the actual session attributes remain stored on the server.
3. What Is HttpSession?
HttpSession is an interface in the Servlet API that allows a web application to maintain user-related state across multiple requests. The servlet container manages the session and associates incoming requests with it through a session-tracking mechanism.
In modern Jakarta EE applications, the interface is available as jakarta.servlet.http.HttpSession. Older Java EE applications may use the legacy javax.servlet.http.HttpSession package. The import must match the servlet API and container version used by the project.
3.1 Important HttpSession Methods
| Method |
Purpose |
request.getSession() |
Returns the current session or creates a new one if necessary. |
request.getSession(false) |
Returns the existing session or null without creating a new session. |
session.setAttribute(name, value) |
Stores an object in the session. |
session.getAttribute(name) |
Retrieves an attribute from the session. |
session.removeAttribute(name) |
Removes a particular session attribute. |
session.invalidate() |
Invalidates the session and removes its session state. |
session.getId() |
Returns the current session identifier. |
session.isNew() |
Indicates whether the session is new from the container's perspective. |
session.getCreationTime() |
Returns the session creation time as a timestamp. |
session.getLastAccessedTime() |
Returns the last time the client sent a request associated with the session. |
session.setMaxInactiveInterval(seconds) |
Sets the maximum inactivity interval in seconds. |
session.getMaxInactiveInterval() |
Returns the configured maximum inactivity interval in seconds. |
4. Creating and Accessing a Session
Use getSession() when the application needs a session and is allowed to create one. Use getSession(false) when checking whether a session already exists, especially in authentication filters, where accidentally creating a new session for every anonymous request is undesirable.
4.1 Creating a Session
import java.io.IOException;
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 jakarta.servlet.http.HttpSession;
@WebServlet("/create-session")
public class CreateSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession();
session.setAttribute("username", "Amit");
session.setAttribute("role", "USER");
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().println("Session created successfully.");
}
}
Explanation:
request.getSession() returns the current session or creates one.
setAttribute() stores values under named attributes.
- Other servlets in the same web application can access these attributes when handling requests associated with that session.
4.2 Reading Session Attributes
@WebServlet("/profile")
public class ProfileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
HttpSession session = request.getSession(false);
response.setContentType("text/plain;charset=UTF-8");
if (session == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().println("Please log in first.");
return;
}
Object username = session.getAttribute("username");
if (username == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().println("Please log in first.");
return;
}
response.getWriter().println("Welcome, " + username);
}
}
This approach avoids creating a new session just to check whether the user is already authenticated. The example demonstrates session lookup only; real authentication must also validate the application's trusted authentication state and enforce appropriate authorization rules.
5. Session Attributes and Data Management
Session attributes are objects stored under string-based names. They can represent a username, shopping cart, temporary form data, or other information that should be available across related requests.
5.1 Storing and Removing Attributes
HttpSession session = request.getSession();
session.setAttribute("username", "Amit");
session.setAttribute("language", "English");
String language = (String) session.getAttribute("language");
session.removeAttribute("language");
5.2 Recommended Session Data
- A minimal authenticated-user reference.
- A shopping cart or checkout workflow state, where appropriate.
- Temporary multi-step form data.
- Non-sensitive user interface preferences.
5.3 Data That Should Not Be Stored Carelessly
- Plain-text passwords.
- Unnecessary personal or confidential information.
- Large uploaded files or large collections that consume excessive memory.
- Non-serializable or container-specific objects when sessions may be replicated or persisted.
- Database connections, open streams, or other short-lived resources.
Session data consumes resources and may need to be replicated in a clustered deployment. Store only what the application needs and remove temporary information when it is no longer required.
6. Session Timeout Management
A session timeout determines how long a session may remain inactive before the container invalidates it. This helps release resources associated with inactive users and reduces the period during which abandoned sessions remain usable.
6.1 Setting Timeout Programmatically
HttpSession session = request.getSession();
session.setMaxInactiveInterval(900);
The value 900 means 900 seconds, or 15 minutes. The interval is based on inactivity, not necessarily the total duration of a user's visit.
6.2 Configuring Timeout in web.xml
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
version="6.0">
<session-config>
<session-timeout>15</session-timeout>
</session-config>
</web-app>
The session-timeout value in web.xml is expressed in minutes. This is a deployment descriptor example for a compatible Jakarta Servlet version; use the descriptor schema and version supported by your application server.
6.3 Common Timeout Problems
| Problem |
Possible Cause |
Solution |
| User is logged out unexpectedly. |
Timeout is shorter than the user's idle period. |
Review inactivity requirements and configure a suitable timeout. |
| Session remains active longer than expected. |
Requests keep refreshing the inactivity timer. |
Check periodic AJAX requests, polling, and background traffic. |
| Session disappears after redeployment. |
Server restart, application redeployment, or session persistence settings. |
Review container behavior and use appropriate persistence if required. |
| Session data is missing on a different server. |
Requests are reaching another instance without shared session state. |
Configure supported session replication or a shared session store. |
7. Invalidating a Session and Implementing Logout
When a user logs out, the application should invalidate the session so that stored session attributes are no longer available. Merely redirecting to a login page does not remove the existing session state.
7.1 Logout Servlet
@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
response.sendRedirect(
request.getContextPath() + "/login.html"
);
}
}
This example uses POST for logout. A production application should also protect state-changing requests against cross-site request forgery (CSRF), according to its authentication architecture.
7.2 Important Logout Considerations
- Invalidate the session on the server.
- Clear authentication-related state maintained by the application.
- Ensure protected endpoints reject requests without valid authentication.
- Use appropriate cookie settings and clear client-side cookies when required.
- Do not treat a redirect alone as proof that logout is complete.
8. Session Tracking and Cookies
Servlet containers commonly use cookies to associate a browser with a session. In a typical configuration, the server sends a session identifier in a cookie such as JSESSIONID. The browser returns that cookie with later matching requests, allowing the container to identify the associated session.
8.1 Example Session Tracking Flow
- The browser sends a request to the web application.
- The application creates a session when needed.
- The container provides a session identifier to the client through the configured tracking mechanism.
- The browser returns the identifier on subsequent matching requests.
- The container associates those requests with the corresponding session, if it is still valid.
8.2 Cookie Security Settings
For applications that use cookie-based sessions, review these cookie attributes:
| Attribute |
Purpose |
Secure |
Restricts cookie transmission to secure HTTPS connections. |
HttpOnly |
Prevents ordinary client-side scripts from reading the cookie. |
SameSite |
Controls when browsers send the cookie in cross-site contexts and can help reduce CSRF risk. |
Path |
Restricts the URL paths for which the cookie is sent. |
Max-Age or Expires |
Controls client-side cookie persistence when configured. |
Cookie settings must reflect the application's deployment and authentication requirements. For example, a cookie used in a cross-site authentication flow may require different SameSite handling from a cookie used only within a same-site application.
9. Session Fixation and Session Security
Session fixation is a security risk in which an attacker attempts to make a victim use a session identifier known to the attacker. If the application authenticates the user without changing or protecting the session identifier, the attacker may be able to misuse that session.
9.1 Recommended Protection
- Use the security features provided by the servlet container or authentication framework.
- Rotate or change the session identifier after successful authentication when supported by the framework and required by the security design.
- Do not accept arbitrary client-provided values as proof of authentication.
- Use HTTPS for authenticated sessions.
- Set appropriate session cookie security attributes.
- Invalidate sessions on logout and authentication revocation.
- Apply CSRF protections to state-changing requests where relevant.
9.2 Changing the Session Identifier
The Servlet API provides a session ID rotation method in supported versions:
HttpSession session = request.getSession();
request.changeSessionId();
Use the appropriate authentication lifecycle hook for your framework. In a Spring Security application, prefer the framework's session-fixation protection rather than implementing a separate, conflicting mechanism.
10. What Is a Servlet Filter?
A servlet filter is a Java component that intercepts requests and responses as they pass through the web container. It can inspect a request, add or modify headers, perform validation, record activity, block access, or allow the request to continue to the next filter or target resource.
Filters are useful because cross-cutting tasks can be implemented once and applied to multiple endpoints instead of duplicating the same logic inside every servlet.
10.1 Common Uses of Filters
- Authentication and access-control checks.
- Request logging and audit records.
- Character encoding configuration.
- Request validation and input normalization.
- Adding security-related response headers.
- Cross-Origin Resource Sharing (CORS) handling when configured appropriately.
- Compression or request/response wrapping.
- Measuring request-processing duration.
10.2 Filter Lifecycle Methods
| Method |
Purpose |
init(FilterConfig config) |
Called by the container when the filter is initialized. |
doFilter(request, response, chain) |
Processes a request and response or passes processing onward. |
destroy() |
Called when the container takes the filter out of service. |
11. Creating a Basic Servlet Filter
In Jakarta Servlet applications, a filter implements jakarta.servlet.Filter. The doFilter() method contains the processing logic. To allow the request to reach the next filter or target resource, call chain.doFilter(request, response).
11.1 Request Logging Filter
import java.io.IOException;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
@WebFilter("/*")
public class RequestLoggingFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) {
// Initialize filter resources if required.
}
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest =
(HttpServletRequest) request;
long start = System.currentTimeMillis();
try {
chain.doFilter(request, response);
} finally {
long duration =
System.currentTimeMillis() - start;
System.out.println(
httpRequest.getMethod() + " "
+ httpRequest.getRequestURI()
+ " completed in " + duration + " ms"
);
}
}
@Override
public void destroy() {
// Release filter resources if required.
}
}
This filter measures how long the downstream processing takes. In a production application, use a logging framework and avoid recording passwords, session identifiers, access tokens, or other sensitive information.
12. Understanding FilterChain
The FilterChain represents the sequence of filters and ultimately the target resource. Calling chain.doFilter() continues processing. If a filter does not call it, the request does not proceed further through that chain.
12.1 Request and Response Flow
Client Request
|
v
Filter A
|
v
Filter B
|
v
Servlet / Resource
|
v
Filter B completes
|
v
Filter A completes
|
v
Client Response
Processing before chain.doFilter() generally occurs on the inbound path. Code after the call generally runs as downstream processing returns, which is useful for measuring duration or inspecting response state.
12.2 Blocking a Request
if (requestIsNotAllowed) {
response.setStatus(
HttpServletResponse.SC_FORBIDDEN
);
response.getWriter().println("Access denied.");
return;
}
chain.doFilter(request, response);
When blocking a request, ensure that the response is appropriate for the application and that the filter does not accidentally continue the chain.
13. Configuring Filters with Annotations
The @WebFilter annotation can register a filter and specify the URL patterns it should process.
import jakarta.servlet.annotation.WebFilter;
@WebFilter("/admin/*")
public class AdminFilter implements Filter {
// Implement init(), doFilter(), and destroy().
}
This mapping applies the filter to matching paths in the web application's URL space. It does not automatically make a request secure; the filter must implement the required checks correctly.
14. Configuring Filters in web.xml
Filters can also be declared in the deployment descriptor. This is useful when the project centralizes web configuration or requires explicit filter mappings.
<filter>
<filter-name>RequestLoggingFilter</filter-name>
<filter-class>com.example.RequestLoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RequestLoggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Place these elements in the appropriate location within the application's web.xml, using a descriptor version compatible with the servlet container.
14.1 Annotation vs. web.xml
| Feature |
Annotation |
web.xml |
| Configuration location |
Near the Java class. |
Central deployment descriptor. |
| Typical use |
Simple, self-contained filter registration. |
Centralized deployment configuration and explicit mapping. |
| Ordering |
Depends on registration and container rules. |
Filter mapping declaration order controls the mapped chain order for matching requests. |
| Maintenance |
Convenient for class-level configuration. |
Useful when deployment configuration is managed separately. |
15. Solving Authentication Problems with a Filter
An authentication filter can check whether a request has an authenticated user session before allowing access to protected resources. The filter should use a reliable authentication state established by the application's login process.
15.1 Example Authentication Filter
import java.io.IOException;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@WebFilter("/protected/*")
public class AuthenticationFilter implements Filter {
@Override
public void doFilter(
jakarta.servlet.ServletRequest request,
jakarta.servlet.ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest =
(HttpServletRequest) request;
HttpServletResponse httpResponse =
(HttpServletResponse) response;
HttpSession session = httpRequest.getSession(false);
boolean authenticated =
session != null
&& Boolean.TRUE.equals(
session.getAttribute("authenticated")
);
if (!authenticated) {
httpResponse.sendRedirect(
httpRequest.getContextPath() + "/login.html"
);
return;
}
chain.doFilter(request, response);
}
}
In this example, the login process must set the authenticated session attribute only after successful authentication. A stronger design stores or retrieves a trusted authenticated principal rather than relying on arbitrary user-controlled input. Use your security framework's authorization facilities for complex applications.
15.2 Important Authentication Filter Rules
- Protect every relevant endpoint, not only pages linked from the user interface.
- Do not create a new session merely to check authentication.
- Keep public endpoints such as login, registration, and selected static resources accessible as intended.
- Distinguish authentication from authorization: being logged in does not automatically grant administrator permissions.
- Return an appropriate response for APIs, often HTTP 401 or 403, rather than always redirecting to an HTML login page.
- Ensure that filter mappings cover the intended URL patterns.
16. Solving Session-Based Login Problems
Session-related login failures often happen because the login servlet does not store authentication state correctly, a protected page checks a different attribute name, or the browser does not return the session cookie.
16.1 Example Login Session Setup
HttpSession session = request.getSession(true);
session.setAttribute("authenticated", Boolean.TRUE);
session.setAttribute("username", verifiedUsername);
Only set these attributes after verifying the submitted credentials against a trusted authentication system. Do not treat a username submitted by the client as proof of identity.
16.2 Diagnosing a Login Loop
- Confirm that the login process succeeds and reaches the expected code path.
- Verify that authentication state is saved in the session after successful verification.
- Check that the filter uses the same attribute name and expected data type.
- Confirm that the login page and login-processing endpoint are not blocked by the authentication filter.
- Check that the browser receives and returns the session cookie.
- Verify cookie path, domain, HTTPS, and SameSite configuration.
- Check whether a reverse proxy or multiple server instances cause session continuity problems.
17. Solving Filter Ordering Problems
When multiple filters apply to the same request, their order can affect application behavior. For example, an encoding filter should normally run before code that reads request parameters. An authentication filter should execute before a protected resource is accessed.
17.1 Example Filter Chain
Character Encoding Filter
|
v
Request Logging Filter
|
v
Authentication Filter
|
v
Authorization / Application Logic
|
v
Servlet or Controller
This is an illustrative order; the actual sequence should reflect the application's requirements. In a web.xml-based configuration, mappings are ordered according to their declaration for matching requests. When using framework-managed filters, follow that framework's registration and ordering rules.
17.2 Common Ordering Errors
| Problem |
Cause |
Solution |
| Request parameters contain incorrect characters. |
Encoding is configured after parameters are read. |
Apply character encoding before parameter access. |
| Login page redirects repeatedly. |
Authentication filter also blocks login resources. |
Exclude intended public paths or configure permitted routes. |
| Logging does not include all requests. |
Mapping excludes some paths or dispatcher types. |
Review URL patterns and dispatcher mappings. |
| Authorization is bypassed on some routes. |
Filter mapping does not cover every protected endpoint. |
Audit URL patterns and test access to all protected routes. |
18. Character Encoding Filter
Character encoding determines how request and response text is interpreted. Incorrect encoding can cause accented characters, symbols, and non-English text to display incorrectly.
18.1 Example Encoding Filter
import java.io.IOException;
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;
@WebFilter("/*")
public class EncodingFilter implements Filter {
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}
}
Configure the filter early enough that request parameters have not already been parsed. Set an appropriate response content type in the servlet or resource, for example text/html;charset=UTF-8 or application/json;charset=UTF-8, as appropriate.
19. Adding Security Headers with a Filter
Response headers can communicate security policies to browsers. A filter can add appropriate headers to responses across a set of endpoints. The policy must be designed for the application's functionality and deployment.
19.1 Example Security Header Filter
import java.io.IOException;
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.HttpServletResponse;
@WebFilter("/*")
public class SecurityHeadersFilter implements Filter {
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletResponse httpResponse =
(HttpServletResponse) response;
httpResponse.setHeader(
"X-Content-Type-Options", "nosniff"
);
httpResponse.setHeader(
"Referrer-Policy", "strict-origin-when-cross-origin"
);
httpResponse.setHeader(
"X-Frame-Options", "SAMEORIGIN"
);
chain.doFilter(request, response);
}
}
These headers are examples, not a complete security configuration. Consider Content Security Policy, HTTPS configuration, and other controls appropriate to the application. Avoid conflicting with headers already managed by a reverse proxy or security framework.
20. Request Validation and Input Handling
Filters can perform broad checks that apply across multiple endpoints, such as validating a request's general structure or rejecting requests that violate an application-wide rule. Detailed business validation should normally remain in the appropriate application layer.
20.1 Example: Rejecting an Unsupported HTTP Method
String method = request.getMethod();
if (!"GET".equals(method) && !"POST".equals(method)) {
response.setStatus(
HttpServletResponse.SC_METHOD_NOT_ALLOWED
);
return;
}
chain.doFilter(request, response);
Use method restrictions only where they match the endpoint's requirements. HTTP methods such as PUT, PATCH, DELETE, OPTIONS, and HEAD may be valid and necessary. For REST APIs, configure allowed methods at the correct resource or security layer.
20.2 Validation Best Practices
- Validate request data on the server even when client-side validation exists.
- Use parameterized database operations to prevent SQL injection.
- Apply output encoding to reduce cross-site scripting risks.
- Limit request size and upload size according to business needs.
- Return useful but non-sensitive error messages.
- Avoid logging full request bodies when they may contain secrets or personal information.
21. Filter Dispatcher Types
Filters can be mapped to different dispatcher types, which determine how the filter applies when a resource is accessed through different request-processing paths.
| Dispatcher Type |
Meaning |
REQUEST |
A normal client request. |
FORWARD |
A request forwarded to another resource by the server. |
INCLUDE |
A resource included during another resource's processing. |
ERROR |
Processing associated with an error dispatch. |
ASYNC |
Processing associated with asynchronous request dispatch. |
Review dispatcher types when a filter appears to run more than once or fails to run during a forward or error dispatch. The exact behavior depends on the filter mapping and container configuration.
22. Handling Session Expiration in Filters
When a session expires, a protected request may arrive without a valid session or authentication state. The application should respond predictably instead of throwing a null pointer exception or allowing access.
22.1 Safe Session Check
HttpSession session = request.getSession(false);
if (session == null
|| session.getAttribute("authenticated") == null) {
response.setStatus(
HttpServletResponse.SC_UNAUTHORIZED
);
return;
}
chain.doFilter(request, response);
For browser-based applications, a redirect to the login page may be more appropriate. For REST APIs, an HTTP 401 response with a suitable response body is often preferable. Choose behavior based on the client type and authentication design.
23. Concurrent Requests and Session Data
A single user may make multiple requests at the same time through browser tabs, asynchronous requests, or background polling. These requests can access the same session concurrently. Developers should not assume that multiple session attribute updates occur in a predictable order.
23.1 Common Concurrency Problems
- Two requests update the same shopping cart simultaneously.
- One request invalidates a session while another request is using it.
- A shared mutable object stored as a session attribute is changed by multiple threads.
- Multiple application instances process requests for the same user.
23.2 Recommended Practices
- Keep session attributes simple and minimize mutable shared state.
- Use suitable concurrency controls for shared mutable objects.
- Use database transactions for persistent business operations.
- Do not assume that marking a session attribute update as synchronized makes every related operation automatically thread-safe.
- Test simultaneous requests for important workflows such as checkout and account updates.
24. Session Management in Clustered Applications
In a multi-instance deployment, requests from one user may be routed to different application servers. If each server keeps independent session data, the user may appear logged out or lose session attributes when the next request reaches another instance.
24.1 Common Approaches
| Approach |
Description |
Considerations |
| Session Affinity |
Attempts to route a user's requests to the same application instance. |
May reduce flexibility during failures or scaling. |
| Session Replication |
Replicates session state across supported server instances. |
Requires compatible infrastructure and careful handling of session attributes. |
| Shared Session Store |
Stores session data in a shared system such as a supported database or Redis-backed session store. |
Requires operational management, security, and performance planning. |
| Stateless Authentication |
Uses an authentication design that does not depend on server-side HTTP session state for each request. |
Requires careful token validation, expiry, revocation, and authorization design. |
Do not assume that session affinity alone provides high availability or data replication. Choose a strategy based on the application's scaling, availability, and security requirements.
25. Common Session and Filter Problems
| Problem |
Likely Cause |
Solution |
| Session attribute returns null. |
Attribute was never set, was removed, or belongs to another session. |
Check attribute names, login logic, session continuity, and timeout. |
| New session appears on every request. |
Session cookie is not returned or tracking configuration is incorrect. |
Inspect browser cookies, cookie path, domain, HTTPS, and SameSite settings. |
| Logout does not work. |
Session is not invalidated or authentication is maintained elsewhere. |
Invalidate the session and clear the appropriate authentication state. |
| Filter is not executed. |
Incorrect URL mapping, registration, or dispatcher type. |
Review annotations, deployment descriptor, and application startup logs. |
| Filter executes twice. |
Multiple registrations or mappings, or additional dispatcher types. |
Check annotation and descriptor configuration and review dispatch behavior. |
| Application redirects repeatedly. |
Login endpoint is protected or authentication state is not preserved. |
Review public routes, session attributes, and cookie transmission. |
| Character encoding is incorrect. |
Encoding is configured after request parameters are read. |
Apply the encoding filter early and set the correct response content type. |
| Session is lost between instances. |
Session state is not shared or replicated. |
Configure session affinity, replication, or an appropriate shared session store. |
| Concurrent updates overwrite each other. |
Multiple requests modify the same mutable session data. |
Review synchronization, data structures, and transaction boundaries. |
| Filter exposes sensitive information in logs. |
Logging includes cookies, tokens, passwords, or request bodies. |
Redact sensitive values and follow a secure logging policy. |
26. Practical Project: Login and Protected Dashboard
Build a small Java web application that demonstrates login state, protected resources, logout, and filter-based access control. The example focuses on the session and filter flow; it is not a complete production authentication system.
Step 1: Create a Login Servlet
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
// Demonstration only.
// Replace with secure authentication against a trusted system.
boolean valid =
"student".equals(username)
&& "demo-password".equals(password);
if (!valid) {
response.sendError(
HttpServletResponse.SC_UNAUTHORIZED,
"Invalid credentials"
);
return;
}
HttpSession session = request.getSession(true);
request.changeSessionId();
session.setAttribute("authenticated", Boolean.TRUE);
session.setAttribute("username", username);
response.sendRedirect(
request.getContextPath() + "/protected/dashboard"
);
}
}
Important: Hardcoded credentials are included only to demonstrate the flow and must never be used in a real application. Store passwords securely using a recognized password-hashing approach and authenticate through an appropriate service. In production, use the security framework's session-fixation protection and avoid conflicting session-ID rotation logic.
Step 2: Protect the Dashboard
Register an authentication filter for the /protected/* URL pattern. The filter checks for the authentication state stored after successful login and blocks requests that do not have it.
@WebFilter("/protected/*")
public class DashboardAuthenticationFilter implements Filter {
@Override
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req =
(HttpServletRequest) request;
HttpServletResponse res =
(HttpServletResponse) response;
HttpSession session = req.getSession(false);
if (session == null
|| !Boolean.TRUE.equals(
session.getAttribute("authenticated"))) {
res.sendRedirect(
req.getContextPath() + "/login.html"
);
return;
}
chain.doFilter(request, response);
}
}
Step 3: Create a Dashboard Servlet
@WebServlet("/protected/dashboard")
public class DashboardServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws IOException {
HttpSession session = request.getSession(false);
response.setContentType("text/html;charset=UTF-8");
String username =
(String) session.getAttribute("username");
response.getWriter().println(
"<h1>Welcome, "
+ escapeHtml(username)
+ "</h1>"
);
}
private String escapeHtml(String value) {
if (value == null) return "";
return value.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace("\"", """)
.replace("'", "'");
}
}
For this demonstration, the dashboard assumes the filter has validated the session. In a larger application, keep authorization rules centralized and ensure that every protected resource is covered.
Step 4: Add Logout
Implement a POST logout endpoint that invalidates the session and redirects the user to the login page. Add CSRF protection and a proper logout form or mechanism for the application.
Step 5: Test the Application
- Open the login page.
- Submit invalid credentials and confirm that access is denied.
- Submit valid demonstration credentials and confirm that a session is created.
- Open the protected dashboard and verify that the username is displayed safely.
- Open the dashboard in a separate unauthenticated browser session and confirm that access is denied.
- Log out and verify that the previous session no longer grants access.
- Wait for the configured timeout and confirm that expired sessions are handled correctly.
- Inspect filter logs without exposing session identifiers or credentials.
27. Testing Session and Filter Behavior
Testing should verify both expected behavior and failure scenarios. Session and filter bugs can otherwise remain hidden until users encounter timeouts, multiple browser tabs, or invalid requests.
27.1 Test Cases
| Test Case |
Expected Result |
| Access protected route without a session. |
Request is denied or redirected to login. |
| Access protected route with valid authentication state. |
Request proceeds to the protected resource. |
| Access route after logout. |
Previous session no longer authorizes the request. |
| Use a session after its inactivity timeout. |
Application handles the missing or expired session safely. |
| Request an unmapped public resource. |
Resource remains accessible as intended. |
| Submit non-ASCII text. |
Text is decoded and displayed using the intended encoding. |
| Send an unsupported HTTP method. |
Application returns an appropriate response, if the endpoint restricts that method. |
| Send multiple simultaneous requests. |
Shared state remains consistent according to application rules. |
27.2 Unit and Integration Testing
- Unit-test helper classes and authentication decision logic.
- Use mock requests and responses when testing isolated filter behavior.
- Run integration tests in a servlet container or a compatible test environment.
- Verify actual cookie behavior with browser-based or HTTP-client tests.
- Test timeout and logout behavior against the selected container and configuration.
28. Best Practices
- Use
getSession(false) when checking for an existing session.
- Store only the session information needed by the application.
- Set a suitable inactivity timeout.
- Invalidate sessions when users log out.
- Use secure cookie settings and HTTPS.
- Apply session-fixation protection after authentication.
- Do not treat a session attribute alone as a complete authorization policy.
- Use filters for cross-cutting request and response processing.
- Call
chain.doFilter() only when the request should continue.
- Configure filter mappings carefully and test the execution order.
- Avoid duplicate filter registrations.
- Do not log passwords, session IDs, access tokens, or other sensitive values.
- Use a supported authentication framework for complex access-control requirements.
- Test timeout, logout, concurrent requests, and clustered deployment behavior.
29. Interview Questions and Answers
Q1. What is session management in Servlets?
Answer: Session management associates multiple requests with a user interaction and allows the application to preserve relevant state across requests.
Q2. Why is HTTP called stateless?
Answer: HTTP requests are generally independent. The protocol does not automatically preserve application-specific user state from one request to the next.
Q3. What is HttpSession?
Answer: HttpSession is a Servlet API interface used to store and retrieve server-side session attributes associated with a client session.
Q4. What is the difference between getSession() and getSession(false)?
Answer: getSession() returns the current session or creates one. getSession(false) returns the existing session or null without creating a new session.
Q5. How do you store data in a session?
Answer: Use session.setAttribute("key", value) and retrieve it using session.getAttribute("key").
Q6. How do you end a session?
Answer: Call session.invalidate() to invalidate the session and remove its associated session state.
Q7. What is a session timeout?
Answer: It is the maximum permitted inactivity interval before the container invalidates the session.
Q8. What is a servlet filter?
Answer: A filter is a component that intercepts requests and responses to perform reusable processing before or after a target resource executes.
Q9. What is the purpose of FilterChain?
Answer: It allows a filter to pass a request and response to the next filter or target resource by calling chain.doFilter().
Q10. What happens if a filter does not call chain.doFilter()?
Answer: The request does not continue through that chain. The filter can intentionally block the request, but it must provide an appropriate response when necessary.
Q11. How can a filter protect a page?
Answer: It can verify the authenticated state and authorization requirements before allowing the request to reach the protected resource.
Q12. What is session fixation?
Answer: Session fixation is a security risk in which an attacker attempts to make a victim use a session identifier known to the attacker.
Q13. Why is filter order important?
Answer: Filters may depend on earlier processing. For example, character encoding should be applied before request parameters are parsed, and authentication checks should run before protected resources are accessed.
Q14. Why might a filter execute twice?
Answer: It may be registered more than once, mapped through multiple mechanisms, or invoked for additional dispatcher types such as forwards or error dispatches.
Q15. How can session loss occur in a clustered environment?
Answer: Requests may reach different server instances that do not share session state. Session affinity, supported replication, or a shared session store may be needed.
30. Practice Exercises
- Create a servlet that stores a username in an HTTP session.
- Write another servlet that retrieves and displays the stored username.
- Implement a logout servlet that invalidates the session.
- Configure a 15-minute session inactivity timeout.
- Create a logging filter that records request method, URI, and duration.
- Create an authentication filter for a protected URL pattern.
- Configure a character encoding filter and test non-English input.
- Add selected security headers to responses.
- Investigate why a session attribute becomes null after redeployment.
- Test filter order and diagnose duplicate filter execution.
- Test what happens when the browser does not send the session cookie.
- Document how session state should be handled if the application runs on multiple instances.
31. Quick Revision Checklist
- ☑ Understand HTTP statelessness.
- ☑ Know how
HttpSession stores and retrieves attributes.
- ☑ Distinguish
getSession() from getSession(false).
- ☑ Configure session timeout and implement logout correctly.
- ☑ Understand session cookies and session identifiers.
- ☑ Apply session-fixation and cookie security protections.
- ☑ Understand filter lifecycle methods.
- ☑ Use
FilterChain correctly.
- ☑ Configure filters using annotations or
web.xml.
- ☑ Troubleshoot authentication, filter ordering, and session expiration.
- ☑ Test concurrent requests and clustered session behavior.
- ☑ Avoid logging sensitive information.
32. Additional Learning Resources
33. Conclusion
Servlet session management and filter-based processing are foundational techniques for developing secure and maintainable Java web applications. Sessions help preserve relevant state across HTTP requests, while filters provide reusable request and response processing for authentication checks, logging, encoding, validation, and security headers.
To solve session and filter problems effectively, understand the session lifecycle, inspect cookie and timeout configuration, verify filter mappings and ordering, and test both authenticated and unauthenticated requests. For production systems, use a trusted authentication framework, secure session cookies, minimize stored session data, and plan for concurrency and multi-instance deployments.