Discussions

Web tier: servlets, JSP, Web frameworks: Diff btw response.sendRedirect, jsp:forward and RequestDispatch

  1. What is the difference between the following:

    1) response.sendRedirect()
    2) jsp:forward
    3) RequestDispatcher .forward
    4) RequestDispatcher .include

    Any examples to illustrate the differences and how each of them is applied?
  2. Includes: RequestDispatcher.include() and <jsp:include> both include content. The included page is inserted into the current page or output stream at the indicated point. These operations can be used to assemble content into a single logical page:

    <jsp:include page="header.html" />
    [Main page conten here.]
    <jsp:include page="footer.html" />

    The header and footer can therefore be common to many different pages.

    Forward and Redirects: The forward and redirect operations both replace content. The current page or output stream is terminated, and is replaced with the output of the specified page.

    Forwards: Both <jsp:forward> and RequestDispatcher.forward() are what I refer to as "server-side" redirects. The redirect operation is performed in the server side, and the browser is unaware of the change. If page1.jsp forwards to page2.jsp, the browser's address bar will still show page1.jsp

    Redirects: The response.sendRedirect() is what I call a "client-side" redirect. The redirect operation is passed to the browser, which is aware of the change. If page1.jsp redirects to page2.jsp, the browser's address bar be updated to show page2.jsp.

    Forwards vs. Redirects: You choose between forwards and redirects depending on how you want the browser to be affected. Forward operations are faster, because all the processing happens server-side. Redirect operations update the browser history, however, which is often desirable.

    If you forward between page1 and page2, if the user's clicks the "refresh" or "reload" button, both page1 and page2 are executed a second time. On the other hand, if you use a client-side redirect, the browser's address information is updated. If the user clicks refresh, only page2 are re-executed.

    I use redirects to separate update components from display components. Suppose you have a ProcessPaymentServlet and a ShowConfirmation.jsp that informs the use that their payment has been processed. If you used a forward operation between them, if the user refreshed the page, both the servlet and the JSP would be re-executed, for a second payment.

    On the other hand, if you used a client-side redirect, only the ShowConfirmation.jsp will be refreshed (which is probably what you want).

    Forward operations are useful when you don't want the browser's address bar to be updated. Error pages are a good situation for using forward operations. Front Controllers in web frameworks that intercept all requests also use forward operations.
  3. Hi Paul,

    Thanks for the detailed explanation, really appreciate it :)

    I have some questions on certain parts of your reply:

    > Includes: RequestDispatcher.include() and <jsp:include> both include content. The included page is inserted into the current page or output stream at the indicated point. These operations can be used to assemble content into a single logical page:
    >
    > <jsp:include page="header.html" />
    > [Main page conten here.]
    > <jsp:include page="footer.html" />
    >
    > The header and footer can therefore be common to many different pages.


    Is <jsp:include> the same as <%@ include file="jspfile" %>?

    If not, what is the difference between them, and any examples to illustrate their usage?

     
    > Forward and Redirects: The forward and redirect operations both replace content. The current page or output stream is terminated, and is replaced with the output of the specified page.
    >
    > Forwards: Both <jsp:forward> and RequestDispatcher.forward() are what I refer to as "server-side" redirects. The redirect operation is performed in the server side, and the browser is unaware of the change. If page1.jsp forwards to page2.jsp, the browser's address bar will still show page1.jsp
    >
    > Redirects: The response.sendRedirect() is what I call a "client-side" redirect. The redirect operation is passed to the browser, which is aware of the change. If page1.jsp redirects to page2.jsp, the browser's address bar be updated to show page2.jsp.
    >
    > Forwards vs. Redirects: You choose between forwards and redirects depending on how you want the browser to be affected. Forward operations are faster, because all the processing happens server-side. Redirect operations update the browser history, however, which is often desirable.
    >
    > If you forward between page1 and page2, if the user's clicks the "refresh" or "reload" button, both page1 and page2 are executed a second time. On the other hand, if you use a client-side redirect, the browser's address information is updated. If the user clicks refresh, only page2 are re-executed.
    >
    > I use redirects to separate update components from display components. Suppose you have a ProcessPaymentServlet and a ShowConfirmation.jsp that informs the use that their payment has been processed. If you used a forward operation between them, if the user refreshed the page, both the servlet and the JSP would be re-executed, for a second payment.


    Does this mean that in the servlet code, you will have something like this:

    public class ProcessPaymentServlet extends HttpServlet {
       ...
      public void doPost (HttpServletRequest req, HttpServletResponse res)
          throws ServletException, IOException {

           ....
           String urlRedirect = "ShowConfirmation.jsp"
           res.sendRedirect(urlRedirect);

      }
    }

    If the code is correct, for the URL parameter, does it have to be a full URL (e.g. http://localhost/myapp/ShowConfirmation.jsp) or just simply the JSP filename (as shown above)? That is, the container will take care of the context-path mapping?

    Also, can sendRedirect accept a servlet name instead of a JSP filename? If for example, there is a servlet called ProcessAccountServlet, can the following code work?

           String urlRedirect = "ProcessAccountServlet"
           res.sendRedirect(urlRedirect);




    > On the other hand, if you used a client-side redirect, only the ShowConfirmation.jsp will be refreshed (which is probably what you want).
    >
    > Forward operations are useful when you don't want the browser's address bar to be updated. Error pages are a good situation for using forward operations. Front Controllers in web frameworks that intercept all requests also use forward operations.
  4. Hi Paul,

    >
    > Thanks for the detailed explanation, really appreciate it :)
    >
    > I have some questions on certain parts of your reply:
    >
    > > Includes: RequestDispatcher.include() and <jsp:include> both include content. The included page is inserted into the current page or output stream at the indicated point. These operations can be used to assemble content into a single logical page:
    > >
    > > <jsp:include page="header.html" />
    > > [Main page conten here.]
    > > <jsp:include page="footer.html" />
    > >
    > > The header and footer can therefore be common to many different pages.
    >
    >
    > Is <jsp:include> the same as <%@ include file="jspfile" %>?
    >
    > If not, what is the difference between them, and any examples to illustrate their usage?

    > > > <%@ include file="jspfile" %> - inlines the content into the current page. since any changes in this jspfile result into compilation of current page also. If more number of pages includes this page would result in recompilation of all the pages. would affect the performance significantly if you have a staic content which is changed regularly.


    > > ><jsp:include> - includes the content into the outputstream. Any changes to your jspfile need not require recompilation of other pages.
    >  
    > > Forward and Redirects: The forward and redirect operations both replace content. The current page or output stream is terminated, and is replaced with the output of the specified page.
    > >
    > > Forwards: Both <jsp:forward> and RequestDispatcher.forward() are what I refer to as "server-side" redirects. The redirect operation is performed in the server side, and the browser is unaware of the change. If page1.jsp forwards to page2.jsp, the browser's address bar will still show page1.jsp
    > >
    > > Redirects: The response.sendRedirect() is what I call a "client-side" redirect. The redirect operation is passed to the browser, which is aware of the change. If page1.jsp redirects to page2.jsp, the browser's address bar be updated to show page2.jsp.
    > >
    > > Forwards vs. Redirects: You choose between forwards and redirects depending on how you want the browser to be affected. Forward operations are faster, because all the processing happens server-side. Redirect operations update the browser history, however, which is often desirable.
    > >
    > > If you forward between page1 and page2, if the user's clicks the "refresh" or "reload" button, both page1 and page2 are executed a second time. On the other hand, if you use a client-side redirect, the browser's address information is updated. If the user clicks refresh, only page2 are re-executed.
    > >
    > > I use redirects to separate update components from display components. Suppose you have a ProcessPaymentServlet and a ShowConfirmation.jsp that informs the use that their payment has been processed. If you used a forward operation between them, if the user refreshed the page, both the servlet and the JSP would be re-executed, for a second payment.
    >
    >
    > Does this mean that in the servlet code, you will have something like this:
    >
    > public class ProcessPaymentServlet extends HttpServlet {
    >    ...
    >   public void doPost (HttpServletRequest req, HttpServletResponse res)
    >       throws ServletException, IOException {
    >
    >        ....
    >        String urlRedirect = "ShowConfirmation.jsp"
    >        res.sendRedirect(urlRedirect);
    >
    >   }
    > }
    >
    > If the code is correct, for the URL parameter, does it have to be a full URL (e.g. http://localhost/myapp/ShowConfirmation.jsp) or just simply the JSP filename (as shown above)? That is, the container will take care of the context-path mapping?
    >
    >>>
    > Also, can sendRedirect accept a servlet name instead of a JSP filename? If for example, there is a servlet called ProcessAccountServlet, can the following code work?
    >
    >        String urlRedirect = "ProcessAccountServlet"
    >        res.sendRedirect(urlRedirect);
    >
    >
    > > > You need to take care of the context in your url. It accepts servlet.
            String urlRedirect = "/myapp/ShowConfirmation.jsp"
            res.sendRedirect(urlRedirect);


    >
    >
    > > On the other hand, if you used a client-side redirect, only the ShowConfirmation.jsp will be refreshed (which is probably what you want).
    > >
    > > Forward operations are useful when you don't want the browser's address bar to be updated. Error pages are a good situation for using forward operations. Front Controllers in web frameworks that intercept all requests also use forward operations.
  5. <jsp:include> vs. <%@ include file="jspfile" %>: The <jsp:include> action tag is what I call a "runtime include". The inclusion occurs during JSP execution. Conversely, <%@ include file="jspfile" %> directive is what I call a "compile-time include". Inclusion occurs when the JSP page is compiled.

    In general, <jsp:include> is better. If you use <%@ include file="jspfile" %> for headers and footers, the header and footer will be duplicated in every compiled page. If your header code uses up 5000 bytes, and you have 500 pages, that is a waste of 2.5 Mb. With a runtime include, the pages and header/footers are assembled at runtime, which is much more memory effecient.

    The exception to the rule are instructions that must be compiled into the page to be effective. For example, if you want to put your custom taglib imports in an include file (a good idea), you must use <%@ include file="jspfile" %>, because the taglib imports only work if they are compiled into the page.

    Redirects in servlets: The code you wrote, which I copied below, is typically of how I recommend servlets redirect to JSP:

    public class ProcessPaymentServlet extends HttpServlet {
       ...
      public void doPost (HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {

           ....
           String urlRedirect = "ShowConfirmation.jsp"
           response.sendRedirect(urlRedirect);
      }
    }

    Relative vs. Absolute URLs: Hmm. This is another kettle of worms. As a rule, relative URLs are fine. But, you must be aware of what they are relative to. A relative URL in a servlet is relative to the URL of the servlet. Since you can define URL mappings arbitrarily, this can be anything.

    Suppose your servlet URL patterns is:

    <url-pattern>/checkout/ProcessPaymentServlet</url-pattern>

    If your JSP were at the root directory of your application, your relative URL must go one "directory" up:

    String urlRedirect = "../ShowConfirmation.jsp"
    response.sendRedirect(urlRedirect);

    Site-Relative URLs: A way around this problem is to use Site-Relative URLs, that begin with a "/". Your redirect can be written as:

    String urlRedirect = "/ShowConfirmation.jsp"
    response.sendRedirect(urlRedirect);

    The extra "/" at the beginning informs the browser to resolve the URL relative to the root directory of the web server, so that the URL will resolve correctly even if your Servlet URL changes.

    In final consideration: your web application may have a context path, and this must be prepended to the beginning of all site-relative URLs:

    String urlRedirect = request.getContextPath() + "/ShowConfirmation.jsp"
    response.sendRedirect(urlRedirect);
  6. what woul be the output[ Go to top ]

    response.sendRedirect("error.jsp"); out.println("hello"); RequestDispather rd=request.getRequestDispatcher("error.jsp"); out.println("hello"); what would be the output in both cases?
  7. Thanks[ Go to top ]

    Hey thanks a lot :)

    I was trying to  figure out some way to work this out... just helped a lot... great explanation :)