This month, Rizon Software's CTO Paul Tabor joins me on my quest to dispel the FUD about JSF. In this article, we'll work through the concepts of JSF's conversion and validation framework, which is much simpler to use and far more flexible than you may think.
We'll start with an introduction to conversion and validation procedures as they apply to the JSF lifecycle, then demonstrate a default conversion and validation procedure in a simple JSF application. We'll also show you how to create and plug-in your own custom implementations to deal with more demanding scenarios. As Rick has in previous articles, we'll focus on both theory and practice, explaining the concepts and then walking through them with a working example. The example application will cover most conversion and validation use cases, albeit at a basic level.
Note that the default build environment for the example application is Maven, though an Ant script is also provided. You can download the example source by clicking the Code icon at the top or bottom of this page. For simplicity, you'll find the example setup the same as it was in the previous article. See Resources for further directions on the build environment setup, including directions for building and running the example application in Ant rather than Maven.
While it isn't necessary to understand the underpinnings of the JavaServer Faces lifecycle to use conversion and validation in a JSF Web application, it probably is a good idea to review some of the basics before jumping into conversion and validation specifics. Besides, a little dose of JSF lifecycle know-how can go a long way toward simplifying your Web application development efforts. It will also help you better understand JSF's pluggable capabilities.
Figure 1 outlines what we call the "basic JSF lifecycle." Basic simply implies a typical faces request-and-response scenario dealing with submitted form values.
Figure 1. Basic JSF lifecycle

Obviously, different scenarios could differently impact the lifecycle descriptions highlighted here. We'll describe some of them a little later in the article. For now, you should simply note that conversion and validation processes occur at the phases of apply request values, process validations, and render response.
We'll explain in a minute why conversion and validation happen at these phases, but first let's clear up a more basic question: What is conversion? Simply put, it's the process of ensuring data is of the right object or type. Here are two typical conversions:
- string value is convertible to a
java.util.Date - string value is convertible to a Float
As for validation, it ensures data contains the expected content. Here are two typical validations:
- java.util.Date is MM/yyyy format
- Float is between 1.0 and 100.0
The main purpose of conversion and validation is to ensure values have been properly sanitized before updating model data. Subsequently, when the time comes to invoke application methods to actually do something with that data, you can safely make certain assumptions about the state of your model. Conversion and validation allow you to focus on business logic rather than the tedious qualifications of input data such as null checks, length qualifiers, range boundaries, etc.
It makes sense, then, that conversion and validation processes happen before component data is bound to your backing bean model in the update model data lifecycle phase. As you saw in Figure 1, conversion occurs in the apply request values phase and validation in the process validations phase. These phases are highlighted in Figure 2.
Figure 2. Conversion and validation phases of interest

Note that the conversion and validation processes outlined in
Figure 2 represent the application flow when the UIInput component's
immediate attribute is set to false. Were the
attribute set to true, conversion and validation would occur
earlier in the lifecycle, during the apply request values phase (see
Figure 3). A detailed discussion about using the immediate attribute is
beyond the scope of this article, but there are instances where it is
useful -- such as managing dynamic lists (which you may recall from
the previous article in this series) and even bypassing validation
altogether (when used with a UICommand component). Can
you think of an application where it would be useful to bypass
validation completely?
Figure 3 shows where conversion and validation would occur in the JSF
application lifecycle were the immediate attribute set to true.
Figure 3. When the immediate attribute is true

From here on we'll use an example application to demonstrate the concepts discussed. This month's example application will demonstrate JSF's conversion and validation capabilities. Bear in mind that the application is very simple and not necessarily comprehensive: Our goal isn't to build an application for use in the real world, after all! The example app will demonstrate the following:
- Usage of standard JSF converters for converting form field data
- Usage of standard JSF validation components for validating form field data
- How to write custom converters and validator
- How to register custom converters and validators in the faces-config.xml file
- How to customize default error messages
The example application is a simple user registration form. Our objective is to gather user data such as name, age, e-mail address, and phone number. Then, we'll show you how to utilize JSF conversion and validation to ensure that the collected data is appropriate for the model.
The application utilizes three JSP pages:
- index.jsp redirects the user to UserRegistration.jsp
- UserRegistration.jsp contains the application's form fields
- results.jsp notifies the application that the user was registered
We'll start start with a look at the options for coding JSF conversion processes.
As previously mentioned, conversion is the process of ensuring data
is of the right object or type; hence we convert strings values into
other types like Date objects, primitive float, or
Float objects. You can use built-in converters or write
custom converters.
JSF supplies many standard data converters. You can also plug in your own
custom converter by implementing the Converter interface, but more on that later.
The following table shows converter ids and the corresponding implementation classes
used by JSF for a simple data conversion. Most data conversions happen automatically.
javax.faces.BigDecimal | javax.faces.convert.BigDecimalConverter |
javax.faces.BigInteger | javax.faces.convert.BigIntegerConverter |
javax.faces.Boolean | javax.faces.convert.BooleanConverter |
javax.faces.Byte | javax.faces.convert.ByteConverter |
javax.faces.Character | javax.faces.convert.CharacterConverter |
javax.faces.DateTime | javax.faces.convert.DateTimeConverter |
javax.faces.Double | javax.faces.convert.DoubleConverter |
javax.faces.Float | javax.faces.convert.FloatConverter |
Figure 4 demonstrates a default conversion on the user's age. The JSF tag is configured as such:
<!-- UserRegistration.jsp -->
<h:inputText id="age" value="#{UserRegistration.user.age}"/>
|
Figure 4. User registration: default conversion on age

A converter for every occasion
UserRegistration.user.age represents a value-binding property that is of type
int. For bindings of either primitive types, or BigInteger/
BigDecimal, JSF chooses a standard converter. However, you may
also use a specific converter for increased granularity using the
<f:converter/> tag, as shown here.
<!-- UserRegistration.jsp -->
<h:inputText id="age" value="#{UserRegistration.user.age}">
<f:converter id="javax.faces.Short"/>
</h:inputText>
|
In Figure 5 you see one scenario where JSF uses a standard converter. In this case, while age is actually a valid integer, conversion still fails because the value is not a short integer.
Figure 5. Using the f:converter tag

Choosing a date format pattern
Although JSF handles primitives and such quite nicely by default,
when dealing with date data you must specify the conversion
tag <f:convertDateTime/>. This tag is based on the
java.text package and utilizes short, long, and custom
patterns. Here's an example:
<!-- UserRegistration.jsp -->
<h:inputText id="birthDate" value="#{UserRegistration.user.birthDate}">
<f:convertDateTime pattern="MM/yyyy"/>
</h:inputText>
|
This example demonstrates how to use
<f:convertDateTime/> to ensure the user's birth
date is convertible into a date object formatted as MM/yyyy
(month/year). See JSF's java.text.SimpleDataFormat (in
Resources) for a list of patterns.
In addition to allowing you to convert date and time formats, JSF
provides a special converter for dealing with numbers such as
percentages or currency. This converter deals with grouping (such
as commas), number of decimal digits, currency symbols, and such. For
example, the following usage of <f:convertNumber/>
is one technique for dealing with currency:
<!-- UserRegistration.jsp -->
<h:inputText id="salary" value="#{UserRegistration.user.salary}">
<f:convertNumber maxFractionDigits="2"
groupingUsed="true"
currencySymbol="$"
maxIntegerDigits="7"
type="currency"/>
</h:inputText>
|
In Figure 6, you see some incorrectly formatted currency data and the resulting conversion error.
Figure 6. Using the f:convertNumber tag

Custom data conversion is necessary if you need to convert field data into an application-specific value object, as in the following examples:
- String to PhoneNumber object (PhoneNumber.areaCode, PhoneNumber.prefix, ...)
- String to Name object (Name.first, Name.last)
- String to ProductCode object (ProductCode.partNum, ProductCode.rev, ...)
To create a custom converter, you must do the following:
- Implement the
Converterinterface (a.k.a.javax.faces.convert.Converter). - Implement the
getAsObjectmethod, which converts a field (string) into an object (for example,PhoneNumber). - Implement the
getAsStringmethod, which converts an object (for example,PhoneNumber) into a string. - Register your custom converter in the
Facescontext. - Insert the converter into your JSPs with the
<f:converter/>tag.
You can see for yourself how these steps fit into the JSF application lifecycle.
In Figure 7, JSF calls the getAsObject method of the custom
converter during the apply request values phase. This is where the converter
must convert the request string value into the desired object type, and then
return the object for storage in the corresponding JSF component. When the value is rendered
back to the view, JSF will call the getAsString method in the render response
phase. This means the converter is also responsible for transforming the
object data back in to a string representation.
Figure 7. Custom converter getAsObject and getAsString methods

We'll use a case study to demonstrate the implementation of the Converter
interface, getAsObject and getAsString methods,
and how to register the converter with the Faces context.
The goal of this case study is to convert a single field string value into a
PhoneNumber object. We'll go through it step by step.
Step 1: Implement the Converter interface
This step implements the Converter interface.
import javax.faces.convert.Converter;
import org.apache.commons.lang.StringUtils;
...
public class PhoneConverter implements Converter {
...
}
|
Step 2: Implement the getAsObject method
This step converts a field value into a PhoneNumber object.
public class PhoneConverter implements Converter {
...
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (StringUtils.isEmpty(value)){ return null;}
PhoneNumber phone = new PhoneNumber();
String [] phoneComps = StringUtils.split(value," ,()-");
String countryCode = phoneComps[0];
phone.setCountryCode(countryCode);
if ("1".equals(countryCode)){
String areaCode = phoneComps[1];
String prefix = phoneComps[2];
String number = phoneComps[3];
phone.setAreaCode(areaCode);
phone.setPrefix(prefix);
phone.setNumber(number);
}else {
phone.setNumber(value);
}
return phone;
}
}
|
Step 3: Implement the getAsString method
This step converts a PhoneNumber object into a string.
public class PhoneConverter implements Converter {
...
public String getAsString(FacesContext context,
UIComponent component, Object value) {
return value.toString();
}
}
public class PhoneNumber implements Serializable {
...
public String toString(){
if (countryCode.equals("1")){
return countryCode + " " + areaCode
+ " " + prefix + " " + number;
}else{
return number;
}
}
}
|
Step 4: Register custom converter with faces context
Step 4 can be executed in one of two ways. The first option is to register the
PhoneConverter class with the id of (for example)
arcmind.PhoneConverter. This id
will then be used by the <f:converter/> tag in your
JSP pages. Here's the code for Step 4, option 1:
<converter>
<converter-id>arcmind.PhoneConverter</converter-id>
<converter-class>com.arcmind.converters.PhoneConverter</converter-class>
</converter>
|
Alternately, you could register the PhoneConverter class to
handle all PhoneNumber objects automatically, as shown here.
<converter>
<converter-for-class>com.arcmind.value.PhoneNumber</converter-for-class>
<converter-class>com.arcmind.converters.PhoneConverter</converter-class>
</converter>
|
Step 5: Use the converter tag in your JSPs?
The execution of the next step will, of course, depend on the
registration option you've chosen. If you chose to register the
PhoneConverter class with the id of
arcmind.PhoneConverter, then you'll use the
<f:converter/> tag as shown here.
<h:inputText id="phone" value="#{UserRegistration.user.phone}">
<f:converter converterId="arcmind.PhoneConverter" />
</h:inputText>
|
If you chose to register the PhoneConverter class to
handle all PhoneNumber objects automatically then you
won't need to use the <f:converter/> tag in your JSPs.
Here's the code for Step 5 without the converter tag.
<h:inputText id="phone" value="#{UserRegistration.user.phone}">
[Look mom no converter!]
</h:inputText>
|
And with that we're done with the conversion processing code for the example application! Here's what the app looks like so far.
Figure 8. Example app with conversion processing

As you'll recall, JSF validation ensures the application data contains the expected content, such as:
- java.util.Date is MM/yyyy format
- Float is between 1.0 and 100.0
There are four forms of validation within JSF:
- Built-in validation components
- Application-level validation
- Custom validation components (which implement the
Validatorinterface) - Validation methods in backing beans (inline)
We'll explain and demonstrate each of these forms in the discussion that follows.
The JSF validation lifecycle and components
Figure 9 shows a lifecycle case study for the first name field of our user registration form. The code references are intended to be interpreted as pseudo-code.
Figure 9. Validation in the JSF lifecycle

Here's a list of the standard validation components supplied by JSF:
DoubleRangeValidator: Component's local value must be numeric type; must be in range specified by minimum and/or maximum values.LongRangeValidator: Component's local value must be numeric type and convertible to long; must be in range specified by minimum and/or maximum values.LengthValidator: Type must be string; length must be in range specified by minimum and/or maximum values.
In our example app the user's age can be any valid integer (byte, short, int). Because it doesn't make sense to allow an age of, say, -2, you'll probably want to add some validation to the field. Here's some simple validation code for ensuring the model integrity of data in an age field:
<h:inputText id="age" value="#{UserRegistration.user.age}">
<f:validateLongRange maximum="150"
minimum="0"/>
</h:inputText>
|
Once you have the age field sorted out, you might want to specify length restrictions on the first-name field. You could code this validation as follows:
<h:inputText id="firstName"
value="#{UserRegistration.user.firstName}">
<f:validateLength minimum="2"
maximum="25" />
</h:inputText>
|
Figure 10 shows the default verbose validation messages generated by the above standard validation examples.
Figure 10. Standard validation error messages

Although it works for many scenarios, JSF's built-in validation is somewhat limited. When dealing with e-mail validation, phone numbers, URLs, dates, etc., it's sometimes better to write your own validator; but we'll get to that in just a bit.
In concept, application-level validation is really business logic validation. JSF separates form- and/or field-level validation from business-logic validation. Basically, application-level validation entails adding additional code to the backing bean methods that use the model to qualify the data already bound to your model. In the case of a shopping cart, form-level validation may validate whether a quantity entered is valid, but you would need business-logic validation to check whether the user had exceeded his or her credit limit. This is another example of the separation of concerns in JSF.
For example, let's say the user clicks a button that is bound to an action method, which gets invoked during the invoke application phase (refer back to Figure 1 for details). Prior to performing any manipulation of model data, which was presumably updated during the update model phase, you could add code that checks to see if the data entered is valid based on the application's business rules.
For instance, in the example application, the user clicks the
Register button, which is bound to the register() method of
the application controller. We could add validation code to the register() method
to determine whether the first-name field is blank or null. In cases where the
field was null, we could also add a message to the FacesContext
directing the associated component to return navigation to the
current page.
Now, granted this is not a good example of business-rule logic. A better example would be checking to see if the user had exceeded his or her credit limit. In this case, instead of checking to see if the field was blank we could invoke a method on a model object to ensure that the current user wasn't already in the system.
You can see an outline of this process in Figure 11.
Figure 11. Application-level validation

Notice how in the register() method, the message is added to the
FacesContext as ${formId}:${fieldId}. Figure 12
shows the relationship between messages and component ids.
Figure 12. A validation message

Pros and cons of application-level validation
Application-level validation is clearly straightforward and easy to do. However, this form of validation occurs after other forms of validation (standard, custom, component).
The advantages of application-level validation are as follows:
- Easy to implement
- No need for a separate class (custom validator)
- No need for page author to specify validator
The disadvantages of application-level validation are as follows:
- Occurs after other forms of validation (standard, custom)
- Validation logic limited to backing bean method, resulting in limited re-use
- Can be difficult to manage in large applications and/or team environment
Ultimately, application-level validation should be used only for circumstances requiring business-logic validation.
You will need to build your own custom validation components for data types that aren't supported by the standard JSF validators, including e-mail addresses and zip codes. You'll also need to build your own validators in cases where you want explicit control over the validation messages displayed to the end user. With JSF, you can create pluggable validation components that are re-usable throughout your Web applications.
The steps to create a custom validator are as follows; we'll go over them one by one:
- Create a class that implements the
Validatorinterface (javax.faces.validator.Validator). - Implement the
validatemethod. - Register your custom validator in the faces-confix.xml file.
- Use the
<f:validator/>tag in your JSPs.
Here's the example code to create a custom validator, step by step.
Step 1: Implement the Validator interface
The first step is to implement the Validator interface.
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
...
public class ZipCodeValidator implements Validator{
private boolean plus4Required;
private boolean plus4Optional;
/** Accepts zip codes like 85710 */
private static final String ZIP_REGEX = "[0-9]{5}";
/** Accepts zip code plus 4 extensions like "-1119" or " 1119" */
private static final String PLUS4_REQUIRED_REGEX = "[ |-]{1}[0-9]{4}";
/** Optionally accepts a plus 4 */
private static final String PLUS4_OPTIONAL_REGEX = "([ |-]{1}[0-9]{4})?";
...
}
|
Step 2: Implement the validate method
Next, you need to implement the validate method.
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
/* Create the correct mask */
Pattern mask = null;
/* more on this method later */
initProps(component);
if (plus4Required){
mask = Pattern.compile(ZIP_REGEX + PLUS4_REQUIRED_REGEX);
} else if (plus4Optional){
mask = Pattern.compile(ZIP_REGEX + PLUS4_OPTIONAL_REGEX);
} else if (plus4Required && plus4Optional){
throw new IllegalStateException("Plus 4 is either optional or required");
}
else {
mask = Pattern.compile(ZIP_REGEX);
}
/* Get the string value of the current field */
String zipField = (String)value;
/* Check to see if the value is a zip code */
Matcher matcher = mask.matcher(zipField);
if (!matcher.matches()){
FacesMessage message = new FacesMessage();
message.setDetail("Zip code not valid");
message.setSummary("Zip code not valid");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
|
Step 3: Register your custom validator with the FacesContext
The code to register the custom validator with the FacesContext should look
familiar to you by now.
<validator>
<validator-id>arcmind.zipCodeValidator</validator-id>
<validator-class>com.arcmind.jsfquickstart.validation.ZipCodeValidator</validator-class>
</validator>
|
Step 4: Use the <f:validator/> tag in your JSPs
The <f:validator/> tag declares use of the
zipCodeValidator. The <f:attribute/>
tag sets the plus4Optional attribute to true.
Note that this defines an attribute of the inputText
component, not the validator!
<h:inputText id="zipCode" value="#{UserRegistration.user.zipCode}">
<f:validator validatorId="armind.zipCodeValidator"/>
<f:attribute name="plus4Optional" value="true"/>
</h:inputText>
|
To read the plus4Optional attribute for the zipCodeinputText component, do the following:
private void initProps(UIComponent component) {
Boolean optional = Boolean.valueOf((String) component.getAttributes().
get("plus4Optional"));
Boolean required = Boolean.valueOf((String) component.getAttributes().
get("plus4Required"));
plus4Optional = optional==null ? plus4Optional :
optional.booleanValue();
plus4Required = required==null ? plus4Optional :
required.booleanValue();
}
|
Overall, creating custom validators is fairly straightforward and makes validation reusable across many applications. The downside is that you do have to create another class and manage validator registration within the faces context. However, you can take the implementation of your custom validator one step further and make it look like built-in validation by creating a custom tag that utilizes the validator. For common validation concerns, such as e-mail validation, this approach can support design philosophies where code re-use and consistent application behavior are of utmost importance.
Validation methods in backing beans
As an alternative to creating a separate validator class, you can simply
implement custom validation in a backing bean method, as long as the method
adheres to the same argument signature as the Validator interface's
validate method. For instance, you might write the following method:
[SomeBackingBean.java]
public void validateEmail(FacesContext context,
UIComponent toValidate,
Object value) {
String email = (String) value;
if (email.indexOf('@') == -1) {
((UIInput)toValidate).setValid(false);
FacesMessage message = new FacesMessage("Invalid Email");
context.addMessage(toValidate.getClientId(context), message);
}
}
|
The method would then be used in the JSF tag via the validator attribute as
shown here:
<h:inputText id="email"
value="#{UserRegistration.user.email}"
validator="#{UserRegistration.validateEmail}"
required="true">
</h:inputText>
|
The validateEmail method is used by JSF to perform
custom validation on an inputText component value bound to
a user.email model
property. If the e-mail format is invalid, then a message is added to the faces
context for the associated component. Now, considering that this validation
method is actually part of the backing bean, why does the value have to be
generically evaluated with a component association in lieu of directly
inspecting the local bean properties? For a hint, look at the prior lifecycle
figures. Don't worry if you can't quite figure it out right now; we'll
explain it all at the end of the article.
Notice the required attribute of the
email tag above. Utilizing the required
attribute is a form of default validation. If the attribute is
true then the corresponding component must have a value. One
important note: if the required attribute is false,
and no validation has been assigned to the tag/component, then JSF
will skip validation for this component and leave the value and
component state unchanged.
Figure 13 is an overview of the forms of validation we've discussed.
Figure 13. Validation overview

As you might of noticed, the default conversion and validation messages provided by JSF are verbose and could generate confusion and irritability for end users who insist on entering invalid form data. Fortunately, it's possible to change the default messages supplied by JSF by creating your own message resource bundle. Contained in the jsf-impl.jar (or similar) is a message.properties file that contains the default messages shown in Figure 14.
Figure 14. Default JSF conversion and validation messages

You can change the default messages by creating your own message.properties file and switching out the message resource bundle in the faces context for the specified locale, as shown in Figure 15.
Figure 15. Switching out the message resource bundles

See Resources to learn more about creating custom conversion and validation messages in JSF.
We left a few loose ends for you to ponder earlier in the article,
and the time has come to clean them up! One thing we mentioned was
using immediate attributes for
UICommand buttons such as commandLink or
commandButtons. We asked you to consider in what types of
application scenarios you might want to skip validation.
Basically, in any scenario where a user must enter data, that data
must be validated. If the overall data entry is optional, however,
then validation need not occur. One way of working around the
validation phase of the JSF lifecycle is to utilize the
UICommand component's immediate attribute,
which can force the action to be invoked during the apply request values phase
before the process validations phase (rather than during the invoke
application phase, which occurs after the process validations phase).
The immediate attribute allows you to control page
flow through standard navigation rules while bypassing validation
altogether. You could implement this technique for specific
scenarios such as online wizards with optional steps and/or forms
(such as when the user clicks the Skip button to advance to the next
view) or in cases where the user cancels out a form for some
reason.
The second loose end we left in the article is the question of why, if a validation method is actually part of a backing bean, its value must be generically evaluated with a component association. We told you to refer back to the JSF application lifecycle and see if you could figure it out.
The trick here is that, although the validateEmail inline
validation method is part of the actual backing bean, the method must reference
the value via component association rather than accessing the local properties
directly. Because validation occurs before the component values are bound to the
model (in the update model values phase), the model is in an
unknown state. Therefore, you must write the inline custom validation logic as
if it were dealing with validation in a custom Validator object.
This is also explains the requirement of maintaining the same method signature.
What's interesting about both of these loose ends, of course, is that they ultimately lead back to the JSF application lifecycle. Together they illustrate the importance of understanding the lifecycle -- backwards, forwards, and inside out -- so that you can manipulate it when you need to.
We've covered quite a bit of ground in this article when it comes to JSF conversion and validation. In fact, we've covered most of what you'll ever need to know about these processes to make them work in your applications (at least for this version of JSF)!
Of course, we couldn't cover everything. For example, you might want to check out MyFaces (see Resources) for validator components not offered in JSF or discussed here. Additionally, while we discussed the most common conversion and validation techniques, there are some we couldn't include here. For instance, when writing custom components you can deal with conversion and/or validation directly within the component's decode/encode process (depending on the type of component and its functionality); but we'll have to save a more in-depth discussion of custom component development for a later time.
Something else to keep in mind is that conversion and validation
don't necessarily work well together. Conversion converts strings
into objects, whereas most of the standard validators work on strings.
Therefore, you must execute caution when using custom convertors and
validators together. For instance, our PhoneNumber
object would not work with a length validator. In this case, you would
either have to write a custom validator, as well, or simply include
any special validation logic in the custom converter. We prefer the
latter option because it allows us to simply associate a custom
converter (with built-in validation logic) with a specific object type
and have JSF handle that object type. JSF does this for us
automatically without having to specify any converter ids in
the JSP. (Of course, some might call this lazy programming, and it
isn't necessarily the best solution for all use cases.)
We think the discussion in this month's article shows, once again, that JSF provides a flexible, powerful, and pluggable framework for Web application development. In addition to standard converters and validators, JSF facilitates custom implementations to accommodate both application and framework developers alike. Ultimately, the conversion and validation strategy you choose is up to you. JSF allows you to easily and quickly get started (standard converters, validators, inline validation) during prototyping, and migrate to more sophisticated production solutions (custom objects, custom messages) during later development phases. And throughout it all, the JSF application lifecycle provides a reliable infrastructure for consistently ensuring data-model integrity.
We'll wrap up this series next month, with an in-depth look at writing your own custom components in JSF.
| Description | Name | Size | Download method |
|---|---|---|---|
| validation zip file without JAR files | jsf-validation-no-jars.zip | 32 KB | HTTP |
| validation zip file with JAR files | jsf-validation.zip | 2170 KB | HTTP |
Information about download methods
- Visit the JSF project page to download the JavaServer Faces APIs, custom tag library,
and related documentation.
- You can download Maven from the Apache Maven Project
page.
- See the MyFaces home page
for a listing of validator components not currently offered by JSF.
- Jackwind Li Guojie's "UI
development with JavaServer Faces" (developerWorks, September
2003) is an early-bird's look at the technology.
- Roland Barcia's five-part "Developing JSF Applications using WebSphere
Studio V5.1.1" (developerWorks, January 2004) tutorial is a
hands-on introduction to programming with JSF.
- Browse for books on these and other technical topics.
- You might also want to check out the detailed
JSF tutorial from Sun Microsystems.
- You'll find articles about every aspect of Java programming in
the developerWorks Java technology
zone.
- Also see the Java technology zone tutorials page for a complete Listing of
free Java-focused tutorials from developerWorks.
Rick Hightower serves as chief technology officer for ArcMind Inc. He is coauthor of the popular book Java Tools for Extreme Programming, about applying extreme programming to J2EE development, as well as co-author of Professional Struts. Rick worked on JSF QuickStart with Warner Onstine and some of the material in this series is based on examples in that course. Contact Rick at rhightower@arc-mind.com.
Paul Tabor serves as chief technology officer for Rizon Software. He has collaborated with Rick Hightower on several projects over the past year. Paul and Rick have utilized JSF along with Spring and Hibernate in several high-technology applications. Contact Paul at ptabor@rizonsoftware.com or at ptabor@arc-mind.com.




