在列表<ui:repeat>或数据数组上使用<h:inputText>、<f:validateWholeBean>和<...>

问题描述 投票:0回答:1

从使用

f:valdiateWholeBean
进行类级别 bean 验证的无处不在的密码示例开始,我尝试通过
<ui:repeat>
<h:inputText>
收集列表或数组中的动态数量的值。为了简单起见,我使用:

class TestData{
  int a;
  int b;
}

作为数据。类型

TestData
的转换器和验证器确实存在。我的 Backingbean 看起来像这样:

class TestController implements Clonable{
  ...
  # just to verify, that class level validation works in general
  String pw1; 
  String pw2;

  # test for scalar values
  TestData x1;

  # test for non-scalar Data
  TestData[] testData;
  ...
  public TestController clone() {
    ...
    clone.testData=new TestData[testData.length];
    for(int i=0;i<clone.testData.length;i++){
      clone.testData[i]=new TestData();
    }
    return clone;
  }
}  

克隆方法按预期被调用,我为数据腾出了空间。对应的Faclet:

<h:form id="testForm">
  <ul>
     <li> 
       <h:inputText id="pw1Input" value="#{testController.pw1}">
         <f:validateBean validationGroups="ValidationGroup"/>
       </h:inputText>
     </li>
     <li>
       <h:inputText id="pw2Input" value="#{testController.pw2}">
         <f:validateBean validationgroups="ValidationGroup"/>
       </h:inputText>
     </li>
     <li>
       <h:inputText value="#{testController.x1}">
         <f:validator validatorId="testDataFacesValidator"/>
         <f:validateBean validationGroups="ValidationGroup"/>
       </h:inputText>
     </li>
     <ui:repeat value="#{testController.testData}" varStatus="status" var="data">
        <li>
          <h:inputText id="valInput_#{status.index}" value="#{testController.testData[status.index]}">
            <f:validator validatorId="testDataFacesValidator"/>
            <f:validateBean validationGroups="ValidationGroup"/>
          </h:inputText>
        </li>
     </ui:repeat>
  </ul>
    
  <h:commandButton value="save" action="#{testController.save}">
    <f:ajax execute="@form" render="globalMsg testForm"/>
  </h:commandButton>
    
  <f:validateWholeBean value='#{testController}' validationGroups="ValidationGroup"/>
</h:form>

当我输入数据时,我可以从日志消息中看到,

TestData
的转换和验证按预期进行。约束验证器是:

public class ConstValidator implements ConstraintValidator<UniqueData, DataHolder> {
  @Override
  public void initialize(UniqueData constraintAnnotation) {
    ConstraintValidator.super.initialize(constraintAnnotation);
    logger.info("[initialize]");
  }

  @Override
  public boolean isValid(DataHolder dataHolder, ConstraintValidatorContext constraintValidatorContext) {
    String pw1=dataHolder.getPw2();
    logger.info("[isValid: pw2: "+pw2+" ]"); // getting the value I entered

    TestData x1=dataHolder.getX1();
    logger.info("[isValid: x1: "+x1+" ]");// getting my value

    TestData[] data=dataHolder.getTestData();
    for(TestData td:data){
        logger.info("[isValid: testData: "+td+" ]");// getting initial, unmodifyed data
    ...
    return true;
  }
} 

最后,我的 Backingbean 获取我输入字符串的所有值、标量测试数据以及数组中的所有修改值。

[文档][2] 说:...如果 bean 实现 Cloneable,则克隆 bean ...用候选值填充复制的 bean....

我问自己:数组的这种“填充”是如何发生的。我修改了 Backingbean 中

TestData[]
的 getter/setter 以获得深层副本,但这让情况变得更糟。

jsf
1个回答
0
投票

我从这个答案了解到,嵌套属性不能以这种方式验证。答案也给出了一个很好的替代解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.