An Introduction to JSF: Part 2

0
98
7 min read

Standard JSF Validators

The JSF Core tag library also includes a number of built-in validators. These validator tags can also be registered with UI components to verify that required fields are completed by the user-that numeric values are within an acceptable range,and that text values are a certain length. For more specific validation scenarios, we can also write our own custom validators. User input validation happens immediately after data conversion during the JSF request lifecycle.

Validating the Length of a Text Value

JSF includes a built-in validator that can be used to ensure a text value entered by the user is between an expected minimum and maximum length. The following example demonstrates using the <f:validatelength> tag’s minimum and maximum attributes to check that the password entered by the user in the password field is exactly 8 characters long. It also demonstrates how to use the label attribute of certain JSF input components (introduced in JSF 1.2) to render a localizable validation message.

JSF Validation Messages The JSF framework includes predefined validation messages for different input components and validation scenarios. These messages are defined in a message bundle (properties file) including in the JSF implementation jar file. Many of these messages are parameterized, meaning that since JSF 1.2 a UI component’s label can be inserted into these messages to provide more detailed information to the user. The default JSF validation messages can be overridden by specifying the same message bundle keys in the application’s message bundle. We will see an example of customizing JSF validation messages below.

Notice that we also set the maxlength attribute of the <h:inputsecret> tag to limit the input to 8 characters. This does not, however, ensure that the user enters a minimum of 8 characters. Therefore, the <f:validatelength> validator tag is required.

<f:view>
<h:form>
<h:outputLabel value="Please enter a password (must be 8
characters): " />
<h:inputSecret maxlength="8" id="password"
value="#{backingBean.password}"
label="Password">
<f:validateLength minimum="8" maximum="8" />
</h:inputSecret>
<h:commandButton value="Submit" /><br />
<h:message for="password" errorStyle="color:red" />
</h:form>
</f:view>

JSF 1.2 Components

Validating a Required Field

The following example demonstrates how to use the built-in JSF validators to ensure that a text field is filled out before the form is processed, and that the numeric value is between 1 and 10:

<f:view>
<h:form>
<h:outputLabel value="Please enter a number: " />
<h:inputText id="number" label="Number"
value="#{backingBean.price}"
required="#{true}" />
<h:commandButton value="Submit" /><br />
<h:message for="number" errorClass="error" />
</h:form>
</f:view>

The following screenshot demonstrates the result of submitting a JSF form containing a required field that was not filled out. We render the validation error message using an <h:message> tag with a for attribute set to the ID of the text field component. We have also overridden the default JSF validation message for required fields by specifying the following message key in our message bundle. We will discuss message bundles and internationalization (I18N) shortly.

javax.faces.component.UIInput.REQUIRED=Required field.
javax.faces.component.UIInput.REQUIRED_detail=Please fill in this field.

JSF 1.2 Components

Validating a numeric range

The JSF Core <f:validatelongrange> and </f:validatedoublerange> tags can be used to validate numeric user input. The following example demonstrates how to use the <f:validatelongrange> tag to ensure an integer value entered by the user is between 1 and 10.

<f:view>
<h:form>
<h:outputLabel value="Please enter a number between 1 and 10: " />
<h:inputText id="number" value="#{backingBean.number}"
label="Number">
<f:validateLongRange minimum="1" maximum="10" />
</h:inputText>
<h:commandButton value="Submit" /><br />
<h:message for="number" errorStyle="color:red" />
<h:outputText value="You entered: #{backingBean.number}"
rendered="#{backingBean.number ne null}" />
</h:form>
</f:view>

The following screenshot shows the result of entering an invalid value into the text field. Notice that the value of the text field’s label attribute is interpolated with the standard JSF validation message.

JSF 1.2 Components

Validating a floating point number is similar to validating an integer. The following example demonstrates how to use the value to ensure that a floating point number is between 0.0 and 1.0.

<f:view>
<h:form>
<h:outputLabel value="Please enter a floating point number between
0 and 1: " />
<h:inputText id="number" value="#{backingBean.percentage}"
label="Percent">
<f:validateDoubleRange minimum="0.0" maximum="1.0" />
</h:inputText>
<h:commandButton value="Submit" /><br />
<h:message for="number" errorStyle="color:red" />
<h:outputText value="You entered: "
rendered="#{backingBean.percentage ne null}" />
<h:outputText value="#{backingBean.percentage}"
rendered="#{backingBean.percentage ne null}" >
<f:convertNumber type="percent" maxFractionDigits="2" />
</h:outputText>
</h:form>
</f:view>

JSF 1.2 Components

Registering a custom validator

JSF also supports defining custom validation classes to provide more specialized user input validation. To create a custom validator, first we need to implement the javax.faces.validator.Validator interface. Implementing a custom validator in JSF is straightforward. In this example, we check if a date supplied by the user represents a valid birthdate. As most humans do not live more than 120 years, we reject any date that is more than 120 years ago. The important thing to note from this code example is not the validation logic itself, but what to do when the validation fails. Note that we construct a FacesMessage object with an error message and then throw a ValidatorException.

package chapter1.validator;

import java.util.Calendar;
import java.util.Date;

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;

public class CustomDateValidator implements Validator {

public void validate(FacesContext context, UIComponent component,
Object object) throws ValidatorException {
if (object instanceof Date) {
Date date = (Date) object;
Calendar calendar = Calendar.getInstance();
calendar.roll(Calendar.YEAR, -120);
if (date.before(calendar.getTime())) {
FacesMessage msg = new FacesMessage();
msg.setSummary("Invalid birthdate: " + date);
msg.setDetail("The date entered is more than 120 years ago.");
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
}
}

We have to declare our custom validators in faces-config.xml as follows, giving the validator an ID of customDateValidator:

<validator>
<description>This birthdate validator checks a date to make sure it
is within the last 120 years.</description>
<display-name>Custom Date Validator</display-name>
<validator-id>customDateValidator</validator-id>

<validator-class>
chapter1.validator.CustomDateValidator
</validator-class>
</validator>

Next, we would register our custom validator on a JSF UI component using the tag. This tag has a converterId attribute that expects the ID of a custom converter declared in faces-config.xml. Notice in the following example that we are also registering the standard JSF <f:convertdatetime></f:convertdatetime> converter on the tag. This is to ensure that the value entered by the user is first converted to a java.util.Date object before it is passed to our custom validator.

<h:inputText id="name" value="#{backingBean.date}">
<f:convertDateTime type="date" pattern="M/d/yyyy" />
<f:validator validatorId="customDateValidator" />
</h:inputText>

Many JSF UI component tags have both a converter and validator attribute that accept EL method expressions. These attributes provides another way to register custom converters and validators implemented in managed beans on UI components.

LEAVE A REPLY

Please enter your comment!
Please enter your name here