JSP, JSTL & the View Layer

JSP Implicit Objects

18 min Lesson 3 of 13

JSP Implicit Objects

Every JSP page is compiled by the container into a servlet. Inside that generated servlet, the container pre-declares nine well-known variables before your scriptlet code ever runs. These are the implicit objects — they are already in scope, fully initialised, and require no import or instantiation. You use them the same way you would use any local variable. This lesson focuses on the five that you will touch in virtually every web application: request, response, session, application, and out.

Why implicit objects exist: The Servlet API exposes these objects as method parameters (doGet(HttpServletRequest, HttpServletResponse)) or via getServletContext(). The JSP compiler simply pulls them out and binds them to short, predictable names so view code remains concise. In MVC practice, controllers do the heavy lifting and pass results to JSPs — but understanding the underlying objects is still essential for debugging, security, and the occasional unavoidable view-level access.

1. request — HttpServletRequest

The request object is an instance of jakarta.servlet.http.HttpServletRequest. It encapsulates everything the browser sent to the server for this HTTP cycle: headers, parameters, cookies, the request URI, the authenticated principal, and any attributes set by upstream servlets or filters.

Common read operations inside a JSP (or EL expression evaluated against it):

<%-- Get a query-string or form parameter --%> <% String keyword = request.getParameter("q"); %> <%-- Get a named attribute forwarded from a servlet --%> <% List<Product> products = (List<Product>) request.getAttribute("products"); %> <%-- Inspect the HTTP method and URI --%> <% String method = request.getMethod(); // "GET" or "POST" String uri = request.getRequestURI(); %> <%-- Read a request header --%> <% String accept = request.getHeader("Accept-Language"); %>
Always validate and sanitise getParameter() output. User-supplied strings must never be written directly into HTML — that is a cross-site scripting (XSS) vector. Use JSTL's <c:out> or Expression Language escaping, which you will learn in the next lessons.

2. response — HttpServletResponse

The response object is an instance of jakarta.servlet.http.HttpServletResponse. It represents the outgoing HTTP response that the container will send to the browser. In pure MVC designs you rarely manipulate it directly inside a JSP, but it is essential for redirects, cookie manipulation, and setting custom headers.

<%-- Redirect the browser to another URL (commits the response immediately) --%> <% response.sendRedirect(request.getContextPath() + "/login"); %> <%-- Add a cookie to the response --%> <% Cookie pref = new Cookie("theme", "dark"); pref.setMaxAge(60 * 60 * 24 * 30); // 30 days pref.setHttpOnly(true); pref.setSecure(true); // HTTPS only response.addCookie(pref); %> <%-- Set a custom response header --%> <% response.setHeader("X-Frame-Options", "DENY"); %>
Call sendRedirect() before any output is written. Once the container begins streaming HTML bytes the response headers are already committed; attempting a redirect after that throws an IllegalStateException. Redirects belong in servlets or filters, not in JSP output logic — keep this in mind when structuring MVC.

3. session — HttpSession

The session object is an instance of jakarta.servlet.http.HttpSession. HTTP is stateless; the session object is the container's answer to that limitation. The container ties a session to a client using a cookie (JSESSIONID by default) and keeps a server-side map of attributes that persist across multiple requests from the same browser.

<%-- Store a logged-in user in the session after authentication --%> <% session.setAttribute("currentUser", authenticatedUser); %> <%-- Read it back on any subsequent JSP --%> <% User user = (User) session.getAttribute("currentUser"); if (user == null) { response.sendRedirect(request.getContextPath() + "/login"); return; // stop rendering this page } %> <%-- Invalidate the session on logout (removes all attributes, forces new session id) --%> <% session.invalidate(); %> <%-- Check how long this session has been idle (in seconds) --%> <% int idle = (int)((System.currentTimeMillis() - session.getLastAccessedTime()) / 1000); %>
Never store large object graphs in the session. Session data lives in server memory (or a session store). Stuffing entire entity lists into the session wastes memory and complicates clustering. Store only small identifiers — user ID, role, locale — and re-query the database for everything else per request.

4. application — ServletContext

The application object is an instance of jakarta.servlet.ServletContext. It represents the entire web application, not a single request or session. There is exactly one ServletContext per deployed application, shared by every thread and every user. It is used for application-wide configuration, shared caches, and inter-servlet communication.

<%-- Read an <context-param> from web.xml --%> <% String environment = application.getInitParameter("app.environment"); %> <%-- Store and retrieve an application-wide value (e.g. a hit counter) --%> <% synchronized (application) { Integer hits = (Integer) application.getAttribute("hitCount"); if (hits == null) hits = 0; application.setAttribute("hitCount", ++hits); } %> <%-- Get the real path to a resource on the file system --%> <% String configPath = application.getRealPath("/WEB-INF/config.properties"); %> <%-- Log a message through the container logger --%> <% application.log("Application started at: " + new java.util.Date()); %>
Scope ladder — request < session < application. Attributes live in the narrowest scope that satisfies the need. Request attributes vanish at response end. Session attributes vanish when the session expires or is invalidated. Application attributes live for the lifetime of the deployed WAR. Over-scoping (putting request data into application scope) causes bugs that are extremely hard to reproduce under concurrency.

5. out — JspWriter

The out object is an instance of jakarta.servlet.jsp.JspWriter, a buffered character writer that feeds directly into the HTTP response body. Every time the container encounters literal HTML in your JSP page it writes it through out automatically. You use out explicitly in scriptlets when you need to write computed text.

<%-- Explicit use of out (identical to <%= expr %>) --%> <% String greeting = "Hello, " + user.getFirstName() + "!"; out.println("<p class='greeting'>" + greeting + "</p>"); %> <%-- Flush the buffer manually (rarely needed; prefer default auto-flush) --%> <% out.flush(); %> <%-- Check how much buffer space remains --%> <% int remaining = out.getRemaining(); %>
Prefer <%= expr %> or EL ${expr} over explicit out.print(). Both resolve to the same underlying write, but the expression syntax is far easier to read, less error-prone, and integrates naturally with EL's automatic null-handling and HTML-escaping (when used via JSTL). Reserve raw out calls for the rare case where you need to write conditional markup inside complex Java logic — and question whether that logic belongs in the view at all.

The Other Four Implicit Objects

For completeness, the full set of nine implicit objects also includes:

  • pageContextjakarta.servlet.jsp.PageContext: a unified API to access all scopes and forward/include; used heavily inside custom tag implementations.
  • page — the generated servlet instance itself (this); almost never used directly.
  • configjakarta.servlet.ServletConfig: init parameters configured for the JSP servlet itself.
  • exception — available only in error pages (JSPs with isErrorPage="true"); holds the thrown Throwable.

Accessing Implicit Objects via Expression Language

When you use EL (${...}) rather than scriptlets, the same underlying objects are accessible through named EL implicit objects. request attributes are read via ${requestScope.productList}, session attributes via ${sessionScope.currentUser}, and application attributes via ${applicationScope.hitCount}. Parameters are read via ${param.q}. EL is covered in depth in Lesson 4, but recognising the connection to the servlet implicit objects early prevents confusion.

Summary

The five core implicit objects wrap the Servlet API objects your code already knows. request carries inbound data; response controls the outbound stream; session persists state across requests; application holds app-wide shared data; and out writes to the response body. All nine are pre-instantiated by the container — you never construct them yourself. In the next lesson you will see how Expression Language lets you read from all four scopes without writing a single line of Java.