
Validator methods
Another way we can implement custom validation is by adding validation methods to one or more of the application's named beans. The following Java class illustrates the use of validator methods for JSF validation:
package net.ensode.glassfishbook.jsfcustomval; import javax.enterprise.context.RequestScoped; 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.ValidatorException; import javax.inject.Named; import org.apache.commons.lang3.StringUtils; @Named @RequestScoped public class AlphaValidator { public void validateAlpha(FacesContext facesContext,
UIComponent uiComponent,
Object value) throws ValidatorException { if (!StringUtils.isAlphaSpace((String) value)) { HtmlInputText htmlInputText = (HtmlInputText) uiComponent; FacesMessage facesMessage = new FacesMessage(htmlInputText. getLabel() + ": only alphabetic characters are allowed."); throw new ValidatorException(facesMessage); } } }
In this example, the class contains only the validator method, but that does not always have to be the case. We can give our validator method any name we want; however its return value must be void, and it must take the three parameters illustrated in the example, in that order. In other words, except for the method name, the signature of a validator method must be identical to the signature of the validate() method defined in the javax.faces.validator.Validator interface.
As we can see, the body of the preceding validator method is nearly identical to the body of our custom validator class, validate() method. We check the value entered by the user to make sure it contains only alphabetic characters and/or spaces; if it does not, then we throw a ValidatorException passing an instance of FacesMessage containing an appropriate error message String: StringUtils.
In the example, we used org.apache.commons.lang3.StringUtils to perform the actual validation logic. In addition to the method used in the example, this class contains several methods for verifying that a String is numeric or alphanumeric. This class, part of the Apache Commons Lang library, is very useful when writing custom validators.
Since every validator method must be in a named bean, we need to make sure the class containing our validator method is annotated with the @Named annotation, as illustrated in our example.
The last thing we need to do to use our validator method is to bind it to our component via the tag's validator attribute:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"> <h:head> <title>Enter Customer Data</title> </h:head> <h:body> <h:outputStylesheet library="css" name="styles.css"/> <h:form> <h:messages></h:messages> <h:panelGrid columns="2" columnClasses="rightAlign,leftAlign"> <h:outputText value="First Name:"> </h:outputText> <h:inputText label="First Name"
value="#{customer.firstName}"
required="true"
validator="#{alphaValidator.validateAlpha}"> <f:validateLength minimum="2" maximum="30"> </f:validateLength> </h:inputText> <h:outputText value="Last Name:"></h:outputText> <h:inputText label="Last Name"
value="#{customer.lastName}"
required="true"
validator="#{alphaValidator.validateAlpha}"> <f:validateLength minimum="2" maximum="30"> </f:validateLength> </h:inputText> <h:outputText value="Email:"> </h:outputText> <h:inputText label="Email" value="#{customer.email}"> <f:validateLength minimum="3" maximum="30"> </f:validateLength> <f:validator validatorId="emailValidator" /> </h:inputText> <h:panelGroup></h:panelGroup> <h:commandButton action="confirmation" value="Save"> </h:commandButton> </h:panelGrid> </h:form> </h:body> </html>
Since neither the first name nor the last name fields should accept anything other than alphabetic characters or spaces, we added our custom validator method to both of these fields.
Notice that the value of the validator attribute of the <h:inputText> tag is a JSF expression language; it uses the default named bean name for the bean containing our validation method. alphaValidator is the name of our bean, and validateAlpha is the name of our validator method.
After modifying our page to use our custom validator, we can now see it in action:
Notice how, for the First Name field, both our custom validator message and the standard length validator were executed.
Implementing validator methods have the advantage of not having the overhead of creating a whole class just for a single validator method (our example does just that, but in many cases, validator methods are added to an existing named bean containing other methods); however, the disadvantage is that each component can only be validated by a single validator method. When using validator classes, several <f:validator> tags can be nested inside the tag to be validated, therefore multiple validations, both custom and standard, can be done on the field.