Forward versus redirect

A Controller (in this context, an implementation of HttpServlet) may perform either a forward or a redirect operation at the end of processing a request. It's important to understand the difference between these two cases, in particular with respect to browser reloads of web pages.

Forward

Redirect In general, a forward should be used if the operation can be safely repeated upon a browser reload of the resulting web page; otherwise, redirect must be used. Typically, if the operation performs an edit on the datastore, then a redirect, not a forward, is required. This is simply to avoid the possibility of inadvertently duplicating an edit to the database.

More explicitly (in terms of common SQL operations) :

In HTML, a <FORM> tag can either GET or POST its data. In this context, a GET corresponds to a SELECT-then-forward, and a POST corresponds to an edit-then-redirect.

It's strongly recommended that forms for the input of search criteria should use GET, while forms for editing database records should use POST.

The most common symptom of not using forward/redirect properly is a warning message in a browser, asking the user if they really wish to POST their form data a second time.

Example

This example is after the style of the WEB4J Controller class. The important methods of the Servlet API are:


import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
import hirondelle.web4j.action.Action;
import hirondelle.web4j.action.ResponsePage;
import hirondelle.web4j.request.RequestParser;
import hirondelle.web4j.model.BadRequestException;

public class RedirectForward extends HttpServlet {
  
  //..many items elided

  @Override public final void doGet(
      HttpServletRequest aRequest, HttpServletResponse aResponse
   ) throws ServletException, IOException {
    processRequest(aRequest, aResponse);
  }

  @Override public final void doPost(
      HttpServletRequest aRequest, HttpServletResponse aResponse
   ) throws ServletException, IOException {
    processRequest(aRequest, aResponse);
  }

  /**
  * Handle all HTTP <tt>GET</tt> and <tt>POST</tt> requests.
  */
  protected void processRequest(
    HttpServletRequest aRequest, HttpServletResponse aResponse
  ) throws ServletException, IOException {
    RequestParser requestParser = RequestParser.getInstance(aRequest, aResponse);
    try {
      Action action = requestParser.getWebAction();
      ResponsePage responsePage = action.execute();
      if ( responsePage.getIsRedirect() ) {
        redirect(responsePage, aResponse);
      }
      else {
        forward(responsePage, aRequest, aResponse);
      }
    }
    catch (BadRequestException ex){
      //..elided
      //use Response.sendError()
    }
    catch (Throwable ex) {
      //..elided
      //use Response.sendError()
    }
  }
  
  // PRIVATE //
  
  private void redirect(
    ResponsePage aDestinationPage, HttpServletResponse aResponse
  ) throws IOException {
    String urlWithSessionID = aResponse.encodeRedirectURL(aDestinationPage.toString());
    aResponse.sendRedirect( urlWithSessionID );
  }

  private void forward(
    ResponsePage aResponsePage, HttpServletRequest aRequest, HttpServletResponse aResponse
  ) throws ServletException, IOException {
    RequestDispatcher dispatcher = aRequest.getRequestDispatcher(aResponsePage.toString());
    dispatcher.forward(aRequest, aResponse);
  }
} 

See Also :
Command objects
A Web App Framework WEB4J
Consider Controllers for redirects
Apply correct redirect code