无法将 JSF ViewScoped bean 作为 ManagedProperty 注入 Validator
Posted
技术标签:
【中文标题】无法将 JSF ViewScoped bean 作为 ManagedProperty 注入 Validator【英文标题】:Unable to inject JSF ViewScoped bean into Validator as ManagedProperty 【发布时间】:2012-11-14 23:10:48 【问题描述】:我正在尝试将 JSF ViewScoped bean 作为 ManagedProperty 注入到实现 javax.faces.validator.Validator 的 RequestScoped bean 中。但总是会注入 ViewScoped bean 的新副本。
ViewScoped Bean
@ViewScoped
@ManagedBean
public class Bean
private Integer count = 1;
private String field2;
public String action()
++count;
return null;
public String anotherAction()
return null;
//getter and setter
验证器
@RequestScoped
@ManagedBean
public class SomeValidator implements Validator
public void validate(FacesContext context, UIComponent comp, Object value)
throws ValidatorException
//logging bean.getCount() is always one here. Even after calling ajax action a few times
@ManagedProperty(value = "#bean")
private Bean bean;
xhtml 页面
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
</h:head>
<h:body>
<h:form>
<h:panelGroup layout="block" id="panel1">
<h:commandButton type="submit" value="Action" action="#bean.action">
<f:ajax render="panel1"></f:ajax>
</h:commandButton>
<h:outputText value="#bean.count"></h:outputText>
</h:panelGroup>
<h:panelGroup layout="block" id="panel2">
<h:inputText type="text" value="#bean.field1">
<f:validator binding="#someValidator" />
</h:inputText>
</h:panelGroup>
<h:commandButton type="submit" value="Another Action" action="#bean.anotherAction">
<f:ajax execute="panel2" render="panel2"></f:ajax>
</h:commandButton>
</h:form>
</h:body>
</html>
正如代码中提到的,即使调用了几次 ajax 操作,当记录 bean.getCount() 时总是显示一个。
但是,如果我将 ViewScoped 更改为 SessionScoped,同样的情况也适用。此外,如果我删除 RequestScoped bean 的 Validator 实现并在 PostConstruct 中使用记录器,则每个 ajax 请求的计数都会按预期增加。
我做错了吗?或者这应该如何工作?提前致谢
【问题讨论】:
【参考方案1】:这是因为<f:validator>
的binding
属性是在视图构建时评估的。在那一刻,视图范围还不可用(这是有道理的,它仍在忙于构建......),因此将创建一个全新的视图范围 bean,它与请求范围 bean 具有相同的效果。在即将到来的 JSF 2.2 中,这个先有鸡还是先有蛋的问题将得到解决。
在此之前,如果您绝对肯定需要在 validate()
方法中使用视图范围的 bean(我宁愿寻找其他方法,例如 <f:attribute>
、EJB、多字段验证器等),那么唯一的方法就是在validate()
方法本身内部以编程方式评估#bean
,而不是通过@ManagedProperty
注入它。
您可以为此使用Application#evaluateExpressionGet()
:
Bean bean = context.getApplication().evaluateExpressionGet(context, "#bean", Bean.class);
另见:
JSTL in JSF2 Facelets... makes sense? - 更好地理解“查看构建时间”与“查看渲染时间”。【讨论】:
我已阅读链接的答案至少十次。但是忘记点赞了。今天不行。 ;) 谢谢。以上是关于无法将 JSF ViewScoped bean 作为 ManagedProperty 注入 Validator的主要内容,如果未能解决你的问题,请参考以下文章
在 JSF 中如何以及何时销毁 @ViewScoped bean?
JSF 2.x @ViewScoped 托管 bean 线程安全吗?
JSF ViewScoped bean 在所有 ajax 请求中的唯一 ID?