JSF has a pretty comprehensive support for validations, but it is lack of a validation for an empty field. The built-in “required” property of JSF is not so usable, since it validates empty fields only. If a field has a space in it, JSF will accept it. In most scenarios, when inputting text in a form, a space (or several spaces) is considered to be an empty field. Since JSF doesn’t support “out of the box” validation for empty field, we will write our own Validator that will do the job.
Writing a JSF Validator mainly involves 3 things:
- Writing the Validator code by implementing a JSF Validator interface.
- Registering Validator in JSF faces-config.xml.
- Using the Validator in a JSF page.
In order to write the Validator we have to implement “validate” method of Validator interface. This method will be called automatically by JSF, when we use the Validator in some of our input fields. Our Validator class simply checks that the field value is not empty. If the field is empty a ValidationException is thrown from the Validator. JSF mechanism knows to treat this exception as a validation error, when it checks the form inputs for validation errors. Let’s have a look at the Validator code:
package com.bashan.blog.jsf.validator;import javax.faces.application.FacesMessage;import javax.faces.component.UIComponent;import javax.faces.context.FacesContext;import javax.faces.validator.Validator;import javax.faces.validator.ValidatorException;/**
* @author Bashan*/public class RequiredValidator implements Validator {public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {if (value == null || "".equals(value.toString().trim())) {FacesMessage message = new FacesMessage();String messageStr = (String)component.getAttributes().get("message");if (messageStr == null) {messageStr = "Please enter data";}message.setDetail(messageStr);message.setSummary(messageStr);message.setSeverity(FacesMessage.SEVERITY_ERROR);throw new ValidatorException(message);}}}
Note, that the Validator tries to get an attribute named “message” from the component for which it is attached. The “message” attribute should contain a custom error message to show to the user. If “message” attribute is not used, a default error message: “Please enter data” is shown to the user.
Now, let’s register the Validator in JSF faces-config.xml file. This file should be located under the “WEB-INF” directory by default:
<?xml version="1.0" encoding="windows-1255"?><!DOCTYPE faces-config PUBLIC"-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN""http://java.sun.com/dtd/web-facesconfig_1_1.dtd"><faces-config><validator><validator-id>RequiredValidator</validator-id><validator-class>com.bashan.blog.jsf.validator.RequiredValidator</validator-class></validator></faces-config>
You can see in this “faces-config.xml” file the validator id, which is used to call the validator from a JSF page, and the JSF class corresponds to this validator id.
Finally, let’s have a look how this validator is used in a JSF page:
This is only a fragment of a JSF page, showing a text area control and a message under it. Note, that the control can be any JSF input like <h:inputText />. Also note for the <f:attribue /> control used for sending a custom message to the Validator. Another important thing worth mentioning, it that the “required” attribute of the <h:inputTextArea /> control is also used with the same error message (using the “requiredMessage” property). One can say, using 2 validations is redundant, and that only the “RequiredValidator” could have been used. This was true, unless JSF mechanism had a problematic issue with empty fields: When field is empty (has no value and no spaces) validators and converters are not invoked. For this reason, both “required” and “RequiredValidtor” are needed to be used.<h:inputTextarea id="someText" value="#{support.message}" styleClass="textarea1" required="true" requiredMessage="Please write something"><f:attribute name="message" value="Please write something" /><f:validator validatorId="RequiredValidator" /></h:inputTextarea><div><h:message for="someText" styleClass="error"/></div>