Forward vs Redirect
http://alltiers.com/pages/jsf/jsfRedirect.jsf
While navigating to another page, the default behaviour of the JSF Controller Servlet, is to use page forwarding. Unfortunately this means that a user will be unable to bookmark a page as the browser will always display the previous pages URL in its address bar.
JSF does support the notion of a page redirect that is implemented in the FacesConfig.xml as follows:
This means that a
Under the above navigation rule, when the user presses the Add button the browser will display /pages/state.jsf in the address bar. Without the redirect being specified, the browser would display /pages/country.jsf.
Defining a navigation case as redirect causes JSF to send a redirect response that asks the browser to request the required new view. This works fine as long as the validation is contained by JSF. If you have additional validation ( for example that there must be at least one State per Country ) that is evaluated in your code, then the redirect will cause:
- Your coded messages to be lost
- The potential loss of the users inputted Data as the page is re-directed to itself causing a new View of your pre-saved Data
Thus, the disadvantages of a Redirect are as follows:
- Redirect is a two step process, where the web application instructs the browser to fetch a second URL, which differs from the original. Thus, a redirect has a slight performance penalty over forward.
- Managed Beans placed in the original request scope are not available to the second request
- The Redirect must be specified for every Navigation Case.
- Possible Loss of Messages and or data
To solve this we have implemented a ReDirect Listener that handles the redirect for us. Basically each navigation will cause a redirect unless error messages exist. The problem with this approach is that it assumes:
- All pages will be re-directed
- A page will not be re-directed if it contains Error Messages.
For us, the advantages of being able to bookmark every page and not having to specify for every navigation case far exceed these minor inconveniences:
FacesConfig.xml will not specify redirect and will contain the definition of the ReDirect Listener
AReDirectListener.java
public class ARedirectListener implements PhaseListener { // Logger private static final Log log = LogFactory.getLog(ARedirectListener.class); private static final String POST = "POST"; public ARedirectListener() { } public PhaseId getPhaseId() { return PhaseId.ANY_PHASE; } /** * ReDirect to the next page only if there are no Error Messages. */ public void beforePhase(PhaseEvent _event) { // We do this only for the RENDER_RESPONSE Phase if (_event.getPhaseId() != PhaseId.RENDER_RESPONSE) { return; } // Get the Current Request FacesContext facesContext = _event.getFacesContext(); HttpServletRequest servletRequest = (HttpServletRequest) facesContext.getExternalContext().getRequest(); // If POST Method if (POST.equals(servletRequest.getMethod())) { // Get the next View ID and URL String nextViewID = facesContext.getViewRoot().getViewId(); String nextViewURL = facesContext.getApplication().getViewHandler().getActionURL(facesContext, nextViewID); // re-direct to the Next URL if Messages don't Exist try { // If the Form does not have Messages re-direct // Else use Default Navigation as defined in Faces Config // We-Default to re-direct so the URL will represent the Page they are on // and so the user can properly refresh their page // We do this because during a re-direct the Messages are Lost // and any user input is refreshed from what is currently in the model if (!AFacesUtility.isMessagesRendered(facesContext)) { log.debug("Redirecting to " + nextViewURL); facesContext.getExternalContext().redirect(nextViewURL); } else { log.info("Messages Exist - Staying on the Same Page"); } } catch (IOException ex) { log.debug("beforePhase() -- Error re-directing to " + nextViewURL + " and Id = " + nextViewID, ex); AErrorHandler.displayPhaseListenerException(facesContext, ex); } } }
No comments:
Post a Comment