Given: JSF2 Form with some input fields, including password field.

Main Goal: If the password field is left empty (resulting in password.isEmpty()==true or password==null), the validation and password binding should be skipped!

No-Go: Separate DTO (i know it would be more clean, but i am not allowed to decide this)

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 ...
  }

This actually works, but only for the first submit, each submit after the first results in a error message (no exception ... probably it gets eaten somewhere ... ?). What is interesting, is that the message says "kann nicht null sein'" (german), and i have actually no clue who or what is producing this message.

What i conclude, is that after the first submit the default bean validation is activated again.

Any Idea?

有帮助吗?

解决方案 3

Found a non-hack solution to this problem!

Instead of writing:

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

I had to write:

<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>

The First variant does not survive post-requests!

Thanks anyway for the hints and regards!

其他提示

This message is coming from JSR303 bean validation annotation @NotNull. JSR303 bean validation is by default also executed during JPA EntityManager#persist() and update().

Like as that you can disable JSR303 bean validation in JSF by <f:validateBean disabled="true">, you can disable JSR303 bean validation in JPA by the following entry in persistence.xml:

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

Keep in mind that this affects all JSR303 bean validation annotations. You might want to remove the @NotNull and make use of a conditional required="true".

See also:

The message "darf nicht null sein" comes from ValidationMessages_de.properties, you find that one within the JAR hibernate-validator-<version>.jar/org/hibernate/validator.

So you seem right, somewhere the validator strikes back. When rendering this messages via JSF, some message bundle holds

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

so that the message is like: "password" darf nicht null sein. Either in your project this got changed (look for the key in your message properties) or the validation is possibly started from somewhere else (Hibernate persisting?).

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top