在其他字段之前将请求值应用于从inputHidden加载id的实体bean

时间:2012-06-28 08:37:55

标签: jsf viewparams omnifaces

我有一个facelet模板:

<f:metadata>
    <o:viewParam name="id" value="#{homeBean.id}" />
</f:metadata>                

<h:form>
    <h:inputHidden value="#{homeBean.id}" />
    <h:inputText value="#{homeBean.user.firstName}" />
    <h:commandButton value="Submit" action="#{homeBean.onSave()}" />
</h:form>

和请求范围的bean:

@Named
@RequestScoped
public class HomeBean {
    private Integer id;
    private User user;

    public void setId(Integer id) {
      System.out.println("setId called");
      user = // code for loading User entity bean with supplied id
    }

    // other accessors for id and user
}

初始页面加载效果很好,实体加载并以表格形式显示,inputHidden设置为实体ID。问题是提交投掷:

javax.el.PropertyNotFoundException - Target unreachable, base expression '. user' resolved to null

可能是因为在setId之前调用了getUser。我怎么解决这个问题?我真的想要一个请求范围的bean,我知道这可以用至少viewaccess scoped bean轻松解决。

编辑:现在我注意到在流程验证阶段抛出异常,我最初认为在更新模型值阶段抛出了异常。我将“私人用户”改为“私人用户=新用户()”,现在没关系,但感觉不太奇怪。

此致 帕维尔

1 个答案:

答案 0 :(得分:1)

OmniFaces <o:viewParam>仅在初始请求中设置请求参数,而不在回发中设置。这是为了与@ViewScoped bean一起使用,这样就不会在每次回发时不必要地验证,转换和更新请求参数(因为它已经存在于视图范围内的bean中)。 API documentationshowcase example也明确提到它应该与视图范围的bean一起使用。

然而,您有一个请求范围的bean,它会在每个请求上进行删除和重新创建,同样也会回发到同一视图。因此,user属性将消失,并在每个后续回发请求中回退到默认null

基本上有两种方法可以解决它:

  1. <o:viewParam>替换为<f:viewParam>。它会在每次请求时调用setter,也会在回发时调用。

  2. @Named @RequestScoped替换为@ManagedBean @ViewScoped,这样只要您与同一视图进行交互,bean就会生效。或者,如果您坚持使用CDI,请改用@Named @ConversationScoped,但您必须自己管理对话的开始和结束。