SPRING CONCEPTS

Server-side forward

Spring Concepts / Server-side forward

A forward delegates to another server resource inside the same request.

Understand the idea

The Servlet prepares data as request attributes, selects a JSP through RequestDispatcher, and forwards the request and response to it. The JSP reads those attributes and produces the HTML response.

A concrete example

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

In the application

TodoServlet forwards for list/form rendering and validation failures.

Do not commit the response body before forwarding. Forward is different from a redirect that asks the browser for a new request.

1. Prepare the data in the Servlet

These statements belong inside the Servlet request handler. The existing store loads the tasks; setAttribute() then places that Java list on the current request under the name todos.

Servlet request handler excerpt
List<Todo> tasks = store.list();
request.setAttribute("todos", tasks);

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

setAttribute() makes the data available to the view. It does not render a JSP or send the list to the browser by itself.

2. Understand each part

ExpressionWhat it does
tasksThe Java List<Todo> containing the data.
"todos"The attribute name the JSP will use to find that list.
request.setAttribute("todos", tasks)Stores the list on this request.
getRequestDispatcher("/WEB-INF/views/list.jsp")Obtains a dispatcher for the JSP resource. The initial slash means the web application root.
forward(request, response)Hands the current request and response to that resource so it can generate the response.

3. Read the data in the JSP

Save the view at src/main/webapp/WEB-INF/views/list.jsp. This excerpt uses the JSTL dependencies already included in the supplied project.

list.jsp — JSP, EL and JSTL
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<ul>
  <c:forEach items="${requestScope.todos}" var="todo">
    <li><c:out value="${todo.title}" /></li>
  </c:forEach>
</ul>

${requestScope.todos} reads the request attribute explicitly. ${todos} also works here when no closer scope shadows the name. The loop visits each Todo; ${todo.title} reads its getTitle() property, and c:out escapes the title for safe HTML text output.

4. Follow the complete flow

If the list contains tasks titled Learn Java and Learn JSP, the page displays the following bullet list.

Request and rendering flow
Browser requests /todo-servlet-jsp/todos
  -> Servlet loads tasks
  -> setAttribute("todos", tasks)
  -> forward to /WEB-INF/views/list.jsp
  -> JSP reads the list and renders HTML
  -> Browser displays that HTML

The browser URL remains /todo-servlet-jsp/todos. The JSP runs on the server; the browser receives its generated HTML, not JSP source. Files inside WEB-INF cannot be opened directly by a browser URL.

5. Expected browser output

The same request carries the attributes into the JSP. A redirect starts another browser request, so these request attributes do not automatically travel with it.

Rendered list (two example tasks)
• Learn Java
• Learn JSP

6. Common mistakes to check

The names must match: setAttribute("todos", tasks) pairs with ${requestScope.todos}, not ${requestScope.tasks}. The Java variable name tasks does not become the attribute name automatically.

If the list is null or empty, c:forEach has no items to display. First check the attribute name and the data returned by store.list().

Prepare the data before forwarding. Keep data loading in the Servlet or its service layer and presentation in the JSP. Do not send or flush response content before calling forward().

Practice: change the attribute name to taskList in both the Servlet and the JSP, rebuild the WAR, redeploy it, and confirm that the tasks still appear.

Related concepts

Read the official documentation ↗
Java 21 · Spring Boot 4.1.1 · Edupoly