Search code examples
jsfjsf-2post-redirect-get

JSF 2 and Post/Redirect/Get?


Please correct me if I'm wrong, but I'm thinking of all of my non-AJAX submits should use the Post/Redirect/Get (PRG) way, since GET should be used to refresh/query data, and in my case, the application pages I can think of really only do update on the data and then refresh the page, so I think PRG fits here.

I believe I can do this using the faces-config.way, where I make use of the <redirect/>, or I can use the return "myview.xhtml?faces-redirect=true";

Now the question is ..

Is there any way I can configure this globally that for non-AJAX calls/submits, automatically make use of faces-redirect=true, so that my source is as simple as this:

return "myview";

Solution

  • You could do this with a custom ConfigurableNavigationHandler. Here's a kickoff example:

    package com.example;
    
    import java.util.Map;
    import java.util.Set;
    
    import javax.faces.application.ConfigurableNavigationHandler;
    import javax.faces.application.NavigationCase;
    import javax.faces.application.NavigationHandler;
    import javax.faces.context.FacesContext;
    
    public class RedirectNavigationHandler extends ConfigurableNavigationHandler {
    
        private NavigationHandler parent;
    
        public RedirectNavigationHandler(NavigationHandler parent) {
            this.parent = parent;
        }
    
        @Override
        public void handleNavigation(FacesContext context, String from, String outcome) {
            if (!outcome.endsWith("?faces-redirect=true")) {
                outcome += "?faces-redirect=true";
            }
    
            parent.handleNavigation(context, from, outcome);        
        }
    
        @Override
        public NavigationCase getNavigationCase(FacesContext context, String fromAction, String outcome) {
            if (parent instanceof ConfigurableNavigationHandler) {
                return ((ConfigurableNavigationHandler) parent).getNavigationCase(context, fromAction, outcome);
            } else {
                return null;
            }
        }
    
        @Override
        public Map<String, Set<NavigationCase>> getNavigationCases() {
            if (parent instanceof ConfigurableNavigationHandler) {
                return ((ConfigurableNavigationHandler) parent).getNavigationCases();
            } else {
                return null;
            }
        }
    
    }
    

    Register it as follows in faces-config.xml:

    <application>
        <navigation-handler>com.example.RedirectNavigationHandler</navigation-handler>
    </application>