14. Implementing Post/Redirect/Get (PRG) Pattern

PROBLEM

Post/Redirect/Get (PRG) is a common design pattern for web applications, to help avoid duplicate form submissions and allow web applications to behave more intuitively with browser bookmarks and the reload button. After a web user submits a form to a server, the server typically generates an HTML page as a response. To the user, this looks like an ordinary web page, but because it was generated by an HTTP POST request, it cannot be bookmarked, and attempting to reload/refresh the page in the browser could cause the form information to be resubmitted, possibly with unexpected results (such as a duplicate purchase). Wikipedia

SOLUTION

To avoid this problem, many web applications use the PRG pattern — instead of returning an HTML page directly, the POST operation returns a redirection command (using the HTTP 303 response code (sometimes 302) together with the HTTP "Location" response header), instructing the browser to load a different page using an HTTP GET request. The result page can then safely be bookmarked or reloaded without unexpected side effects. Wikipedia

HOW IT WORKS

When a post is made to a Skyway Operation, the View is configured to send a redirect command to the browser to a second URL, using the URL mapping's redirect option. The redirect results in a second request (get) being automatically made by the end-user's browser to another URL. The second URL is mapped to an operation for loading the model data before being directed to a JSP page for rendering the view. The redirect results in the second URL being listed in the browser's address bar. If the end-user refreshes the page, the original data won't be resubmitted because only the second URL will be reloaded. If the second URL is configured with an Operation that loads data, a bookmarked page can be reconstituted.

The following fragment shows two URL mappings working in tandem to implement the PRG pattern.

Example 2.7. URL Mapping - Post/Redirect/Get (PRG)

URL                                        OPERATION                         VIEW 
----------------------                     ----------------------------      ---------------------------------
/MyController/SaveOperation.action 1 --> SaveOperation 2             --> edit.html (w/ REDIRECT) 3
/edit.html 4                         --> LoadOperation 5             --> edit.jsp 6
          

1

When data is posted to the server, the form is configured to post to the /MyController/SaveOperation.action URL.

2

The URL mapping for /MyController/SaveOperation.action is configured to invoke SaveOperation, which presumably processes the user input.

3

Rather than emitting the view directly using a JSP, the View is configured to redirect to a second URL, specified as edit.html.

4

The edit.html URL has it's own URL mapping entry (get).

5

The URL mapping for /edit.html is configured to invoke LoadOperation to load data.

6

The view for edit.html is rendered using the configured JSP page (edit.jsp)

As far as the end-user is concerned, they submitted data to the application and they received a response, and they are generally unaware that two http requests were used to accomplish it.

RELATED RECIPES

  1. Mapping URLs to Operations and Views

  2. Creating Helper Methods using Operations

  3. Reusing Operations in Different Contexts

  4. Hiding the Implementation Technology