Как выполнять навигацию в режиме прослушивания preRenderView

Я начинаю с Что может < f: metadata > , < f: viewParam > и < f: viewAction > для использования?

У меня есть прослушиватель событий представления предварительной рендеринга:

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

который вызывает следующий метод:

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;
    }
}

и следующее правило навигации:

<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>

Однако он не выполняет навигацию. Он работает, когда я использую командную кнопку следующим образом:

<p:commandButton ... action="#{loginBean.performWeakLogin()}"  /> 

Ответ 1

Навигация на основе возвращаемого значения метода выполняется только компонентами, реализующими интерфейс ActionSource2 и предоставляющий атрибут, принимающий MethodExpression для что, например, атрибут action компонента UICommand, который ставится в очередь во время фазы запроса запроса и вызывается во время фазы Application Invoke.

<f:event listener> - это просто метод system system event, а не метод действия. Вам необходимо выполнить навигацию вручную следующим образом:

public void performWeakLogin() {
    // ...

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

В качестве альтернативы вы также можете отправить перенаправление по заданному URL-адресу, что более полезно для случая, когда вы не хотите перемещаться внутри, но внешне:

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

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

Несвязанный для конкретной проблемы, сервлет-фильтр - лучшее место для выполнения авторизации и аутентификации на основе запроса.

См. также:

Ответ 2

Я использую JBoss 7 с JSF 2.1. Решение от BalusC перенаправлялось на страницу ошибок по умолчанию JBoss, хотя я уже установил страницу ошибок по умолчанию в файле web.xml

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

Чтобы перенаправить на мою собственную страницу ошибки, я использовал ответ для отправки ошибки:

FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse)facesContext.getExternalContext().getResponse();
try {
    response.sendError(404);
} catch (IOException ioe) {
    ioe.printStackTrace();
}
facesContext.responseComplete();