我有一个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轻松解决。
编辑:现在我注意到在流程验证阶段抛出异常,我最初认为在更新模型值阶段抛出了异常。我将“私人用户”改为“私人用户=新用户()”,现在没关系,但感觉不太奇怪。
此致 帕维尔
答案 0 :(得分:1)
OmniFaces <o:viewParam>
仅在初始请求中设置请求参数,而不在回发中设置。这是为了与@ViewScoped
bean一起使用,这样就不会在每次回发时不必要地验证,转换和更新请求参数(因为它已经存在于视图范围内的bean中)。 API documentation和showcase example也明确提到它应该与视图范围的bean一起使用。
然而,您有一个请求范围的bean,它会在每个请求上进行删除和重新创建,同样也会回发到同一视图。因此,user
属性将消失,并在每个后续回发请求中回退到默认null
。
基本上有两种方法可以解决它:
将<o:viewParam>
替换为<f:viewParam>
。它会在每次请求时调用setter,也会在回发时调用。
将@Named @RequestScoped
替换为@ManagedBean @ViewScoped
,这样只要您与同一视图进行交互,bean就会生效。或者,如果您坚持使用CDI,请改用@Named @ConversationScoped
,但您必须自己管理对话的开始和结束。