FacesMessage从未呈现的ViewScoped bean添加

时间:2013-01-06 22:44:41

标签: jsf java-ee jsf-2

我有一个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。然而,这不起作用。上述代码段中的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并显示在视图上。

1 个答案:

答案 0 :(得分:3)

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

因此,假设上述假设为真,那么在引用<h:messages>属性的组件之前在视图中声明item组件时,就会出现此问题。 。然后,在面部上下文中添加新消息为时已晚。 <h:messages>就在那时,已经呈现。

我至少可以不考虑与此特定问题症状相匹配的其他合理原因。该问题基本上有两种解决方案:

  1. 引用<h:messages>属性的组件之后将item移动到,以便在 faces消息之后呈现已被添加。

  2. <f:event>的预渲染视图事件期间执行业务作业,最好与<f:viewParam>结合使用,将请求参数设置为bean属性。你甚至可以单独使用<f:viewParam>与转换器结合使用,因为你的糟糕的getter方法的唯一工作就是转换价值。

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

    E.g。

    <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实施,其中请求参数转换为Item方法中的getAsObject()实例。

    另见: