1

I am new to JSF and going through one JSF application.

I want to validate one Password field for Blank string.

I know instead of doing it in Javascript, I am calling a function for validation.

My need is, if value of the password field is blank then it is validated from validator function till now it is going correctly but after validation when it come =s to UI bav=ck at that time password field should be empty.

If password field is empty(contains spaces only) then i want it to set it as blank or else keep data as it is.

My try till now, JSF view page singin.xhtml

                    <h:outputText styleClass="outputBox" style="margin: 3px;"
                        value="Password" />
                    <h:inputSecret id="password" required="true" 
                        requiredMessage="Please enter your password"
                        value="#{userActionManager.dto.password}" 
                        validator="#{userActionManager.validateSamePassword}">

                            <a4j:ajax event="change" execute="@this" bypassUpdates="true" />
                    </h:inputSecret>

Validator method.

    public void validateSamePassword(FacesContext fc, UIComponent component, Object obj) {
         System.out.println("UserActionManager.validateSamePassword()");

         String confirmPassword = (String)obj;
         System.out.println("Password is :" + confirmPassword);
            if(confirmPassword!=null && confirmPassword.trim().equals("")) {
              FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Password cannot be blank", " detail Passwords do not match!");

//            System.out.println(component.getFamily());
//            String field1Id = (String) component.getAttributes().get("password");

              // Find the actual JSF component for the client ID.
//            UIInput textInput = (UIInput) fc.getViewRoot().findComponent("password");
//            textInput.setValue("");

              dto.setPassword(null);

              throw new ValidatorException(message);
            }else{
                dto.setPassword(confirmPassword);
            }
    }

I tried option dto.setPassword(null); but when it returns to view, blank spaces in password field is still there and i have to manually remove.

what I am missing?

Jayesh
  • 6,047
  • 13
  • 49
  • 81

2 Answers2

1

Within your validator, call resetValue() on the instance of UIComponent passed as argument

public void validateSamePassword(FacesContext fc, UIComponent component, Object obj) {
     System.out.println("UserActionManager.validateSamePassword()");

     String confirmPassword = (String)obj;
     System.out.println("Password is :" + confirmPassword);
        if(confirmPassword!=null && confirmPassword.trim().equals("")) {
          FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,   "Password cannot be blank", " detail Passwords do not match!");

          component.resetValue();

          throw new ValidatorException(message);
        }else{
            dto.setPassword(confirmPassword);
        }
}

dto.setPassword(null) will not affect the value in the password box as input components are designed to preserve the values that caused them to fail validation. resetValue() is a method that will cause the component to reset it's value to an uninitialized state

EDIT: The solution above resets the input value prematurely. Technically, validation doesn't fail until a ValidationException is thrown. To effectively reset the field:

  1. Define a listener event that will reset the value of the component only after validation fails

    public void resetPwd(ComponentSystemEvent evt) throws IOException {
    HtmlInputSecret txt = (HtmlInputSecret) evt.getComponent();
    if(!txt.isValid()){ //make sure that the validation failed 
        txt.resetValue();
       }
    
    }
    
  2. Attach the listener event to the postValidate event listener on the password component. This will ensure that the value is reset only after validation has failed.

      <h:inputSecret id="password" required="true" 
                    requiredMessage="Please enter your password"
                    value="#{userActionManager.dto.password}" 
                    validator="#{userActionManager.validateSamePassword}">
                        <f:event name="postValidate" listener="#{userActionManager.resetPwd}"/>
                        <a4j:ajax event="change" execute="@this" bypassUpdates="true" />
                </h:inputSecret>
    

The key here is to reset the value at the right time. Other options for time include the preRenderView event and postAddToView event. It's all in the timing

kolossus
  • 20,559
  • 3
  • 52
  • 104
  • component.resetValue(); there is no such method on UIComponent. I tried like ((UIInput)component).resetValue() and I found resetValue is there in UIInput. Still no success. blank value is still present in Field and I want to make it clear. – Jayesh Mar 17 '13 at 07:54
  • @JayeshPatel, actually that makes sense. My mistake. Technically, the validation doesn't fail until you throw `ValidationException`. The current solution I've proposed is prematurely resetting the value. See my update for a more appropriate timing. – kolossus Mar 17 '13 at 08:34
  • `resetValue()` is not definied in `UIComponent`. It's definied in `EditableValueHolder` interface which is implemented by among others `UIInput`. – BalusC Mar 17 '13 at 15:07
1

If a component is marked invalid, then it won't redisplay the model value (in your case, the value from the dto). Instead, it will redisplay its submitted value. You just need to set the submitted value to an empty string.

Replace

dto.setPassword(null);

by

((UIInput) component).setSubmittedValue("");
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555