Request Dispatching: Forward & Include
Request Dispatching: Forward & Include
A single HTTP request rarely belongs to just one servlet. Real web applications split work across multiple components: one servlet validates input and prepares data, a JSP renders the HTML, a header fragment is reused across every page. RequestDispatcher is the mechanism that wires these components together server-side, invisibly to the browser. This lesson covers its two operations — forward and include — and the request-attribute channel that carries data between them.
What Is a RequestDispatcher?
A RequestDispatcher is a server-side delegation object. You obtain one by asking the HttpServletRequest or the ServletContext for a target resource path, then you either forward the entire request to that resource or include its output inside your own response. The browser sees one HTTP response with one status code; it has no idea how many components produced it.
There are two ways to obtain a dispatcher:
/). The request-level variant additionally supports paths relative to the current servlet — rarely needed but good to know.
forward() — Handing Off the Request Completely
forward(request, response) transfers full control of the response to the target resource. After the call returns, the calling servlet must write nothing more to the response. If it does, the container will either throw an IllegalStateException or silently discard the extra output, depending on whether the response was already committed.
The JSP at /WEB-INF/views/product-list.jsp receives the same request and response objects, so it can read the attributes placed there by the servlet:
response.flushBuffer() has been called. Calling forward on a committed response throws IllegalStateException. Prepare all attributes, then forward — and make it the very last statement in your handler.
include() — Composing a Page from Parts
include(request, response) delegates to the target resource temporarily. The target writes its output into the same response buffer, then control returns to the calling servlet, which can continue writing. This is perfect for reusable page fragments — headers, footers, navigation bars — that multiple servlets embed into their own output.
setContentType(), setStatus(), or sendRedirect() made inside an included resource. Only the top-level servlet controls those. Use include purely for body content fragments.
Passing Data: Request Attributes
Request attributes are the standard courier between a servlet and the resource it dispatches to. They live for the duration of a single request and are stored as a key-value map on the HttpServletRequest object.
In a JSP with EL (Expression Language) and JSTL you read attributes without explicit casting:
forward vs include vs sendRedirect — Choosing the Right Tool
- forward: server-side, same request/response. Use when one servlet prepares data and delegates rendering entirely to a JSP. URL in the browser does not change.
- include: server-side, same request/response. Use to embed reusable fragments (header, footer, sidebar) into a page assembled by a controlling servlet.
- sendRedirect: client-side (HTTP 302). Use after POST to prevent form re-submission (Post/Redirect/Get pattern), or to redirect to an external URL. The browser makes a second request, so request attributes are lost.
forward is the handoff between C and V — this is how classic Jakarta EE MVC works before you introduce a framework like Spring MVC.
Practical Pattern: Front Controller with Forwarding
Many applications route all requests through one entry-point servlet, which decides which sub-handler to delegate to. This is the Front Controller pattern — the same concept Spring MVC's DispatcherServlet implements internally.
Summary
RequestDispatcher gives you two server-side delegation tools. Use forward to hand off the complete response to a JSP or another servlet — the servlet prepares data as request attributes, then steps aside. Use include to embed fragment output from another resource into a page you are building. Both operate within the same HTTP request/response cycle, sharing the same attribute map, and both are invisible to the browser. Knowing when to forward, when to include, and when to redirect instead is one of the core routing decisions in any Jakarta EE web application.