Image of forward() vs sendRedirect() vs include()

ADVERTISEMENT

Table of Contents

Introduction

It is a common practice that a controller redirects to another resource after processing a request, the resource could be either a view which displays the result of processing or even another controller which needs to do further processing on the request.

In this tutorial, we explain the different ways of redirecting requests from servlet to another resource. Basically we talk about 3 methods forward(), sendRedirect() and include(). We define them, compare their usage and provide a situation for using each of them.

1. forward()

It is a method exposed by RequestDispatcher interface:

void forward(ServletRequest request, ServletResponse response)
  • Input:
    • request: a ServletRequest object that represents the initial request sent by the client.
    • response: a ServletResponse object that represents the response the servlet returns to the client.
  • Description:
    • This method forwards a request from a servlet to another resource (servlet, JSP file, or HTML file) internally in the same server without the notice of browser, i.e. the client doesn’t know that the request is being handled by other resource.
    • You can forward to other resource as the following:
request.getRequestDispatcher("home.jsp").forward(request, response);
* It is normally used when you define one servlet to do preliminary processing of a request and have another resource generates the response.
* This method should be called before committing the response to the client. If the response has already been committed, this method throws an IllegalStateException. A typical mistake of using this method is to forward to another resource and then generate output afterwards in the current servlet, any output defined after forwarding the request is neglected.
  • Typical usage:
    • Forwarding to home page after login.
  • Request flow:
    • Client sends a HTTP request to some.jsp.
    • Server sends a HTTP response back with content of other.jsp
  • Example:
    • Consider the following code block in LoginProcessor which forwards the request to BaseServlet after validating the credentials of the user. In the following example, we pass some attributes in the request object and we modify the response output after calling forward():
request.setAttribute("username", "Hussein");
request.setAttribute("password", "Terek");
request.getRequestDispatcher("HomeServlet").forward(request, response);
response.getWriter().append("\nHello from Login servlet");
response.getWriter().append("\nBase servlet attribute: " + request.getAttribute("label"));
* In BaseServlet, we generate a response using the passed attributes as the following:
response.getWriter().append("Hello from base servlet, username: " + request.getAttribute("username") + " ,password: " + request.getAttribute("password"));
request.setAttribute("label", "Hello from base");
* After running http://localhost:8085/LoginProcessor, we get the following output:

local host

* Output observations:
    * The output displays the response generated by BaseServlet, however any modification done on the response after the forward() call inside LoginProcessor is neglected.
    * The browser address bar doesn’t change and still shows LoginProcessor even though the generated output is from BaseServlet.
    * Using forward(), a servlet can easily pass attributes to the destination resource using setAttribute().

2. sendRedirect()

It is a method exposed by HttpServletResponse interface:

  • Signature:
public void sendRedirect(java.lang.String location) throws java.io.IOException
  • Input:
    • location: the url of the destination resource.
  • Description:
    • This method redirects the request to completely other resource existing on different server or context.
    • The method is called using the HttpServletResponse as the following:
response.sendRedirect( "home.jsp?name=Hussein Terek" );
* When calling this method, the server sends back a HTTP status code of 302 (temporary redirect) which causes the web browser to issue a brand new HTTP GET request for the content at the redirected location.
* It is normally used when you want to use an external resource ( existing outside server ) to complete processing the request.
* This method should be called before committing the response or otherwise it throws an IllegalStateException.
  • Typical usage:
    • When paying for items in e-commerce website, the customer is always redirected to external merchant site for completing the payment.
  • Request flow:
    • Client sends a HTTP request to some.jsp
    • Server sends a HTTP response back with location: other.jsp in the header.
    • Client sends a HTTP request to other.jsp (this get reflected in the browser address bar)
    • Server sends a HTTP response back with content of other.jsp
  • Example:
    • Again we use the same above example, but now we use sendRedirect() instead of forward() in LoginProcessor:
request.setAttribute("username", "hussein");
request.setAttribute("password", "terek");
response.sendRedirect( "BaseServlet" );
response.getWriter().append("\nHello from Login servlet");
response.getWriter().append("\nBase servlet attribute: " + request.getAttribute("label"));
* We keep BaseServlet as is, then run http://localhost:8085/PassHtmlServlet/LoginProcessor
* Following is how the response looks like in the browser:

local host

* Output observation:
    * The browser address bar gets changed to the redirected resource.
    * Again, only the response generated from the destination resource is displayed in the output.
    * With sendRedirect(), you can’t pass attributes using setAttribute().

3. include()

It is a method exposed by RequestDispatcher interface:

  • Signature:
void include(ServletRequest request,ServletResponse response)
  • Input:
    • request: a ServletRequest object that represents the initial request sent by the client.
    • response: a ServletResponse object that represents the response the servlet returns to the client.
  • Description:
    • This method includes another resource existing under the same server in the response returned from a web component.
    • This method is called using RequestDispatcher as the following:
request.getRequestDispatcher("home.jsp").include(request, response);
  • When calling include(), the control switches to the other component and when the processing of the other component finishes, the control returns back to the initial component starting from the next point of coding after the include call.
  • An included web component has access to the request object and it can write to the response , however it can’t set headers or call any method such as setCookie() that affects the headers of the response.
  • Typical usage:
    • It is often useful to include another web resource such as banner content or copyright information in the response returned from a web component.
  • Request flow:
    • Client sends a HTTP request to some.jsp.
    • Server includes banner.jsp component in the response.
    • Server sends a HTTP response back with content of some.jsp appended with banner.
  • Example:
    • We run exactly the same login/home example, but now we use include() instead of forward():
request.setAttribute("username", "hussein");
request.setAttribute("password", "terek");
request.getRequestDispatcher("BaseServlet").include(request, response);
response.getWriter().append("\nHello from Login servlet");
response.getWriter().append("\nBase servlet attribute: " + request.getAttribute("label"));
  • We keep BaseServlet as is, then run http://localhost:8085/PassHtmlServlet/LoginProcessor
  • Following is how the response looks like in the browser:

local host

  • Output observation:
    • The output displays an appended response from both BaseServlet and LoginProcessor.
    • The address bar of the output keeps pointing to LoginProcessor, even though the response includes a response from another resource.
    • Using include(), you are able to pass attributes between web components using setAttribute().

4. Using redirect() over forward()

In some situations, it’s better to go with sendRedirect() instead of forward() & include().

A typical situation is when you redirect to another resource after processing a post request like form submission. In this case, if you use forward() as a redirection mechanism, you will end up returning a result page with exactly the same address url and any additional attempt to reload the page would cause a double submit problem.

So it’s better that the servlet redirects the response to a new view instead of forwarding it so that the browser loads the result page separately using a totally different address url. This way, when end user refreshes the browser he will be just refreshing the result view.

In general, a forward request should be used if the operation can be safely repeated upon a browser reload of the resulting web page; otherwise, redirect is preferable. Typically, if the operation performs an edit on the data store, then a redirect not a forward is recommended, this is simply to avoid the possibility of inadvertently duplicating an edit to the database.

That’s it.

Summary

In general, a forward request should be used if the operation can be safely repeated upon a browser reload of the resulting web page; otherwise, redirect is preferable. Typically, if the operation performs an edit on the data store, then a redirect not a forward is recommended, this is simply to avoid the possibility of inadvertently duplicating an edit to the database.

Next Steps

If you're interested in learning more about the basics of Java, coding, and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you'll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article. If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.

Final Notes