在提交后重新启用在JSF中禁用的Bean验证

时间:2013-12-12 13:43:54

标签: hibernate jpa jsf-2 bean-validation

给定:JSF2 Form包含一些输入字段,包括密码字段。

主要目标:如果密码字段为空(导致password.isEmpty()==truepassword==null),则应跳过验证和密码绑定!

No-Go:单独的DTO(我知道它会更干净,但我不允许这样决定)

view.xhtml:

<h:form id="someForm">
    <h:outputLabel value="Password " />
    <h:inputSecret id="password" value="#{myBackingBean.entity.password}" immediate="true" redisplay="false" required="false">
        <f:validateBean disabled="true"/>
        <f:validator validatorId="myPasswordValidator"/>
    </h:inputSecret>
    <p:message for="password" />
    <p:commandButton value="Save" update="someForm">
        <f:actionListener binding="#{myBackingBean.updateEntityAction()}" />
    </p:commandButton>
</h:form>

MyPasswordValidator.java:

@FacesValidator(value = "myPasswordValidator")
public class MyPasswordValidator implements Validator {
@Override
public void validate(FacesContext context, UIComponent component,
    Object value) throws ValidatorException {
            String password = (String) value;
if (password == null || password.isEmpty()) {
    UIInput inputComponent = ((UIInput) component);
        inputComponent.setValid(true);
        inputComponent.setRequired(false);
}
return;
    }
}

MyBackingBean.java:

@ManagedBean(name = "myBackingBean")
@ViewScoped
public class MyBackingBean extends GenericBackingBean<....> {

    public ActionListener updateEntityAction(){
    return new ActionListener() {
      @Override
      public void processAction(ActionEvent event)
          throws AbortProcessingException {
          // .... hybernate stuff
        }
      };
  }
}

Entity.java:

  class Entity{

  @NotNull
  private String password;
  // ...
  public void setPassword(String password)  {
        // do nothing if null
        if(password == null || password.isEmpty()){

              log.warn("Password not changed for some reason ....");
          return;
        }
        // set and crypt password ...
  }

这实际上有效,但仅适用于第一次提交,每次提交后第一次产生错误消息(没有例外......可能它会被某处吃掉......?)。有趣的是,消息中写着“kann nicht null sein'”(德语),我实际上并不知道是谁或者是什么产生了这个消息。

我的结论是,在第一次提交后,再次激活默认bean验证。

任何想法?

3 个答案:

答案 0 :(得分:2)

此消息来自JSR303 bean验证注释@NotNull。默认情况下,JSR303 bean验证在JPA EntityManager#persist()update()期间执行

就像您可以通过<f:validateBean disabled="true">在JSF中禁用JSR303 bean验证一样,您可以通过persistence.xml中的以下条目禁用JPA中的JSR303 bean验证:

<validation-mode>none</validation-mode>

请注意,这会影响所有 JSR303 bean验证注释。您可能希望删除@NotNull并使用条件required="true"

另见:

答案 1 :(得分:1)

消息“darf nicht null sein”来自ValidationMessages_de.properties,您在JAR hibernate-validator-<version>.jar/org/hibernate/validator中找到了一个消息。

所以你似乎是正确的,验证者反击的地方。通过JSF呈现此消息时,某些消息包保存

javax.faces.validator.BeanValidator.MESSAGE = {1} {0}

这样的消息就像:“密码”darf nicht null sein。在您的项目中,这已经改变了(在消息属性中查找键)或者可能从其他地方开始验证(Hibernate持久存在?)。

答案 2 :(得分:1)

找到了解决此问题的非黑客解决方案!

而不是写作:

<h:inputSecret id="password" value="#{myBackingBean.entity.password}" immediate="true" redisplay="false" required="false">
    <f:validateBean disabled="true"/>
    <f:validator validatorId="myPasswordValidator"/>
</h:inputSecret>

我不得不写:

<f:validateBean disabled="true">
<h:inputSecret id="password" value="#{myBackingBean.entity.password}" immediate="true" redisplay="false" required="false">
    <f:validator validatorId="myPasswordValidator"/>
</h:inputSecret>
</f:validateBean>

第一个变体在请求后无法生存!

非常感谢您的提示和问候!

相关问题