从preRender导航后无法保留面部消息

时间:2012-10-30 17:36:14

标签: jsf jsf-2

在我的preRender代码页面中我添加了face消息,然后导航到另一个页面,如下所示:

if(error){
addMessageToComponent(null,"AN ERROR HAS OCCURRED");
FacesContext.getCurrentInstance().getExternalContext().getFlash()
                .setKeepMessages(true);
navigateActionListener("myoutcome");
}

和添加消息和导航的util方法是:

public static String getClientId(String componentId)
    {
        FacesContext context = FacesContext.getCurrentInstance();
        UIViewRoot root = context.getViewRoot();

        UIComponent c = findComponent(root, componentId);
        return c.getClientId(context);
    }

    public static UIComponent findComponent(UIComponent c, String id)
    {
        if (id.equals(c.getId())) { return c; }
        Iterator<UIComponent> kids = c.getFacetsAndChildren();
        while (kids.hasNext())
        {
            UIComponent found = findComponent(kids.next(), id);
            if (found != null) { return found; }
        }
        return null;
    }

    /**
     * @param componentId
     *            : the id for the jsf/primefaces component without formId:
     *            prefix. <br>
     *            if you use null then the message will be added to the
     *            h:messages component.
     **/
    public static void addMessageToComponent(String componentId, String message)
    {

        if (componentId != null)
            componentId = GeneralUtils.getClientId(componentId);
        FacesContext.getCurrentInstance().addMessage(componentId,
                new FacesMessage(message));
    }

public static void navigateActionListener(String outcome)
    {
        FacesContext context = FacesContext.getCurrentInstance();
        NavigationHandler navigator = context.getApplication()
                .getNavigationHandler();
        navigator.handleNavigation(context, null, outcome);
    }

但邮件未保存,因此重定向后不会显示。

请告知如何解决这个问题。

1 个答案:

答案 0 :(得分:4)

preRenderView事件在RENDER_RESPONSE阶段的最开始运行。 太晚指示Flash范围保留消息。您最迟可以在INVOKE_APPLICATION阶段执行此操作。

由于没有标准的JSF组件系统事件,你需要自制一个:

@NamedEvent(shortName="postInvokeAction")
public class PostInvokeActionEvent extends ComponentSystemEvent {

    public PostInvokeActionEvent(UIComponent component) {
        super(component);
    }

}

要发布此内容,您需要PhaseListener

public class PostInvokeActionListener implements PhaseListener {

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.INVOKE_APPLICATION;
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        // NOOP.
    }

    @Override
    public void afterPhase(PhaseEvent event) {
        FacesContext context = FacesContext.getCurrentInstance();
        context.getApplication().publishEvent(context, PostInvokeActionEvent.class, context.getViewRoot());
    }

}

faces-config.xml

中注册后如下
<lifecycle>
    <phase-listener>com.example.PostInvokeActionListener</phase-listener>
</lifecycle>

您将能够按如下方式使用新活动:

<f:event type="postInvokeAction" listener="#{bean.init}" />

你只需要确保你至少有一个<f:viewParam>,否则JSF根本不会进入被调用的阶段。

JSF实用程序库OmniFaces已经支持此事件和preInvokeAction事件。另请参阅the showcase page,其中还演示了为重定向设置facesmessage。