1

我有一个 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

可能是因为 getUser 在 setId 之前被调用。我该如何解决这个问题?我真的很想拥有一个请求范围的 bean,我知道这可以通过至少 viewaccess 范围的 bean 轻松解决。

编辑:现在我注意到在流程验证阶段引发了异常,我最初认为在更新模型值阶段引发了异常。我将“private User”改为“private User user = new User()”,现在可以了,但感觉有点奇怪。

问候, 帕维尔

4

1 回答 1

1

OmniFaces<o:viewParam>仅在初始请求中而不在回发中设置请求参数。这旨在与@ViewScopedbean 一起使用,以便在每次回发时不会不必要地验证、转换和更新请求参数(因为它仍然存在于视图范围的 bean 中)。API 文档展示示例还明确提到它应该与视图范围的 bean 一起使用。

但是,您有一个请求范围的 bean,它在每个请求上被丢弃并重新创建,也在回发到同一视图时。因此,该user属性消失并null在每个后续回发请求中恢复为默认值。

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

  1. 替换<o:viewParam><f:viewParam>。它将在每个请求上调用 setter,在回发时也是如此。

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

于 2012-06-28T12:52:22.017 回答