I haven't still found a definitive implementation of PRG pattern with JSF2.
The BalusC blog presents a very good solution, but as the author himself states, such a solution does not apply for JSF2.
The solutions based on Flash scope work fine if no validations error occurs, but in case of validation error the REDIRECT is not executed because the lifecycle does not call the NavigationHandler. Assuming that pages are not cached by the browser (setting the right headers in the HTTP response), if a validation error occurs and the user clicks the "reload" browser button then a POST is executed, not a GET.
What's the best practice for implementing a robust PRG pattern which works even on validation errors using JSF2?

- 417
- 5
- 13
1 Answers
I'm facing the same challenge. Did not find a 100% satisfying solution. But look to this approach from BalusC. This solution will not preserve values if hitting the browsers back button without browser cache control.
<h:form>
<h:inputText id="somefield" required="true" value="#{formbean.someProperty}"/>
<h:message for="somefield" />
<h:commandButton value="POST with redirect and ajax" action="third?faces-redirect=true">
<f:ajax execute="@form" render="@form" />
</h:commandButton>
</h:form>
Load the page, leave the field empty, post the form (-> error message appears), enter data, post again and now hit the back button. This will show the form again, the error message has gone but the input field value has also gone.
Assuming you preserve the formbeans value somehow (session scope, using the flash, view-params, ...), you could disable the browsers cache causing a page reload (GET-requested) when hitting the back button. I did this per page with the following code:
JSF-Page:
<f:view>
<f:event type="preRenderView" listener="#{formbean.doNotCache}"/>
</f:view>
Bean:
public void doNotCache(ComponentSystemEvent event) {
// Using Omnifaces to simplify code
Faces.getResponse().setHeader("Pragma", "no-cache");
Faces.getResponse().setHeader("Cache-Control", "no-cache");
Faces.getResponse().addHeader("Cache-Control", "must-revalidate");
Faces.getResponse().addHeader("Cache-Control", "no-store");
}
I will see if this solution holds on real world sites. In my opinion their should be a configuration option for the validation system offering a consequent use of the Post-Redirect-Get-Pattern. It should redirect (not forward) invalid forms. (Probably not a trivial task, for example howto handle/redisplay invalid fields?). Perhaps I'm wrong but it feels like a similar option is missing.