Core and Web-based Java

Servlets, Containers, Sessions, JSP and MVC

PGCP-AC

Servlets form the foundation of traditional Java web applications. A servlet container accepts HTTP traffic, maps URLs to components, manages their lifecycle and supplies request, response, session, security and dispatch services. JSP renders server-prepared data, while MVC keeps request decisions, business work and presentation separate. Scope and ownership matter because one servlet instance commonly serves many requests concurrently.

Enterprise web platform and deployment

The platform historically called J2EE and later Java EE is now developed as Jakarta EE. It defines standard contracts for web components, persistence, transactions, dependency injection, validation, messaging and web-service support. A compliant server or a focused servlet container supplies implementations of the contracts it supports. Applications compile against APIs but run against provider implementations chosen by the deployment environment.

A web application is packaged as an expanded directory or WAR archive containing classes, libraries, public resources and deployment metadata. Deployment installs that application into a container, assigns a context path, creates an application class loader and ServletContext, discovers annotations and descriptors, initializes eager components and begins accepting mapped requests. Redeployment or shutdown stops request service and invokes orderly destruction callbacks. Build tools, server administration tools, IDE adapters or automated pipelines may perform deployment, but they all establish the same runtime relationship between application and container.

Servlets improved on classic CGI execution because a container can reuse a managed servlet instance and process requests through threads rather than launching a separate operating-system process for every request. This reduces process-creation overhead and provides standard lifecycle, session, security and dispatch services. The shared process and instance model also creates the servlet concurrency rules discussed below.

1. Container and request flow

A browser sends an HTTP request to a servlet container. The container identifies the application, runs matching filters, selects a servlet and creates request and response objects.

Browser → filters → controller servlet → service/DAO
                                      ↓
                                 model data
                                      ↓
Browser ← HTTP response ← JSP view ← forward

The container manages component construction, mappings, threads, sessions, security constraints, errors, class loading and JSP compilation. The application supplies domain behaviour. Older material uses javax.servlet; newer Jakarta environments use jakarta.servlet. Imports, libraries and container versions must be consistent.

2. Servlet lifecycle

The container normally creates a servlet instance and invokes:

  1. init() once for initialization;
  2. service() for each request;
  3. destroy() once during orderly removal.

HttpServlet.service() dispatches by method to doGet, doPost, doPut, doDelete and related handlers.

@WebServlet("/students")
public class StudentServlet extends HttpServlet {
    private StudentService service;

    @Override public void init() {
        service = createService();
    }

    @Override
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
            throws ServletException, IOException {
        request.setAttribute("students", service.findAll());
        request.getRequestDispatcher(
                "/WEB-INF/views/students.jsp")
               .forward(request, response);
    }
}

destroy can release owned resources, but abrupt process termination cannot guarantee it.

3. Servlet concurrency

One servlet instance can handle requests on several threads. Mutable instance fields are therefore shared:

// Unsafe: all requests can overwrite this
private String currentStudentName;

Keep request data in local variables, request attributes or request-owned objects. Fields may hold immutable or thread-safe services. Never keep a normal JDBC Connection, per-user identity or request-specific value in a servlet field.

Stateless controllers are easiest to reason about. Shared dependencies must have an explicit concurrency contract.

4. URL mapping and paths

Mappings may use annotations or web.xml:

@WebServlet(urlPatterns = "/courses/*")

Annotations such as @WebServlet, @WebFilter and @WebListener declare components in code. The deployment descriptor can declare or override mappings, initialization parameters, welcome files, errors, sessions and security constraints. Annotation scanning and descriptor metadata are processed during deployment; they are not ordinary per-request reflection work.

The context path identifies the application. The servlet path is the matched portion, path info follows a path mapping and the query string follows ?. Build links using the context path so deployment below a non-root path works. Request URLs and server filesystem paths are separate namespaces.

5. HTTP methods

GET retrieves a representation and should be safe. POST commonly submits a command or creates a subordinate resource. PUT replaces or creates at a known identifier and DELETE removes.

Safe means no intended state change. Idempotent means repeating the request has the same intended server-state effect; GET, PUT and DELETE are designed as idempotent, while POST commonly is not.

Method choice influences caching, browser resubmission, links, intermediaries and CSRF defences. Never implement a destructive action as a GET link.

6. Request parameters and headers

Parameters are untrusted client strings:

String rawId = request.getParameter("id");
String[] roles = request.getParameterValues("role");

Parse and validate them, then apply business authorization. Client-side validation improves usability but cannot enforce server rules.

Headers carry protocol metadata:

String type = request.getContentType();
String agent = request.getHeader("User-Agent");

Trust forwarded-address headers only behind controlled proxies that sanitize them.

7. Request attributes

Parameters come from the client and are textual. Attributes are server-side objects:

request.setAttribute("student", student);
Student value = (Student) request.getAttribute("student");

Controllers pass model data to forwarded views through attributes. They survive internal dispatch of the same request but not a redirect, which creates another request.

8. Creating a response

response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(json);

Status, content type, encoding, headers and body must agree. Once the response buffer commits, status and headers cannot be changed reliably. Use either the character writer or binary output stream, not both. sendError enters configured error handling; sendRedirect sends a redirect Location.

9. Forward, include and redirect

A forward executes another server resource with the same request and response. It preserves attributes and normally leaves the browser URL unchanged.

An include inserts another resource's output and returns control to the caller.

A redirect asks the browser for a new request:

response.sendRedirect(
        request.getContextPath() + "/students");

The URL changes, request attributes disappear and another round trip occurs. Avoid writing output before dispatching.

10. Post/Redirect/Get

After successful POST processing, redirect to GET:

POST /students → validate and save → redirect
GET /students/42 → load and render

Refreshing repeats GET instead of resubmitting the form. On validation failure, forward back in the same request so errors and entered values remain available. Cross-request feedback needs deliberate flash storage, commonly a short-lived session attribute removed after display.

11. Cookies

A cookie is small client-side name–value data returned according to domain, path, lifetime and security rules:

Cookie cookie = new Cookie("theme", "dark");
cookie.setHttpOnly(true);
cookie.setSecure(true);
cookie.setPath(request.getContextPath());
response.addCookie(cookie);

HttpOnly prevents ordinary script access and Secure restricts transmission to HTTPS. SameSite policy limits some cross-site sending. Cookies are client-controlled; do not trust roles, prices or authorization claims stored in them.

12. HttpSession

HttpSession holds server-managed cross-request state:

HttpSession session = request.getSession();
session.setAttribute("userId", user.id());

The browser usually holds only a session-identifier cookie. getSession(false) checks without creating a session and invalidate() ends it.

Concurrent requests can access one session, so mutable attributes may race. Keep session state small and do not use it as a permanent database or unlimited cache.

13. Session security

After authentication or privilege elevation, call request.changeSessionId() to reduce session fixation. Use HTTPS, Secure and HttpOnly cookies, timeouts, CSRF protection and authorization for every protected action.

Session IDs are credentials. Do not log or expose them. URL rewriting can carry an ID when cookies are unavailable, but URLs leak into history, logs, referrers and copied links.

14. Scope

ScopeLifetimeShared by
PageOne JSP evaluationCurrent page
RequestOne request and dispatchesCurrent request components
SessionUser sessionRequests in that session
ApplicationApplication lifetimeAll application requests

Choose the narrowest scope. Wider scope increases memory and concurrency risk. Application-scope mutable objects must be thread-safe.

ServletContext represents the application and provides attributes, initialization parameters, resources, logging and dispatch. It must not hold per-user data.

15. Filters

A filter wraps processing:

public void doFilter(ServletRequest request,
                     ServletResponse response,
                     FilterChain chain)
        throws IOException, ServletException {
    long start = System.nanoTime();
    try {
        chain.doFilter(request, response);
    } finally {
        logDuration(System.nanoTime() - start);
    }
}

Filters suit authentication gates, encoding, correlation IDs, security headers and timing. Calling chain.doFilter continues; omitting it ends processing. Filter instances also serve concurrent requests.

16. Listeners

ServletContextListener observes application startup and shutdown, HttpSessionListener observes sessions and ServletRequestListener observes requests. Attribute listeners observe additions, replacements and removals.

Listeners can initialize infrastructure or metrics, but should not conceal core business flow. Release startup-owned resources during orderly shutdown.

17. WAR structure

application.war
├── public resources
└── WEB-INF/
    ├── web.xml
    ├── classes/
    ├── lib/
    └── views/

The browser cannot directly fetch resources under WEB-INF. A controller can forward there, preventing users from bypassing model preparation. Compiled classes belong in WEB-INF/classes and dependency JARs in WEB-INF/lib.

18. JSP translation

A JSP is translated into a servlet and compiled. It therefore has servlet-style initialization, concurrent service and destruction.

JSP syntax includes directives, declarations, scriptlets, expressions, Expression Language and tags. A declaration becomes a servlet member, while a scriptlet places statements in request processing. Prefer EL and JSTL: scriptlets mix Java with markup and declarations may create shared mutable state.

19. Expression Language

EL uses a dollar sign followed by braces, for example the expression for the name property of student. It resolves scoped values, JavaBean properties, maps and supported indexes. Explicit scope objects such as requestScope and sessionScope remove lookup ambiguity.

EL does not automatically make output safe for every HTML, JavaScript, URL or CSS context. Apply context-appropriate encoding.

20. JSTL and implicit objects

JSTL supplies tags for iteration, conditionals, variables, URL construction, encoded output and formatting. A typical c:forEach reads a collection through EL and c:out writes an encoded property. Dependencies and tag URIs must match the chosen Java EE or Jakarta platform.

Implicit objects include request, response, session when enabled, application, out, pageContext, config and page. The exception object exists only on a configured error page.

21. MVC

  • Model: domain data and business state.
  • View: presents prepared data.
  • Controller: reads input, invokes services and selects a response or view.
List<Student> students = studentService.findAll();
request.setAttribute("students", students);
request.getRequestDispatcher(
        "/WEB-INF/views/students.jsp")
       .forward(request, response);

The JSP renders the list. It does not create a DAO, open a database connection or decide a transaction. Services own business rules, while DAOs own persistence.

22. Validation, errors and security

Validate request syntax at the boundary and domain rules in services. Error responses must not reveal stack traces, SQL, paths, session IDs or credentials. Log the internal cause with a correlation ID and return a safe message.

Core protections include output encoding, CSRF defence, per-operation authorization, parameterized SQL, safe upload policies, HTTPS, security headers and allowlisted redirect destinations.

Practical considerations

MistakeCorrect approach
Request data in servlet fieldsUse locals or request attributes
GET for destructive workUse a state-changing method
Expecting attributes after redirectUse deliberate flash state
Creating sessions just to check loginUse getSession(false)
Trusting cookie rolesAuthorize from server identity
Per-user data in application scopeUse a narrower scope
JDBC logic in JSPUse controller, service and DAO
Unencoded dynamic outputEncode for the output context
Exposing stack tracesLog internally and return safe errors

Worked request trace

For successful student creation:

  1. POST passes through encoding and authentication filters.
  2. The controller parses and validates parameters.
  3. The service authorizes and commits the transaction.
  4. The controller stores short-lived feedback and redirects.
  5. The browser issues GET.
  6. The controller loads model data into request attributes.
  7. It forwards to a JSP under WEB-INF.
  8. JSTL and EL render encoded values.

On validation failure, forward to the form with errors and entered values in the same request.

Continue learning

Related notes

Put this topic into timed practice

Open mock tests when you want full-exam pacing, or keep drilling in practice mode.