【问题标题】:FacesMessage added from a ViewScoped bean not rendered从未呈现的 ViewScoped bean 添加的 FacesMessage
【发布时间】:2012-12-20 16:33:18
【问题描述】:

我有一个 ViewScoped bean,方法如下:

public Item getItem()  
{
     try {
          itemID = Integer.parseInt(
             FacesContext.getCurrentInstance().getExternalContext()
                         .getRequestParameterMap().get("itemID"));  
     } catch(NumberFormatException ex) {
          FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(
                       FacesMessage.SEVERITY_ERROR, "Item lookup error", null));
          return null;  
     }  
     return itemsDAO.findByID(itemID);
}

该方法采用 ViewID 参数并使用 itemsDAO 查找对象。如果 itemID 不是整数,我想通过捕获 NumberFormatException 并在其中添加消息来显示 FacesMessage。然而,这不起作用。上面代码 sn-p 中的FacesMessage 不会在下面的视图标签h:messages globalOnly="true" infoClass="info" errorClass="error" 内渲染

我怀疑在调用该方法时 FacesContext 不可用,但我不知道如何处理此异常。

更新 1:

关于使用 viewParam 来利用内置转换和验证的建议。我不知道在这种情况下这将如何工作。 itemID 是从“索引”视图传递的,其中列出了所有项目,如下所示。每个项目标题都是指向 viewItem 页面的链接,其中 itemID 通过 URL 传递。在这种情况下,鉴于索引视图有很多项目,我如何使用 viewParam 将 itemID 传递给 viewItem 视图?

index.xhtml

<code>
 <ui:repeat var="item" value="#{ItemViewBean.items}">
       <div id="item">
        <h:link value="#{item.title}" outcome="viewItem">
        <f:param name="itemID" value="#{item.id}"></f:param>
        </h:link>
        <p><h:outputText value="#{item.description}"></h:outputText> <br />
        Address: <h:outputText value="#{item.address}"></h:outputText></p>
        <span class="itemFooter">
        Submitted By: <h:outputText value="#{item.user.username}"></h:outputText> On
        <h:outputText value="#{item.postDate}"></h:outputText>
        </span>
       <hr />
       </div>
       </ui:repeat>
</code>

更新 2: 我想出了一个解决这个问题的方法。如果发生异常,我将错误 FacesMessage 放在 Flash 对象中并重定向到某个错误页面。我仍然不明白为什么不能简单地将 FacesMessage 添加到 FacesContext 并显示在视图上。

【问题讨论】:

  • 你怎么知道这完全行不通?您确定正在调用 addMessage 方法吗?你有错误吗?您是否在执行 AJAX 请求(如果是,则必须更新 h:messages)?
  • @elias 我知道它不起作用,因为 h:messages 标签是空的,如果我故意通过将 itemID 设置为字符串来在它需要一个整数时导致异常。

标签: jsf jakarta-ee jsf-2


【解决方案1】:

鉴于您正在遍历 ExternalContext#getRequestParameterMap(),您似乎正在拦截 GET 请求。鉴于它发生在 getter 方法 (bad!!) 中,它似乎仅在要呈现引用 item 属性的组件时执行。

因此,假设上述假设成立,那么当&lt;h:messages&gt; 组件在引用item 属性的组件之前 在视图中声明时,就会出现此问题。然后将新消息添加到面孔上下文中为时已晚。 &lt;h:messages&gt; 就在那个时候,即已经渲染了。

我至少想不出与此特定问题症状相匹配的其他合理原因。这个问题基本上有两种解决方案:

  1. &lt;h:messages&gt; 移动到之后引用item 属性的组件,以便在添加面孔消息之后呈现它。

  2. 在预渲染视图事件期间通过&lt;f:event&gt; 执行业务作业,最好结合&lt;f:viewParam&gt; 将请求参数设置为bean 属性。您甚至可以单独使用 &lt;f:viewParam&gt; 和转换器,因为您的不良 getter 方法的唯一工作就是转换值。

不用说选项 2 是首选,因为您目前基本上在滥用/解决一些基本的 JSF 概念。其中业务逻辑不属于 getter。

例如

<f:metadata>
    <f:viewParam id="itemID" name="itemID" value="#{bean.item}"
        required="true" requiredMessage="Invalid page access. Please use a link from within the system."
        converter="itemConverter" converterMessage="Unknown item ID."
    />
</f:metadata>
<h:message for="itemID" />

private Item item; // +getter +setter

itemConverter 只是一个Converter 实现,其中请求参数在getAsObject() 方法中转换为Item 实例。

另见:

【讨论】:

  • 感谢您的详尽回答。选项 1 不起作用,因为我需要将消息显示在页面顶部,它不能位于我设计中的组件下方。对于选项 2,请参阅我的更新 1 帖子编辑以了解这对我来说是个问题
  • 根据您的更新 1:将元数据/视图参数放在与结果 viewItem 关联的页面中。另请参阅“另请参阅”链接以获取更详细的示例。根据您的更新 2:flash 有效,因为在呈现 &lt;h:messages&gt; 之前添加了消息。不使用 flash 会失败,因为在呈现&lt;h:messages&gt; 之后添加了消息。正如我在回答中试图解释的那样。
  • 感谢 BalusC 解决这个问题。我对 viewParam 标签有一个巨大的误解。这对我有用。感谢您的支持以及您对 JSF 标签的所有精彩回答。
猜你喜欢
  • 2018-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
  • 2014-03-29
  • 1970-01-01
相关资源
最近更新 更多