Search code examples
jsfhttp-redirectjsf-2parametersquery-string

How to redirect to same page with all parameters?


In my app I have JSF page with some parameters

(url of example page: /pages/user.xhtml?id=123&userToShowId=2)

On this page i have a commandButton. After click it I want to redirect to the same page with all parameters. I know, that for this specified page I can do this manually this way:

public String redirect(){
    //extCtx - ExternalContext
    //ctx - FacesContext
    Map<String,String> param = extCtx.getRequestParameterMap();
    String currentURL = ctx.getViewRoot().getViewId();
    return currentURL+"?userToShowId="+param.get("userToShowId")+"&id="+param.get("id");
}

But what to do when I want to get universal way to redirect from any page with any parameters?


If I have view parameters only at pages, without set it as a bean property:

<f:metadata>
    <f:viewParam name="backurl"/>
    <f:viewParam name="id"/>
</f:metadata>

not with value:

<f:metadata>
    <f:viewParam name="backurl" value=#{bean.id}/>
    <f:viewParam name="id" value=#{bean.id}/>
</f:metadata>

can I use includeViewParams=true to do my work?


Solution

  • You can do it without having to bind them to the managed bean. In JSF there are two main navigation cases:

    • Perform a view request without doing nothing more. That's an HTTP GET request and is done using h:button, which doesn't need to be wrapped by a form and acts like a link.
    • Perform a form POST and after that ask for another page (REDIRECT-GET), that's done by h:commandButton.

    You can include view params in both cases. That's how it's done:

    <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:f="http://java.sun.com/jsf/core">
    <h:head />
    <h:body>
        <f:metadata>
            <f:viewParam name="backurl" />
            <f:viewParam name="id" />
        </f:metadata>
        <h:outputText value="backurl value is #{backurl} and id value is #{id}" />
        <br />
        <h:button outcome="index" value="redirect">
            <f:param name="backurl" value="directUrl" />
            <f:param name="id" value="directId" />
        </h:button>
        <h:form>
            <h:commandButton value="action" action="#{bean.redirect}" />
        </h:form>
    </h:body>
    </html>
    
    @ManagedBean
    @RequestScoped
    // You could also use @ViewScoped
    public class Bean implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        /**
         * Performs a redirection to index destination view with the given params
         * 
         * @return
         */
        public String redirect() {
            return "index?backurl=actionUrl&id=actionId&faces-redirect=true";
        }
    }
    

    You'll see when you initially load the page, both backurl and id don't have a value.

    The first button performs a GET request with fixed view parameter values. When view loads again, values are already there. Second button does the same but using an action method.

    Keep in mind that using @RequestScoped or @ViewScoped here has the same effect, as @RequestScoped doesn't maintain the state of the bean and @ViewScoped destroys it each time an String value is returned from the method, which is happening every time we invoke it.