6

I'm starting from What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?

I have a pre render view event listener:

<f:metadata>
    <f:event type="preRenderView" listener="#{loginBean.performWeakLogin()}" />
</f:metadata>

which invokes the following method:

public String performWeakLogin() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    String parameter_value = (String) facesContext.getExternalContext().getRequestParameterMap().get("txtName");

    if (parameter_value != null && parameter_value.equalsIgnoreCase("pippo")) {
        try {
            return "mainPortal";
        } catch (IOException ex) {
            return null;
        }
    } else {
        return null;
    }
}

and the following navigation rule:

<navigation-rule>
    <from-view-id>/stdPortal/index.xhtml</from-view-id>
    <navigation-case>
        <from-outcome>mainPortal</from-outcome>
        <to-view-id>/stdPortal/stdPages/mainPortal.xhtml</to-view-id>
        <redirect/>
    </navigation-case>
</navigation-rule>

However, it doesn't perform the navigation. It works when I use a command button as follows:

<p:commandButton ... action="#{loginBean.performWeakLogin()}"  /> 
Community
  • 1
  • 1
user1594895
  • 587
  • 1
  • 10
  • 31
  • Note that I edited and changed the incorrectly used term "implicit navigation" to "navigation" throughout your question. With implicit navigation is meant that there's no `` been used. E.g. just returning the `to-view-id` directly as outcome as in `return "/stdPortal/stdPages/mainPortal.xhtml";` or `handleNavigation(fc, null, "/stdPortal/stdPages/mainPortal.xhtml")`. – BalusC Apr 19 '13 at 14:18
  • @BalusC Thanks I thought the opposite! My fault! – user1594895 Apr 19 '13 at 14:25

2 Answers2

10

Navigation based on a method's return value is only performed by components implementing ActionSource2 interface and providing an attribute taking a MethodExpression for that, such as action attribute of UICommand components, which is queued during Apply Request Values phase and invoked during Invoke Application phase.

The <f:event listener> is merely a component system event listener method, not an action method. You need to perform the navigation manually as follows:

public void performWeakLogin() {
    // ...

    FacesContext fc = FacesContext.getCurrentInstance();
    fc.getApplication().getNavigationHandler().handleNavigation(fc, null, "mainPortal");
}

Alternatively, you can also send a redirect on a given URL, which is more useful for the case you don't want to navigate internally, but externally:

public void performWeakLogin() throws IOException {
    // ...

    ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
    ec.redirect(ec.getRequestContextPath() + "/stdPortal/stdPages/mainPortal.xhtml");
}

Unrelated to the concrete problem, a servlet filter is a better place for the job of performing request based authorization/authentication.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • thanks as the usual. My problem starte d with http://stackoverflow.com/questions/16103844/jsf-read-post-param-and-skip-login. Where i have to manage a lot of situation so i think that the use of backingbean is enough to check user, but i go to investigate with servlet filter. – user1594895 Apr 19 '13 at 14:14
1

I use JBoss 7 with JSF 2.1. The solution from BalusC was redirecting to the JBoss default error page, even though I had already set the default error page in the web.xml‎‎

<error-page>
    <error-code>404</error-code>
    <location>/myapp/404.xhtml</location>
</error-page>

To redirect to my own error page, I used the response to send the error:

FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse)facesContext.getExternalContext().getResponse();
try {
    response.sendError(404);
} catch (IOException ioe) {
    ioe.printStackTrace();
}
facesContext.responseComplete();
Andreas Panagiotidis
  • 2,763
  • 35
  • 32