4 min read

JSF Validation

Earlier in this article, we discussed how the required attribute for JSF input fields allows us to easily make input fields mandatory.

If a user attempts to submit a form with one or more required fields missing, an error message is automatically generated.

Java EE 5 Development with NetBeans 6

The error message is generated by the <h:message> tag corresponding to the invalid field. The string First Name in the error message corresponds to the value of the label attribute for the field. Had we omitted the label attribute, the value of the fields id attribute would have been shown instead. As we can see, the required attribute makes it very easy to implement mandatory field functionality in our application.

Recall that the age field is bound to a property of type Integer in our managed bean. If a user enters a value that is not a valid integer into this field, a validation error is automatically generated.

Java EE 5 Development with NetBeans 6

Of course, a negative age wouldn’t make much sense, however, our application validates that user input is a valid integer with essentially no effort on our part.

The email address input field of our page is bound to a property of type String in our managed bean. As such, there is no built-in validation to make sure that the user enters a valid email address. In cases like this, we need to write our own custom JSF validators.

Custom JSF validators must implement the javax.faces.validator.Validator interface. This interface contains a single method named validate(). This method takes three parameters: an instance of javax.faces.context.FacesContext, an instance of javax.faces.component.UIComponent containing the JSF component we are validating, and an instance of java.lang.Object containing the user entered value for the component. The following example illustrates a typical custom validator.

package com.ensode.jsf.validators;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlInputText;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
public class EmailValidator implements Validator {
public void validate(FacesContext facesContext,
UIComponent uIComponent, Object value) throws
ValidatorException {
Pattern pattern = Pattern.compile("w+@w+.w+");
Matcher matcher = pattern.matcher(
(CharSequence) value);
HtmlInputText htmlInputText = (HtmlInputText) uIComponent;
String label;
if (htmlInputText.getLabel() == null ||
htmlInputText.getLabel().trim().equals("")) {
label = htmlInputText.getId();
} else {
label = htmlInputText.getLabel();
}
if (!matcher.matches()) {
FacesMessage facesMessage =
new FacesMessage(label +
": not a valid email address");
throw new ValidatorException(facesMessage);
}
}
}

In our example, the validate() method does a regular expression match against the value of the JSF component we are validating. If the value matches the expression, validation succeeds, otherwise, validation fails and an instance of javax.faces.validator.ValidatorException is thrown.

The primary purpose of our custom validator is to illustrate how to write custom JSF validations, and not to create a foolproof email address validator. There may be valid email addresses that don’t validate using our validator.

The constructor of ValidatorException takes an instance of javax.faces.application.FacesMessage as a parameter. This object is used to display the error message on the page when validation fails. The message to display is passed as a String to the constructor of FacesMessage. In our example, if the label attribute of the component is not null nor empty, we use it as part of the error message, otherwise we use the value of the component’s id attribute. This behavior follows the pattern established by standard JSF validators.

Before we can use our custom validator in our pages, we need to declare it in the application’s faces-config.xml configuration file. To do so, we need to add a <validator> element just before the closing </faces-config> element.

<validator>
<validator-id>emailValidator</validator-id>
<validator-class>
com.ensode.jsf.validators.EmailValidator
</validator-class>
</validator>

The body of the <validator-id> sub element must contain a unique identifier for our validator. The value of the <validator-class> element must contain the fully qualified name of our validator class.

Once we add our validator to the application’s faces-config.xml, we are ready to use it in our pages.

In our particular case, we need to modify the email field to use our custom validator.

<h:inputText id="email" label="Email Address"
required="true" value="#{RegistrationBean.email}">
<f:validator validatorId="emailValidator"/>
</h:inputText>

All we need to do is nest an <f:validator> tag inside the input field we wish to have validated using our custom validator. The value of the validatorId attribute of <f:validator> must match the value of the body of the <validator-id> element in faces-config.xml.

At this point we are ready to test our custom validator.

Java EE 5 Development with NetBeans 6

When entering an invalid email address into the email address input field and submitting the form, our custom validator logic was executed and the String we passed as a parameter to FacesMessage in our validator() method is shown as the error text by the <h:message> tag for the field.

LEAVE A REPLY

Please enter your comment!
Please enter your name here