Archive for the ‘Validate in jsf’ Category

renferent

Posted: May 8, 2012 in Validate in jsf

http://byteco.de/2009/06/16/jsf-validations/

Introduction

Validators in JSF are nice. They, however, have its shortcomings. They will by default validate only one field at once. There is no standard way to attach one validator to multiple fields. Although there are some situations where you want this kind of functionality. For example validating the password confirmation field, validating the range of two numeric or date values (e.g. the one have to be lesser than the other), validating correctness of the three separate day, month and year fields, etcetera.

The cleanest solution would be to create a custom component which renders two or more components and use a specific validator for that, but that would involve more work. The easiest solution in this particular case is to attach the validator to the first component of the group (components are rendered, validated, converted and updated in the same order as you define them in the JSF view) and pass the other component(s) as unique f:attribute facet(s) along the first component. Then in the validator you can get the desired component(s) using UIComponent#getAttributes().

Back to top

Basic example

This example demonstrates a basic registration form with one username field and two password fields. The value of the second password field should equal to the value of the first password field before the action method may be invoked. The stuff is tested in a Java EE 5.0 environment with Tomcat 6.0 with Servlet 2.5, JSP 2.1 and JSF 1.2_07 (currently called Mojarra by the way!).

Here is the relevant JSF code. Note the binding=”#{confirm}” of the second password field. It binds the component to the view and makes it available elsewhere by #{confirm}. This is an instance of the UIInput class which has a getSubmittedValue() method to get the submitted value. Note the f:attribute of the first password field, its value should point to the component of the second password field #{confirm}. Also note that the second password field doesn’t have any value bound to the backing bean as this is unnecessary in this specific case.

<h:form id="register">
    <h:panelGrid columns="3">
        <h:outputLabel for="username" value="Username" />
        <h:inputText id="username" value="#{myBean.username}" required="true" />
        <h:message for="username" style="color: red;" />

        <h:outputLabel for="password" value="Password" />
        <h:inputSecret id="password" value="#{myBean.password}" required="true">
            <f:validator validatorId="passwordValidator" />
            <f:attribute name="confirm" value="#{confirm}" />
        </h:inputSecret>
        <h:message for="password" style="color: red;" />

        <h:outputLabel for="confirm" value="Confirm password" />
        <h:inputSecret id="confirm" binding="#{confirm}" required="true" />
        <h:message for="confirm" style="color: red;" />

        <h:panelGroup />
        <h:commandButton value="Register" action="#{myBean.register}" />
        <h:message for="register" style="color: green;" />
    </h:panelGrid>
</h:form>

And now the validator code:

package mypackage;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;

public class PasswordValidator implements Validator {

    // Actions ------------------------------------------------------------------------------------

    public void validate(FacesContext context, UIComponent component, Object value)
        throws ValidatorException
    {
        // Cast the value of the entered password to String.
        String password = (String) value;

        // Obtain the component and submitted value of the confirm password component.
        UIInput confirmComponent = (UIInput) component.getAttributes().get("confirm");
        String confirm = confirmComponent.getSubmittedValue();

        // Check if they both are filled in.
        if (password == null || password.isEmpty() || confirm == null || confirm.isEmpty()) {
            return; // Let required="true" do its job.
        }

        // Compare the password with the confirm password.
        if (!password.equals(confirm)) {
            confirmComponent.setValid(false); // So that it's marked invalid.
            throw new ValidatorException(new FacesMessage("Passwords are not equal."));
        }

        // You can even validate the minimum password length here and throw accordingly.
        // Or, if you're smart, calculate the password strength and throw accordingly ;)
    }

}

The appropriate test backing bean look like:

package mypackage;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

public class MyBean {

    // Init ---------------------------------------------------------------------------------------

    private String username;
    private String password;

    // Actions ------------------------------------------------------------------------------------

    public void register() {

        // Just for debug. Don't do this in real! Hash the password, save to DB and forget it ;)
        System.out.println("Username: " + username);
        System.out.println("Password: " + password);

        // Show succes message.
        FacesContext.getCurrentInstance().addMessage("register", new FacesMessage("Succes!"));
    }

    // Getters ------------------------------------------------------------------------------------

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    // Setters ------------------------------------------------------------------------------------

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

Finally the relevant part of the faces-config.xml:

    <validator>
        <validator-id>passwordValidator</validator-id>
        <validator-class>mypackage.PasswordValidator</validator-class>
    </validator>

    <managed-bean>
        <managed-bean-name>myBean</managed-bean-name>
        <managed-bean-class>mypackage.MyBean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>

From : www.http://balusc.blogspot.com