667481 members! Sign up to stay informed.

Sponsored Links


Resources

Enterprise Java
Research Library

Get Java white papers, product information, case studies and webcasts

J2EE patterns J2EE patterns J2EE patterns Messages: 39 Messages: 39 Messages: 39 Printer friendly Printer friendly Printer friendly Post reply Post reply Post reply XML XML XML

Post/Redirect/Get pattern for web applications

Posted by: Michael Jouravlev on August 14, 2003 DIGG
Being able to refresh a web page in the web application is an important usability feature. Also it is an MVC concept showcase: web page is a view for the underlying model, it is a window through which a user looks at the data.
 
Two most popular browsers: MSIE and Netscape/Mozilla have different names for the page refresh operation. IE uses more user-friendly "refresh", while Netscape uses more technical "reload". I prefer "reload" as a more correct term, but in fact both reload and refresh operations take place when a user tries to renew the page in the browser.

Very often a user is completely unaware that browser resends information to the server during page reload. Even if a browser warns user that information should be resent to the server, a user often cannot understand the technical meaning of the warning. Let us trace what happens during standard form submission process.

* The first page containing an input form could be obtained from the server using either GET or POST. If GET was used, then a user can refresh this page without seeing nagging "Information must be resend" message. Still, if this GET has attached parameters, they would be resent to the server.
* After a user fills out the form, it is submitted to the server. POST method is usually used for sending forms.
* Server responds with a result page.

The result page may look completely innocent, with no forms or any active elements, just some boring results from the database. For anyone remote from the internet development it seems completely legal and easy to refresh this page. Most people think that word "refresh" means exactly what it sounds: reload the page with its data from the server.

But in fact to refresh the result page would mean to re-issue the same request to the server which was used to obtain the page at the first place. That means, to do the whole POST of the form from the first page again. Here is where a user sees the "Information must be resend" message. Resending of the information may produce unwanted or inconsistent modifications of underlying data. Thus, these form resubmits must be properly handled by controller and model.

Now we are getting to the problem: because browser needs to resend the whole original request to obtain the result page, the refresh operation is not really MVC-compliant because user data is sent to the server. The solution of problem is quite simple – redirection.

This technique is actually pretty well known, but it is not standard yet for "after-post" results, and it does not have a well-known name. I call it "PRG request pattern", because it consists of three major parts: Post, Redirect and Get. The first one actually is not necessarily a POST, it is just that POST is most often used to send user data to the server. The last one must be GET so user would not see nagging messages. PRG request works in two stages:
* First a user-filled form is sent to the server using either POST or GET method. Server stores the information, updates the database and business model data, and replies with REDIRECT response for a View page.
* Browser loads View using GET, no user data is sent to the server at this point.

Now we have a clean MVC solution. When a user tries to refresh a result page, browser resends to the server "empty" GET request. All needed data is already on the server, so server just fills it in the page and sends back to the user.

What about back button? This works too, it returns us one step backwards, to the page with a form. This form can be refreshed as well. If it was obtained using GET, then user would not see warning message.

Page refresh works perfectly with redirection. We have to do the roundtrip to the browser, but one more second spent for redirection means little for interactive applications.
 
The only thing that have to be dealt with is intentional form resubmitting which happens when a user returns to the first page using Back button and submits form again. This should be checked by controller and a model and is out of scope of this pattern.

Bottom line: the PRG pattern provides the following benefits:
* it separates the View from Model updates;
* result page refresh does not cause form resubmit;
* page refresh is done using GET, so no messages are shown to a user

Threaded replies

·  Post/Redirect/Get pattern for web applications by Michael Jouravlev on Thu Aug 14 13:26:39 EDT 2003
  ·  Post/Redirect/Get pattern for web applications by Paul Strack on Sat Aug 16 19:28:33 EDT 2003
    ·  Parameters passing by Michael Jouravlev on Mon Aug 18 12:02:02 EDT 2003
      ·  Parameters passing by Paul Strack on Mon Aug 18 12:53:29 EDT 2003
        ·  Re: Parameters passing by Michael Jouravlev on Mon Aug 18 14:36:31 EDT 2003
  ·  One of the useless patterns that I've ever seen by Valerij Timofeev on Tue Aug 19 08:10:38 EDT 2003
    ·  Not really one of the useless patterns that I've ever seen by Matthias Buse on Wed Aug 20 05:26:20 EDT 2003
      ·  Re: Not really one of the useless patterns that I've ever seen by Valerij Timofeev on Fri Aug 22 07:22:27 EDT 2003
        ·  sgda by li lim on Fri Jun 26 23:36:24 EDT 2009
    ·  more overkill from theserverside, thanks by Rich Kucera on Wed Aug 20 10:47:01 EDT 2003
      ·  more overkill from theserverside, thanks by Valerij Timofeev on Fri Aug 22 08:59:52 EDT 2003
  ·  redirect is slow by Argyn K on Tue Aug 19 17:35:47 EDT 2003
  ·  Another approach for GUI state maintenance by Roberto Colmegna on Wed Aug 20 03:10:29 EDT 2003
  ·  Small additions by Maxim Wirt on Wed Aug 20 23:25:06 EDT 2003
    ·  RE: Small additions by Arnaud Mxxx on Fri Oct 15 12:04:12 EDT 2004
      ·  The Real Problem is this : by Arnaud Mxxx on Fri Oct 15 12:29:44 EDT 2004
    ·  Search Engine Optimization and Web Site Redirections by raj saxena on Sat Feb 10 14:57:22 EST 2007
  ·  Post/Redirect/Get pattern for web applications by Jason Carreira on Thu Aug 21 13:30:53 EDT 2003
  ·  Post/Redirect/Get pattern for web applications by Ragle Gumm on Wed Sep 03 11:19:24 EDT 2003
    ·  Post/Redirect/Get pattern for Struts applications by Jesper Udby on Wed Nov 19 08:56:10 EST 2003
      ·  Tokens are clearly the solution by Dan Allen on Thu Dec 18 02:07:28 EST 2003
        ·  Another question about form resubmit by Rahul Gupta on Tue Feb 03 18:08:20 EST 2004
        ·  Tokens are clearly the solution by joe gaber on Sun Sep 05 22:12:51 EDT 2004
      ·  Going one step further by uwe janner on Sun Dec 28 20:09:36 EST 2003
      ·  redirect in struts by Paul Kuit on Wed Aug 31 09:32:58 EDT 2005
        ·  struts redirect=true doesnt do it by Manish Pandit on Tue Nov 15 20:55:45 EST 2005
  ·  Scalability benefits of PRG by Matt Pouttu-Clarke on Tue Sep 16 10:15:17 EDT 2003
  ·  This pattern as built into the Web architecture by Hrvoje Simic on Sat Jun 05 04:31:38 EDT 2004
  ·  Post/Redirect/Get pattern for web applications by Serhiy Brytskyy on Sat Aug 28 05:53:16 EDT 2004
    ·  Post/Redirect/Get pattern for web applications by Michael Jouravlev on Sat Aug 28 21:25:36 EDT 2004
  ·  Some benchmarks of industry acceptance (from the trenches) by Matt Pouttu-Clarke on Sat Mar 12 21:30:51 EST 2005
  ·  pb with PRG : back button by Sebag David on Tue Jul 05 10:20:33 EDT 2005
    ·  pb with PRG : back button by Michael Jouravlev on Tue Jul 05 16:46:54 EDT 2005
  ·  Post/Redirect/Get pattern for web applications by Zobel Joachim on Thu Mar 16 17:53:33 EST 2006
  ·  Post/Redirect/Get pattern for web applications by David L?pez on Wed Mar 22 13:38:11 EST 2006
  ·  Struts: I am using last request time in session by Stas Sakalou on Fri Feb 23 23:53:34 EST 2007
  ·  One more supporter by Doug Danoff on Sun Mar 11 20:44:04 EDT 2007
  ·  Does not handle 'Back - Forward' by Jeetesh Chellani on Tue May 29 09:55:27 EDT 2007
  ·  Degree of coupling between POST:GET by Jeetesh Chellani on Tue May 29 10:12:06 EDT 2007
  ·  Post Method help by Ashique Raheem on Tue Sep 29 03:19:41 EDT 2009
  Message #92794 Post reply Post reply Post reply Go to top Go to top Go to top

Post/Redirect/Get pattern for web applications

Posted by: Paul Strack on August 16, 2003 in response to Message #92668
It's nice to see someone post this pattern. It is an approach that I have advocated for a while now, and often face some resistence to.

I do think it is important to list the limitations of this pattern though. Namely, unlike server forwarding operations, there is no easy mechanism to pass data between the component processing the POST (the controller) and the view. In fact, there are only two options:

1. Store data in the session.
2. Passing values as request parameters in the redirect operation:

     /<viewURL>?param1=value1&param2=value1

Despite this limitation, I think this is the correct approach to view invocation. In particular, properly applied, you can use this approach to make the view independent of the controller. All you need to do is ensure that all the information need to render the view should be passed as request parameters.

  Message #92866 Post reply Post reply Post reply Go to top Go to top Go to top

Parameters passing

Posted by: Michael Jouravlev on August 18, 2003 in response to Message #92794
<Paul>
All you need to do is ensure that all the information need to render the view should be passed as request parameters.
</Paul>
This is exactly what I am against of. From the rendering standpoint both operations shold be idempotent: (1) show the view right after form was posted and (2) show the view if refresh is requested. Any data the browser want to send to the server should be send during POST and kept on the server for all future view renderings. Where this data should be kept and when it should be removed is a different issue.

The point is, I want to be able to press F5 as many times as I want, and still get the properly rendered page filled with actual data. Basically, I am talking about updating Model during Post, and rendereing Model during Get. If Model was not changed, I should receive the same page, as 5 minutes ago.

  Message #92878 Post reply Post reply Post reply Go to top Go to top Go to top

Parameters passing

Posted by: Paul Strack on August 18, 2003 in response to Message #92866
I was not advocating sending *all* the information in the original POST to the view. Just enough information to render the page. Consider this example (using servlets and JSP, but the pattern applies to other web development technologies).

1. An "Edit Item" HTML form is submitted to an EditItemServlet via the POST method, including all item data.

2. The EditItemServlet loads the corresponding item object, updates its information and saves it.

3. The EditItemServlet sends a redirect operation [response.sendRedirect()] to a showItem.jsp, passing the primary key value as a parameter:

    showItem.jsp?id=#

4. The showItem.jsp retrieves the id parameter, loads the (possibly cached) item object using its id and displays its information.

The id parameter is important. It forms the conversational state between the client and server. Without it, the server has no easy way to know what information the client wants displayed. The server would have to retain this information in the session, and then your application would need to deal with session-timeout issues, clients that don't support cookies and so forth.

Another advantage of this approach is that the view is more reusable:

1. You could target the showItem.jsp page directly from a hyperlink, without first invoking the EditItemServlet. For example, from a page listing a bunch of items.

2. A "New Item" HTML form could target a CreateItemServlet that creates an item, auto-generates its id, inserts the results in the database and redirects to the same showItem.jsp used to render existing items.

  Message #92889 Post reply Post reply Post reply Go to top Go to top Go to top

Re: Parameters passing

Posted by: Michael Jouravlev on August 18, 2003 in response to Message #92878
Yes, you are right, some form of ID is necessary to identify a View. I suppose it would be "View ID" or "View Name". I did not stress that out, because View identification can be made by the url resourse name itself, without need to pass the additional parameter. But parameter makes it easier to show data, say, from a database.

  Message #92943 Post reply Post reply Post reply Go to top Go to top Go to top

One of the useless patterns that I've ever seen

Posted by: Valerij Timofeev on August 19, 2003 in response to Message #92668
>> Very often a user is completely unaware that browser resends information to the server during page reload.

This should be learned in a basic school ;-)

  Message #92996 Post reply Post reply Post reply Go to top Go to top Go to top

redirect is slow

Posted by: Argyn K on August 19, 2003 in response to Message #92668
1. redirect is slow, and must be used only when forward doesn't work
2. what's a problem with something being "not MVC"? There's no MVC in web applications. can not be. I mean the "original MVC" like in Smalltalk.

  Message #93020 Post reply Post reply Post reply Go to top Go to top Go to top

Another approach for GUI state maintenance

Posted by: Roberto Colmegna on August 20, 2003 in response to Message #92668
Another approach:
http://www.robertocolmegna.it/java

  Message #93029 Post reply Post reply Post reply Go to top Go to top Go to top

Not really one of the useless patterns that I've ever seen

Posted by: Matthias Buse on August 20, 2003 in response to Message #92943
> >> Very often a user is completely unaware that browser resends information to the server during page reload.

Very often a web application developer is completely unaware of the behaviour of the users he is developing for.

Users ARE using Reload/Back/Forward buttons and so web applications must be able to handle this without generating inconsistencies.

Because of that reason, patterns like this are quite important (but often ignored)!

  Message #93054 Post reply Post reply Post reply Go to top Go to top Go to top

more overkill from theserverside, thanks

Posted by: Rich Kucera on August 20, 2003 in response to Message #92943
Seems like everything is being dressed up in patterns these days.

  Message #93137 Post reply Post reply Post reply Go to top Go to top Go to top

Small additions

Posted by: Maxim Wirt on August 20, 2003 in response to Message #92668
I use this pattern and find it very useful. Often it's necessary to return to the same page where user comes from before posting.
The easiest way looks like:

response.sendRedirect(request.getHeader("referer"));

But it doesn't work always because some users use proxies that cut "referer" header. For this kind of users it's possible to use special custom tag inside the form that adds hidden field with URL of the page that contains the form (only if user's request doesn't contain "referer" header), say "backURL". Then we can use this:

String s = request.getParameter("backURL");
if(s == null)
  s = request.getHeader("referer");
if(s == null)
  throw new Exception("unable to return back");
response.sendRedirect(s);

  Message #93206 Post reply Post reply Post reply Go to top Go to top Go to top

Post/Redirect/Get pattern for web applications

Posted by: Jason Carreira on August 21, 2003 in response to Message #92668
In WebWork2 I implemented a token tag which, in combination with the token Interceptor, will make sure that the form can only be submitted once. If a duplicate post comes in, there are 2 strategies for what to do (in my implementation):

1) It returns an "error" code which is mapped to an error view for your Action

2) It can save the processed state of the first form post in the Session and re-render the final view the same as the first time.

  Message #93302 Post reply Post reply Post reply Go to top Go to top Go to top

Re: Not really one of the useless patterns that I've ever seen

Posted by: Valerij Timofeev on August 22, 2003 in response to Message #93029
>> Users ARE using Reload/Back/Forward buttons and so web applications must be able to handle this without generating inconsistencies.

perfectly right, but this pattern doesn't solve this problem completely:

"...The only thing that have to be dealt with is intentional form resubmitting which happens when a user returns to the first page using Back button and submits form again. This should be checked by controller and a model and is out of scope of this pattern."

So why the whole effort?

The only problem this pattern solves completely is that it illuminates "Information must be resend" message.

The price of the solution:
- slow redirect
- redefinition of standard behaviour of a web application (for internet aware users).

But I agree that the name of the "Refresh" / "Reload" button is far from perfect. May be web browsers should change the name of the button dynamically in dependence on the last action...

  Message #93310 Post reply Post reply Post reply Go to top Go to top Go to top

more overkill from theserverside, thanks

Posted by: Valerij Timofeev on August 22, 2003 in response to Message #93054
> Seems like everything is being dressed up in patterns these days.

something like voting for patterns on TheServerSide would be nice, on my opinion.

Thanks rating it would be possible to overfly inconsiderable patterns.

  Message #94395 Post reply Post reply Post reply Go to top Go to top Go to top

Post/Redirect/Get pattern for web applications

Posted by: Ragle Gumm on September 03, 2003 in response to Message #92668
I like the idea behind this pattern. It seems a framework such as struts could work with this to simplify the parameter passing (especially in the case where all form items are kept in session).

Even if a simple ID is used for the GET, I think struts would still work well -- just requiring more thought as to the ActionForm used.

Has anyone tried something like this in Struts?

  Message #95672 Post reply Post reply Post reply Go to top Go to top Go to top

Scalability benefits of PRG

Posted by: Matt Pouttu-Clarke on September 16, 2003 in response to Message #92668
This pattern can also be used to utilize the HTTP 1.1 caching correctly. Referring to a previous example:

showItem.jsp?id=#

If you got to this page through a POST without a redirect then the page will never be cached on the app server/web server, reverse proxy, proxy, or client layers.

By using a redirect and GET you can fully utilize HTTP 1.1 caching policys in the way they should be used. For example, if your items only change once a day you can set the Expires header for showItem.jsp (See ftp://ftp.isi.edu/in-notes/rfc2616.txt section 14.21). Then the results of showItem.jsp?id=# will be cached at each layer of the HTTP REST architecture. That means in effect that the JSP (and database) will only be called once per day for each item id accessed (depending of course on the resources available for caching at all layers in the architecture).

The scalability benefits of fully utilizing HTTP 1.1 far outweigh any additional overhead created by the redirect.

  Message #102030 Post reply Post reply Post reply Go to top Go to top Go to top

Post/Redirect/Get pattern for Struts applications

Posted by: Jesper Udby on November 19, 2003 in response to Message #94395
I've made a simple "super action" that helps implement the pattern with Struts.

For this to work, some information must be stored in the Session for the GET to work.
A simple "id" could be passed along the redirect, if it exists.

My PRGAction below:
-------------------
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

/**
 * @author Jesper Udby
 */
public abstract class PRGAction extends Action {
/**
* Handles the GET method.
* Returns an ActionForward - the JSP/whatever to display in response to the GET
*/
public abstract ActionForward executeGet(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception;

/**
* Handles the POST method.
* Returns an ActionForward - the JSP/whatever to display in response to the POST.
* Return null to have the action redirect to itself...
*/
public abstract ActionForward executePost(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response) throws Exception;

/**
* @see org.apache.struts.action.Action#execute(ActionMapping, ActionForm, HttpServletRequest, HttpServletResponse)
*/
public final ActionForward executeAction(ActionMapping mapping, ActionForm actionForm, HttpServletRequest request, HttpServletResponse response)
throws Exception {

ActionForward ret = null;
if ("GET".equals(request.getMethod())) {
ret = executeGet(mapping, actionForm, request, response);
}
else if ("POST".equals(request.getMethod())) {
ret = executePost(mapping, actionForm, request, response);
if (ret == null) {
String me = request.getServletPath();
response.sendRedirect(me);
}
}
return ret;
}
}

  Message #104519 Post reply Post reply Post reply Go to top Go to top Go to top

Tokens are clearly the solution

Posted by: Dan Allen on December 18, 2003 in response to Message #102030
While this solution might be nice to avoid the "resend information" nag message to clients, it really isn't a solution to the problem it poses to MVC.

All forms that cannot be submitted more than once for data integrity reasons should use TOKENS. You simply create a token, tuck it in the session and pass it to the view, then when the form submits, it checks to make sure the two values are equivalent, clears the token, saves the data and forwards to the view. If back or refresh are issued, the token will no longer be valid until the user goes back in the front door, and you are safe from the reprocessing.

Even better, when the refresh is issued, instead of showing the results page again, you can interpret the request as the user wanting to do something new and you take them to the next logical page.

  Message #105247 Post reply Post reply Post reply Go to top Go to top Go to top

Going one step further

Posted by: uwe janner on December 28, 2003 in response to Message #102030
in one of my last projects we used the same pattern and optimized it for back button usage: my problem was, that users use the back button and so often sees outdated data, e.g. a person's address, that has been changed in the meantime (by this user or someone else);
solution: we set the http-headers to no-cache, so clicking the back-button always reloads the page; because this page was retrieved via the redirect (PRG) it will fetch e.g. the actual person-data (http://...../person.view?id=xy)
but for some pages this behaviour is bad: if the user submits a search page, and then clicks back button, the search page should NOT be reloaded, because fields would then be empty and he had to type in everything again, but most often he just wanted to modify his last search, so the previously entered values should be displayed;
so we decided to set the no-cache headers dependent on the content of the resulting page:
search results & detail-views are always reloaded, all others may be cached by the browser; the decision whether to cache or not is best expressed as a custom tag in the jsp.

fusel.

  Message #109317 Post reply Post reply Post reply Go to top Go to top Go to top

Another question about form resubmit

Posted by: Rahul Gupta on February 03, 2004 in response to Message #104519
>
> All forms that cannot be submitted more than once for data integrity reasons should use TOKENS.

I am working with website in which a user can login and then submit different forms. I want the user to avoid submitting the same form twice by using the browser refresh or back buttons. I also want to give user the ability to resubmit the forms with a different data. If TOKENS are used, the user can submit one form only once.

Is there a suitable solution where a form with same data is submitted only once, but there is no such restriction with different data? I do not want to use redirection after POST, as there are large number of different forms and then each will have to be redirected to a seperate page. (I dont think storing ALL the information filled in each form during that session and then comparing for resubmit is a clean solution).

  Message #124743 Post reply Post reply Post reply Go to top Go to top Go to top

This pattern as built into the Web architecture

Posted by: Hrvoje Simic on June 05, 2004 in response to Message #92668
I'm glad people finally got talking about elementary patterns of Web applications. I propose restricting this pattern to its true form: a POST-request followed by a 303-response. These ideas are not mine, they are directly copied from "the manual" (RFC 2616) and the pattern itself is built into the Web architecture.
You should never use GET for "sending data" to the server. This is specified in RFC 2616 and it is the principle difference between GET and POST. GET is a safe method and it should not perform any user-responsible transactions on the server's business data. The "Information must be resend" message is just a consequence of this rule.
No specific redirect code is mentioned anywhere on this page, but I suppose you would use "the default" 302 (Found). The redirect response code should be 303 (See Other). The RFC 2616 definition of the code directly refers to this pattern. The good deal of browsers popular today misinterprets 302 as if it were a 303, so in practice you may find that it amounts to the same thing. However, I believe that it pays off sticking to the "clean" code 303, since the client with strict interpretation of the specification will respond to a 302 response with a repeated POST request to the new URI, a very bad turn of the events. 303 is properly interpreted by all modern HTTP clients, so you should not expect serious problems by using it.
The problem with the token approach is that it breaks the Web architecture. Masking session-control data as resource identifier, avoiding idempotency of GET, blurring the responsibilities of resources and other tricks to get the protocol to work against its design is just bad engineering to me. I believe all these problems can be solved by working within the Web architecture, not for the sake of the architecture itself, but for the sake of the Web developers.
I believe that 303-response is the best response to the POST-request, in every situation. It's too bad that it requires two HTTP-exchanges instead of one, but as Matt Pouttu-Clarke noted, it actually has less overhead then a POST-200 exchange.

  Message #136075 Post reply Post reply Post reply Go to top Go to top Go to top

Post/Redirect/Get pattern for web applications

Posted by: Serhiy Brytskyy on August 28, 2004 in response to Message #92668
What is bad, redirect clear all request data. What can I do, if I need to put some/all data from previous request, or add additional data and put them into next request?

  Message #136109 Post reply Post reply Post reply Go to top Go to top Go to top

Post/Redirect/Get pattern for web applications

Posted by: Michael Jouravlev on August 28, 2004 in response to Message #136075
What is bad, redirect clear all request data. What can I do, if I need to put some/all data from previous request, or add additional data and put them into next request?
You have two choices: either temporary save it on the server, say in the HttpSession, or stick it in the destination URL of redirect response. The latter is not really a solution because it ruins the whole idea of refreshing result page using just object ID. So, my anwer is: store all business data on the server, and set up object ID only in the destination URL. See the "Using PRG pattern" article: http://www.theserverside.com/articles/article.tss?l=RedirectAfterPost

  Message #136936 Post reply Post reply Post reply Go to top Go to top Go to top

Tokens are clearly the solution

Posted by: joe gaber on September 05, 2004 in response to Message #104519
While this solution might be nice to avoid the "resend information" nag message to clients, it really isn't a solution to the problem it poses to MVC.

All forms that cannot be submitted more than once for data integrity reasons should use TOKENS...
Do you have some example code of how you do this? I am new to MVC pattern.

  Message #142725 Post reply Post reply Post reply Go to top Go to top Go to top

RE: Small additions

Posted by: Arnaud Mxxx on October 15, 2004 in response to Message #93137
Often it's necessary to return to the same page where user comes from before posting.
The easiest way looks like:

response.sendRedirect(request.getHeader("referer"));

[...]
Why don't you let the user click on the BACK button of his browser ???
This is a very basic feature for a browser, and one of the first things a browser-user learns !! Don't you think ?
HTTP is a very simple protocol ; web applications should aim to be as simple as possible. (I know it gets hard sometimes.)
I agree 100% with the PRG pattern, I always use it. One should never be confronted to the "you're about to resend POSTDATA" message.

Cheers.

  Message #142727 Post reply Post reply Post reply Go to top Go to top Go to top

The Real Problem is this :

Posted by: Arnaud Mxxx on October 15, 2004 in response to Message #142725
I think, the real problem is when a form (POST-submitted) is not validated by the application. What should happen in this case ?

From the user point of view, it's easy : we are expecting to see the form filled with the data previously entered (except passwds, maybe), and showing [in red] the error(s) that made the form not to be validated.

But what happens if the user hits 'refresh' on this page ? Should he see the "resend POSTDATA" message ? I think not.
That means that the application, after not validating the POSTed data, should send a REDIRECT, to the page that displays the form. And this is when an important part of the framework enters in game : the form should detect that the user is "back from error", and fill the form with the previously posted data, which would have been saved in session, before the REDIRECT. (The data should not be passed in the URL, since it may be very large.) So, two or three informations are put in session :
 - the previously posted data
 - all the error messages
 - a Boolean indicating that the form should be displayed in 'backFromError' mode, which can also be set as a request parameter in the URL.

And what happens if the user hits the "refresh" button ? It depends on what the designer wants ; the form could display the same data again, or the initial blank form.

An exception for this is the (quite rare) case where it is clearly specified that the application should not use cookies (no cookies = no session). Then, I suggest that the application should not send a REDIRECT after the post, but simply re-display the form with the data contained in the request.
This is not PRG, but users should accept cookies ! cookies are good !

I can give some simple practical examples if you want.

Cheers

  Message #161298 Post reply Post reply Post reply Go to top Go to top Go to top

Some benchmarks of industry acceptance (from the trenches)

Posted by: Matt Pouttu-Clarke on March 12, 2005 in response to Message #92668
I just wanted to comment that previous to Michael Jouravlev's PRG pattern posting 100% of all Java web applications I had worked on or seen were constructed in violation of PRG, by using POST to display content. Before HTTP 1.1 connection keep alive came around implementing PRG would have involved a new TCP/IP connection for each redirect; so maybe it is understandable that the best practice used to be using one HTTP request/response cycle to update business state AND display the next page.

As it stands, I believe that the emergence of this pattern shows how critical it is for web application architects and developers to pay attention to the underlying protocols, not just the APIs and file formats. Innovations in the protocols can and should result in fundamental changes not only in infrastructure tools but in the web applications themselves. (Maybe some of the .NET geeks can comment on the impact of the PRG pattern on the fundamental design of ASP.NET "stateless" sessioning using hidden fields, which requires a form POST for every page transition)

I just got off a gig as Senior Consulting Architect for DaimlerChrysler B2C (NAFTA). One of the things I did there was implement PRG as a legally binding standard for all B2C HTTP applications. These standards are written into all vendor’s contracts so they are heavily scrutinized by many very talented and experienced people including major IT consulting vendors such as IBM and Compuware.

We went though all the discussions on this pattern POSTing and then some. What we came up with is that a web application never has to use POST to display content except in the case of a system generated error which the user should be allowed to resubmit using the browser reload function. For example, a page (with a 500 status code) saying "Your transaction failed due to <whatever>, please click 'Refresh' to try again"

  Message #176720 Post reply Post reply Post reply Go to top Go to top Go to top

pb with PRG : back button

Posted by: Sebag David on July 05, 2005 in response to Message #92668
I am using this pattern, and it works quite fine but I have a problem with the back button : it goes 2 pages back instead of one. It is the same problem with any browser.
The test is :
- I enter the site. It's a form page.
- I submit the form, the server proceed a redirect to a second form,
- I submit the second form. There 's another redirect to a third page.
- I press the back button
Then, the page is the first form !

Anybody has an idea ?

  Message #176788 Post reply Post reply Post reply Go to top Go to top Go to top

pb with PRG : back button

Posted by: Michael Jouravlev on July 05, 2005 in response to Message #176720
I am using this pattern, and it works quite fine but I have a problem with the back button : it goes 2 pages back instead of one. It is the same problem with any browser.The test is :- I enter the site. It's a form page.- I submit the form, the server proceed a redirect to a second form,- I submit the second form. There 's another redirect to a third page.- I press the back buttonThen, the page is the first form !Anybody has an idea ?
Do your second and third form have the same location? I mean, exactly the same, base URL and names and number of parameters? What may happen is that you display second and third pages from the same location, from the same controller or action or whatever it is. If this is true, most browsers would consider these two pages as one resource.

Actually, this is the neat trick that can be used to create single-page components, which do not allow you to go to the previous page simply because all pages are served from the same location. For example, see this sample. Both pages of login component are served from one location, so you cannot go back to the previous page. This is intended behavior.

By the way, try Opera, it usually caches every single page instead of every resource. But most other browsers do not behave like Opera, and use resource locations for page history. If locations are the same, they consider the resources are the same too.

Michael.

  Message #183097 Post reply Post reply Post reply Go to top Go to top Go to top

redirect in struts

Posted by: Paul Kuit on August 31, 2005 in response to Message #102030
Uhh? Like this you complete ignore the forward mechanism struts offers you!

SIMPLY DEFINE THE FORWARD TAG WITH REDIRECT="TRUE"!

map.findForward("myRedirectedForward");

But take care, as discussed, you loose your current request...

  Message #191233 Post reply Post reply Post reply Go to top Go to top Go to top

struts redirect=true doesnt do it

Posted by: Manish Pandit on November 15, 2005 in response to Message #183097
I tried doing redirect="true" in the action forwards. It does not work. I eventually ended up using tokens and it did the job for me!

To give a context:

To test redirect, I used it for the login action, where the user enters credentials, and is then taken to an action as POST (something like login.do), which, upon success, forwards to something like an index_postlogin.jsp. The browser shows http://url/login.do, with postlogin.jsp rendered as the page. If I click refresh, it relogs the user (I do see the browser warning about the POST resubmit). I used redirect="true" but didnt solve the problem.

  Message #204029 Post reply Post reply Post reply Go to top Go to top Go to top

Post/Redirect/Get pattern for web applications

Posted by: Zobel Joachim on March 16, 2006 in response to Message #92668
Hi.

This has been around since at least 2001.

http://www.catstep.de/zobel/post2redirect.html

Note that the page has not been maintained since, so it is a bit outdated. Nice to see it find wider acceptance.

  Message #204418 Post reply Post reply Post reply Go to top Go to top Go to top

Post/Redirect/Get pattern for web applications

Posted by: David L?pez on March 22, 2006 in response to Message #92668
Relating the "Post" in the post/get/redirect pattern, I would remark that the real point isn't that the method actually executed was "post" or "get", nor that any data was sent to the server.

The important point is that the "post" is really an action, that executes changes in your server, no matter the method is post or get, no matter any data was sent. Therefore it isn't idempotent, and cannot be repeatedly executed without unpredictable results.

  Message #227277 Post reply Post reply Post reply Go to top Go to top Go to top

Search Engine Optimization and Web Site Redirections

Posted by: raj saxena on February 10, 2007 in response to Message #93137
On-Page Redirection is highly objectionable from Search Engine Optimization point of view. Most of the Web Sites fail to recognise the importance of their Main Page (Homepage). Several online companies and big multinational companies redirect their web sites onload.

Whenever there needs to add a redirection feature, make sure that there is a gap interval of 5-7 sec, otherwise your website could be in trouble from Search Engine Optimization Point of View.

regards
Raj
Web Site Promotion SEO Search Engine Optimization

  Message #228053 Post reply Post reply Post reply Go to top Go to top Go to top

Struts: I am using last request time in session

Posted by: Stas Sakalou on February 23, 2007 in response to Message #92668
1.JSP form must have a parameter:


<!-- Remember system time. Use this parameter to avoid
dupplicate requests-->
<input type="hidden" name="request_time" value="<%=System.currentTimeMillis()%>"/>

You Struts action should have one method

*********************************************************************************************
* Return true if this request is due to browser reload button effect
*********************************************************************************************/
public boolean isRepeated(final HttpServletRequest request)
{
// This flag is used to avoid recurring calling
final String this_request_time = request.getParameter("request_time");
final String last_request_time = (String)request.getSession().getAttribute("last_request_time");
if (this_request_time==null)
{//page does not need validation
return false;
}
else
{
//Time of the last request should be stored in session to avoid recurring calls
request.getSession().setAttribute("last_request_time",this_request_time);
if (last_request_time==null)
{//page does not need validation
return false;
}
else
{//If page needs validation then check that time of the last request is not the same as time of this request
return last_request_time.equalsIgnoreCase(this_request_time);
}
}
}

Inside execute action you should put in the very beginning

if (isRepeated(request))
{//This is the same call, that have already been processed. Don't do anything
return mapping.findForward("success");
}
You are all set !

  Message #229041 Post reply Post reply Post reply Go to top Go to top Go to top

One more supporter

Posted by: Doug Danoff on March 11, 2007 in response to Message #92668
Michael, Thanks for this post. I've tried to sell this solution to 2 big projects, and was not successful on both. Your work in this area will hopefully help with the next one.

I'm working mostly in the ASP.NET space recently. Server.Transfer() a.k.a. "forward" is causing the POST/FORWARD issue to be more prevelant in ASP.

I have posted a little write-up of my own on this topic:
http://www.strong-point.com/Blogs/tabid/87/EntryID/8/Default.aspx

  Message #233637 Post reply Post reply Post reply Go to top Go to top Go to top

Does not handle 'Back - Forward'

Posted by: Jeetesh Chellani on May 29, 2007 in response to Message #92668
The scenario is GET1 -> POST2:GET2 where ':' indicates redirection.

GET1 creates a new model required for rendering the view. The view is a form which on submission binds the request parameters to the model. These parameters are used by GET2 for rendering the view. Now when I do a Back 'GET1' gets fired which renders the previous view. But when I click on forward since the model has changed by GET1, the request goes to GET2 and since it does not have the parameters bound in 'POST2' and hence it crashes.

Kind Regards,
Jeetesh

  Message #233638 Post reply Post reply Post reply Go to top Go to top Go to top

Degree of coupling between POST:GET

Posted by: Jeetesh Chellani on May 29, 2007 in response to Message #92668
GET requires some parameters for creating model while rendering view. In a POST:GET scenario POST can provide those parameters thru some session object. But in that case I cannot reuse GET in isolation.

So what is the best practice for avoiding the above limitation ?


Kind Regards,
Jeetesh

  Message #310365 Post reply Post reply Post reply Go to top Go to top Go to top

sgda

Posted by: li lim on June 26, 2009 in response to Message #93302
GOOD LIFE GODO WORK!

.............................................
.............................................

  Message #322623 Post reply Post reply Post reply Go to top Go to top Go to top

Post Method help

Posted by: Ashique Raheem on September 29, 2009 in response to Message #92668
I currently use the Get method when submitting forms. Is it worth that i changed to post method. I understand that post method enables a lot of security but bascially my website has less information to hack on.

Regards
SEO Services UK

J2EE PatternsJ2EE PatternsJ2EE Patterns
Patterns

We are proud to provide this patterns/strategies repository to the community. Feel free to post any useful design tips you know!

EJB Design Patterns PDFEJB Design Patterns PDFEJB Design Patterns PDF

EJB Design Patterns is now available for free download in PDF format. The book contains a catalog of twenty advanced EJB patterns and provides strategies for mapping application requirements to patterns-driven design, J2EE development best practices, and more. EJB Design Patterns was the #2 book at Java One 2002, and held the #1 Java book position on Amazon.com for weeks since the book was released in March. Download your PDF here.
Useful patterns around the webUseful patterns around the webUseful patterns around the web
Patterns

EntityBeansAsDomainObjects

This essential pattern describes how to model your entity beans.

The Aggregate Entity pattern

How to make an entity bean a facade to a set of dependent objects.

EJB Unit Testing Strategies

Every guru should use unit testing.

Other Patterns sitesOther Patterns sitesOther Patterns sites

Portland Patterns Repository

The original reference site for patterns. Frequented by the gang of 4 and their mentors (Kent Beck, Ward Cunningham).

Sun Java Center Patterns

A catalogue of J2EE design patterns from Suns Consulting Division.

IBM Patterns for e-Business

A catalogue of high level business, architectural and topological patterns for large scale systems.

J2EE Blueprints Patterns

Design Patterns from the J2EE Blueprints, Suns authoritative guide to J2EE development.


News | Blogs | Discussions | Tech talks | Patterns | Reviews | White Papers | Downloads | Articles | Media kit | About
Java Solutions
All Content Copyright ©2007 TheServerSide Privacy Policy
Site Map