An Introduction to JSF: Part 2

Exclusive offer: get 50% off this eBook here
JSF 1.2 Components

JSF 1.2 Components — Save 50%

Develop advanced Ajax-enabled JSF applications

$26.99    $13.50
by Ian Hlavats | December 2009 | Java

This is the second part of the article series on An Introduction to JSF. In this article by Ian Hlavats, we will discuss about Standard JSF Validators and Internationalization in detail. Read An Introduction to JSF: Part 1 here.

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.

JSF 1.2 Components Develop advanced Ajax-enabled JSF applications
Published: November 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Internationalization (I18N)

One of the many benefits of the JSF framework is the ability to easily internationalize our applications. The support for internationalization (abbreviated as I18N, short for “I followed by 18 letters followed by N”) in JSF is built on top of the Java platforms existing internationalization framework, so it should be familiar to Java developers who already have some experience with properties files and the java.util.ResourceBundle and java.util.Locale classes.

As the format of date and time, numbers, and currency values can change significantly from one locale to another, JSF conveniently extends Java’s internationalization support to our user interface by making UI components locale aware. For example, in the US, a currency value is formatted as $1,999.99 while in France this value is formatted as 1 999,99 $.

At the root of the UI component tree for each view is the JSF UIViewRoot object. This component is rendered by the tag in our JSF markup, and supports a locale attribute that accepts any valid locale value that can be passed to the constructor of the java.util.Locale class.

Internationalization first requires us to define the locales we are supporting, and to convert text messages and other application resources into locale-specific formats. This process is called localization (L10N). Let’s examine the process of localizing the labels for our UI components in a message bundle for three locales: English (our default locale), French, and Spanish.

What is a Locale?A locale in the context of Java internationalization can be defined in terms of a language, country, and variant. In the simplest case, a locale can be a language such as English, French, or Spanish (for example). These languages are represented using ISO-639 standard language codes, specifically “en”, “fr”, and “sp”. As English is spoken and written differently in various English-speaking countries, the Java I18N framework enables us to refine our support for different locales by qualifying the language with a country code, such as “en_US” for US English speakers, and “en_GB” for British English speakers.Finally, the locale identifier can be further qualified by adding a variant after the country code. A variant is an optional identifier for a vendor’s product, such as an operating system or Web browser, or a variation of the language code, such as the traditional or international form of a language. An example of the locale code for a traditional Spanish speaking Windows user would be “en_ES_Traditional_WIN”. (When there are two variant codes, they should be separated with an underscore and the most important one placed first.)

For demonstration purposes, we will only be supporting the English, French, and Spanish languages and will not be using the language or variant components of the locale code. As our JSF application supports three languages, our localized messages would be stored in three message bundles (.properties files), one per language, named “messages_en.properties”, “messages_fr.properties”, and “messages_sp.properties”.

To illustrate how message bundles work, let’s take a closer look at our properties files.

The following is an extract from our English message bundle. Keep in mind that these messages will be used in our JSF pages as button and field labels. Validation messages can also be stored in these files.

messages_en.properties

firstNameLabel=First Name
lastNameLabel=Last Name
dateOfBirthLabel=Date of Birth
genderLabel=Gender
phoneNumberLabel=Phone Number
emailAddressLabel=Email Address
countryLabel=Country of Origin
interestsLabel=Relevant Interests

The following is an extract from our French message bundle. Notice that the same keys are defined, but the values are different. The messages have been translated into French for this locale.

messages_fr.properties

firstNameLabel=Prénom
lastNameLabel=Nom de famille
dateOfBirthLabel=Date de naissance
genderLabel=Sexe
phoneNumberLabel=Téléphone
emailAddressLabel=Courriel
countryLabel=Pays d'origine
interestsLabel=Intérêts

The following is a sample from our Spanish message bundle. Once again, the keys are the same but the message bundle values have been localized (this time in Spanish).

messages_sp.properties

firstNameLabel=Nombre
lastNameLabel=Apellido
dateOfBirthLabel=Fecha de nacimiento
genderLabel=Género
phoneNumberLabel=Número de teléfono
emailAddressLabel=Correo electrónico
countryLabel=País de origen
interestsLabel=Intereses

These message bundles are included with our web application and accessed by the JSF framework when a localized message is rendered in the view. As JSF 1.2, there are two ways to make message bundles available to web pages in our JSF applications:

Registering a message bundle (JSF 1.1)

Registering a message bundle in JSF 1.1 requires adding the following XML to the faces-config.xml file:

<application>
<message-bundle>messages</message-bundle>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>fr</supported-locale>
<supported-locale>es</supported-locale>
</locale-config>
</application>

Notice that we specify the name of the message bundle properties file (without the locale information and without the .properties file extension) for the <message-bundle> element. Next we specify the locales supported by our JSF application in the </locale-config> element, indicating the English (en) is our default locale. The JSF framework will expect the following files to exist on our web application’s classpath:

  • messages.properties - The default (English) message bundle
  • messages_en.properties - The English message bundle
  • messages_fr.properties – The French message bundle
  • messages_sp.properties – The Spanish message bundle

To use our message bundles, we need to declare the <f:loadbundle> tag in our JSF pages:

<f:view>
<f:loadBundle var=”bundle” basename=”messages” />
<h:outputText value=”#{bundle.welcomeMessage}” />
</f:view>

The previous example loads a message bundle for the current JSF page into a Map object and stores it in a variable named “bundle” that can be access using EL expressions. The <h:outputtext> tag demonstrates how to lookup and display a string from the message bundle with the key “welcomeMessage”.

As we did not specify the locale attribute on the <f:view> tag, the JSF framework will automatically attempt to determine the locale of the user by examining the browser’s HTTP request headers.

Registering a Message Bundle (JSF 1.2)

Since JSF 1.2, there is another way to use message bundles in our JSF pages. Instead of loading our message bundle on each page using the <f:loadbundle>  tag, we can simply declare our message bundle once in faces-config.xml and use it from any page in our JSF application. The following XML must be added to faces-config.xml to enable this feature:

<application>
<resource-bundle>
<base-name>messages</base-name>
<var>bundle</var>
</resource-bundle>
</application>

The previous example loads a message bundle from the messages.properties file for the locale of the current view and stores it as a Map object named “bundle”. EL expressions can reference this message bundle as they did before using the <f:loadbundle> approach. The benefit of using the <resource-bundle> element in faces-config.xml instead of the </message-bundle> element is that we can now register our message bundle once for the entire JSF application, instead of having to register it on each page.

Summary

In this article series, we learned a lot about JavaServer Faces (JSF). We spoke about:

  • Model-View-Controller architecture
  • JSF Request Processing Lifecycle
  • Managed Beans
  • EL Expressions
  • UI Components
  • Validators
  • Internationalization

 

JSF 1.2 Components Develop advanced Ajax-enabled JSF applications
Published: November 2009
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Ian Hlavats

Ian Hlavats is an experienced Java developer, instructor, speaker, and author of the book JSF 1.2 Components (Packt). He has worked for clients in government, insurance, and entertainment industries, writing Java applications using Swing, Struts, JSF2, PrimeFaces, jQuery, and other UI technologies. He has delivered Java courses in college and corporate training environments including a one-year engagement with Cognos/IBM.

He is on the JSF 2.2 Expert Group and contributed to the next generation of the JSF specification. A regular speaker at Java EE conferences, he has given presentations on JSF and PrimeFaces technologies since 2008 at JSF Summit, NFJS, and JAXConf in San Francisco. He is the creator of JSFToolbox for Dreamweaver, a suite of design and coding extensions for JSF developers. He co-hosts a podcast on JSF and Java EE technologies with fellow authors Kito D. Mann and Daniel Hinojosa. He holds a Bachelor of Humanities degree from Carleton University and IT certificates from Algonquin College.

Books From Packt

GlassFish Administration
GlassFish Administration

JBoss AS 5 Development
JBoss AS 5 Development

Spring Persistence with Hibernate
Spring Persistence with Hibernate

Tomcat 6 Developer's Guide
Tomcat 6 Developer's Guide

RESTful Java Web Services
RESTful Java Web Services

ICEfaces 1.8: Next Generation Enterprise Web Development
ICEfaces 1.8: Next Generation Enterprise Web Development

JBoss RichFaces 3.3
JBoss RichFaces 3.3

Apache Maven 2 Effective Implementation
Apache Maven 2 Effective Implementation

No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
L
w
a
H
u
Y
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software