URL redirection not working on preRenderView event

2.5k Views Asked by At

I finally got messages passed between pages, but this is not redirecting me to the user login page (../../index.xhtml) instead it shows the forbidden page :

public String permission() throws IOException {
    FacesContext context = FacesContext.getCurrentInstance();
    Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
    String isLog = (String) sessionMap.get("isLogged");

    if(isLog != "TRUE") {

        System.out.println("*** The user has no permission to visit this page. *** ");
        context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Info : ", "Loggez-vous"));
        context.getExternalContext().getFlash().setKeepMessages(true);
        //context.getExternalContext().redirect("../../index.xhtml");
        return "../../index.xhtml?faces-redirect=true";


    } else {
        System.out.println("*** The session is still active. User is logged in. *** ");
    }
    return "../../index.xhtml?faces-redirect=true";
}

Of course, restriced page has this :

<f:event type="preRenderView" listener="#{userloginMB.permission()}"/>

Redirection using get external context will make the messages lost.

2

There are 2 best solutions below

3
On BEST ANSWER

Ignoring the general design problem (look here for a starting point), it seems that you mixed up the new JSF 2.2 <f:viewAction> and the old JSF 2.0/2.1 <f:event type="preRenderView"> trick.

Returning a navigation outcome as String on a GET request is only supported in <f:viewAction>, not in <f:event type="preRenderView">. For the latter you need ExternalContext#redirect() which you happened to have outcommented.

So, you should do either

<f:event type="preRenderView" listener="#{bean.onload}"/>
public void onload() throws IOException {
    // ...
    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.redirect(ec.getRequestContextPath() + "/index.xhtml");
}

or

<f:metadata>
    <f:viewAction action="#{bean.onload}"/>
</f:metadata>
public String onload() {
    // ...
    return "/index.xhtml"; // Note: no need for faces-redirect=true!
}

and not mix up them.

Note that I wrote the code in such way that you can always use an /path relative to the web root without the need to fiddle with ../ nonsense.

See also:

4
On

You need to specify absolute path from the root context when using faces-redirect=true.

so your outcome string should look like:

return "/dir1/dir2/index.xhtml?faces-redirect=true";

if index.xhtml resides in (context root) i.e. Web Content/index.xhtml then use this outcome string:

return "/index.xhtml?faces-redirect=true";

if index.xhtml resides in Web Content/pages/dir2/index.xhtml then use this outcome string:

return "/pages/dir2/index.xhtml?faces-redirect=true";