无法将JSF ViewScoped bean作为ManagedProperty注入Validator

Joh*_*shy 11 java jsf-2

我试图将JSF ViewScoped bean作为ManagedProperty注入到RequestScoped bean中,该bean实现了javax.faces.validator.Validator.但是总是会注入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

}
Run Code Online (Sandbox Code Playgroud)

验证器

@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;
}
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

正如在代码中提到的,即使在调用ajax动作几次之后,当记录bean.getCount()时总是显示一个.

但是,如果我将ViewScoped更改为SessionScoped,则相同的方案也适用.此外,如果我删除RequestScoped bean的Validator实现并在PostConstruct中使用记录器,则计数会按预期为每个ajax请求递增.

难道我做错了什么?或者它应该如何工作?提前致谢

Bal*_*usC 14

这是因为在视图构建期间评估binding属性<f:validator>.在那一刻,视图范围还不可用(它有意义,它仍然在忙于构建......),因此将创建一个全新的视图范围bean,它具有与请求范围bean相同的效果.在即将到来的JSF 2.2中,这个鸡蛋问题将得到解决.

在那之前,如果你非常肯定你需要在validate()方法中使用视图范围的bean (我宁愿寻找其他方法,比如<f:attribute>EJB,多字段验证器等),那么唯一的方法就是以#{bean}编程方式在里面进行评估validate()方法本身而不是让它注入@ManagedProperty.

你可以使用Application#evaluateExpressionGet()这个:

Bean bean = context.getApplication().evaluateExpressionGet(context, "#{bean}", Bean.class);
Run Code Online (Sandbox Code Playgroud)

也可以看看: