【问题标题】:How can I add FacesMessage during page load? Using @PostConstruct does not seem to work如何在页面加载期间添加 FacesMessage?使用 @PostConstruct 似乎不起作用
【发布时间】:2012-04-29 03:35:21
【问题描述】:

在支持 bean 的 @PostConstruct 方法中,我调用了一个 EJB,它可能会返回一些我想通过 p:messages 显示在页面上的消息。但是,即使我添加 FacesMessages 例如FacesContext.getCurrentInstance().addMessage(...), p:messages 没有被 FacesMessages 更新。

如果我改为对来自页面的操作调用 EJB(例如,用户单击页面上的按钮,该按钮调用调用 EJB 的方法,然后添加 FacesMessage(s)),则消息显示按预期使用 p:messages 。

如何在 @PostConstruct 期间添加 Faces 消息并在页面初始呈现时显示它们?

代码:

Page1Controller.java:

@ManagedBean
public class Page1Controller
{
    @PostConstruct
    public void init()
    {
        FacesContext.getCurrentInstance().addMessage(null, 
            new FacesMessage("Test Message from @PostConstruct"));
    }

    public String getValue()
    {
            return "Some Value";
    }

    public void triggerMessage(ActionEvent event)
    {
            FacesContext.getCurrentInstance().addMessage(null, 
                    new FacesMessage("Test Message from Trigger Button"));      
    }

}

page1.xhtml

   <h:form>
        <p:messages showDetail="true" showSummary="true" autoUpdate="true"/>
        <h:outputText value="#{page1Controller.value}"/>
        <br/>
        <p:commandButton value="Trigger Message" 
                         actionListener="#{page1Controller.triggerMessage}"/>  
   </h:form>

【问题讨论】:

  • 注意——如果使用 f:event type="preRenderView" 侦听器指令调用相同的方法(调用 EJB 等),则 FacesMessage 会适当更新。我应该这样做吗?
  • 使用 Mojarra 2.1.7、Primefaces 3.2(最新稳定版)。

标签: jsf message pageload postconstruct


【解决方案1】:

这可能发生在消息组件被渲染之前消息被添加。

在您的具体示例中,&lt;h:outputText&gt; 组件第一次引用了 bean,因此当时第一次构造。但是&lt;h:outputText&gt; 组件出现在您的具体示例中 &lt;p:messages&gt; 组件之后,因此&lt;p:messages&gt; 组件已经呈现,因此显示消息为时已晚。

您需要确保以某种方式添加消息消息组件呈现之前。一种方法是使用&lt;f:viewAction&gt;。它在INVOKE_APPLICATION 阶段运行,该阶段在RENDER_RESPONSE 阶段之前。因此它在 any 组件被渲染之前运行。因此,这是一个绝佳的机会。

<f:metadata>
    <f:viewAction action="#{bean.onload}" />
</f:metadata>

public void onload() {
    // Add message here instead of in @PostConstruct.
}

另见:

【讨论】:

  • Thanks... 是在 @PostConstruct 方法中的替代方法,在我添加 FacesMessage 之后,我然后访问消息组件(通过 ViewRoot.findComponent)并告诉消息组件“重新渲染“本身? (这可能吗?)如果可能,这是否比 preRenderView 或在 p:messages 上方移动输出文本更好?
  • 不,这是不可能的。至于正确的方法,这取决于具体的功能要求。究竟什么情况下需要添加人脸消息?当某些请求参数无效时?如果是这样,您应该为此使用&lt;f:viewParam&gt;。如果没有,那么 &lt;f:event type="preRenderView"&gt; 就可以了(当您以后有机会升级到 JSF 2.2 时,最好用更理智的 &lt;f:viewAction&gt; 代替)。
  • 现在,这对 JSF 来说真是令人沮丧...在屏幕上显示消息应该不难。
  • 我不明白这一点:“ 是在第一次构造托管 bean 之前呈现的。现在添加消息为时已晚。”为什么为时已晚?请注意,我只是好奇,没有任何问题。
  • @CED: Plain java 'example': 假设您有一个包含 5 个元素的数组并对其进行迭代,并对每个元素执行 System.out.println(渲染它),然后添加一个额外的元素。那将不会显示。这不是一个 8 岁评论所暗示的 JSF 特定问题。带有 EL 的普通 JSP 和使用的任何 js UI 框架都有同样的问题。
【解决方案2】:

您可以收集错误,然后在加载页面结束时使用具有 autorun = true 模式的 primefaces 的 remoteCommand 显示它。 就我而言,我有一个 viewScope,在 xhtml 中我显示了在 @PostConstruct 中加载的值列表。如果生成异常,我将在页面加载结束时使用 remoteCommand 将其保存到示例中。

private ArrayList<Exception> postConstucError = new ArrayList<>();

@PostConstruct
public void validarAcceso() {
    /**
     * verificar permisos a la vista de coeficientes
     */
    try {
            this.init() //load data;
        } catch (Exception e) {
        System.out.print(e.getMessage());
        this.postConstucError.add(e);
    }
}

 public void showPostConstructError() {
    try {
        for (int i = 0; i < this.postConstucError.size(); i++) {
            JsfUtil.addErrorMessage("Error al cargar datos iniciales: " + postConstucError.get(i).getMessage());
        }
    } catch (Exception e) {
        JsfUtil.addErrorMessage(e, "Error: showPostConstructError() " + e.getMessage());
    }
}

xhtml代码

  <p:messages id="messages" showDetail="true" autoUpdate="true" closable="true"/> 
  <h:form>
        <p:remoteCommand id="rcomerror" name="showError" process="@this"  autoRun="true"
                         actionListener="#{mBPresentNinos.showPostConstructError()}" />  
    </h:form>

【讨论】:

  • 创意解决方案...您的showPostConstructError() 方法看起来如何?
【解决方案3】:

对我来说,使用 preRenderView 事件在表单初始化上显示消息是一个消息地狱。所以我创建了非常简单的“组件”来保存静态消息。对于此示例,仅支持一条错误消息。

staticMessage.xhtml:

<ui:fragment xmlns="http://www.w3.org/1999/xhtml"
             xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
             rendered="#{rendered}">
    <div id="staticMessage" class="ui-messages ui-widget" aria-live="polite">
        <div class="ui-messages-error ui-corner-all"><span class="ui-messages-error-icon"/>
            <ul>
                <li>
                    <span class="ui-messages-error-summary">#{value}</span>
                </li>
            </ul>
        </div>
    </div>
</ui:fragment>

包括消息:

 <ui:include src="/template/components/staticMessage.xhtml">
     <ui:param name="rendered"value="#{beanMB.staticMessagesRendered}"/>
     <ui:param name="value" value="Place your message here."/>
 </ui:include>

【讨论】:

    猜你喜欢
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多