The JSF Life Cycle
Conversion
- All input from the user to a JSF application begins as
strings.
- Converters can convert these strings into other kinds of Java
objects (part of the Process Validations phase) for
storage in the model.
- All output sent from a JSF application to a browser is
textual.
- To deliver output from a Java object, a converter is used to
convert the object to a string form (the Render Response
phase).
Validation
- Validators check objects after conversion to ensure that they
satisfy application constraints (part of the Process
Validations phase).
- Request Value: form value sent by the browser to the
server using an HTTP request
- Submitted Value: the request value stored in a
UIInput object (part of the page's JSF component tree) in
the Apply Request Values phase
- Local Value: the result of conversion and validation
- During the Update Model Values phase, the local value is
sent to the model bean
A converter for an
input text field requiring a payment amount
using a format having two digits after the decimal point:
<h:inputText value="#{payment.amount}">
<f:convertNumber minFractionDigits="2"/>
</h:inputText>
A converter for an
output text field that supplies a currency symbol
and decimal separators:
<h:outputText value="#{payment.amount}">
<f:convertNumber type="currency"/>
</h:outputText>
A converter for an input text field requiring a date string using a
given date format:
<h:inputText value="#{payment.date}">
<f:convertDateTime pattern="MM/yyyy"/>
</h:inputText>
Built-in JSF converters have names of the
form
javax.faces.converter.<TYPE> where
<TYPE> is one of:
- DateTime
- Number
- Boolean, Byte, Character, Double, Float, Integer, Long, Short
- BigDecimal, BigInteger
Besides using an
f:convert<TYPE> tag, you can use
the
converter attribute with a JSF HTML tag.
For example, the following are equivalent:
<h:outputText value="#{payment.date}" converter="javax.faces.converter.DateTime"/>
<h:outputText value="#{payment.date}">
<f:convertDateTime/>
</h:outputText>
When a conversion error occurs:
- The component whose conversion process failed posts a
message
- No bean processing occurs
- The current page is redisplayed with the values the user
originally entered
The error message must be explicitly included in the page or it will
not appear on page redisplay.
Displaying error messages (
h:message and
h:messages) is
covered in
Ch.4: Standard JSF Tags.
If you don't like the default error message provided by a standard
converter, you can provide a custom converter error message for a
component.
Set the
converterMessage attribute of the component whose value is
being converted. For example:
<h:inputText ... converterMessage="Not a valid number."/>
Key role of validation: protect the model from getting into an inconsistent
state.
Built-in validation mechanisms:
- Checking the length of a string
- Checking limits for a numerical value
- Checking that a value is not missing
Currently JSF does not
explicitly support client-side validation; all
validation occurs on the server side after the user submits form data.
Suppose a credit card number field requires at least 13 characters:
<h:inputText id="card" value="#{payment.card}">
<f:validateLength minimum="13"/>
</h:inputText>
To specify that an input is required:
<h:inputText id="date" value="#{payment.date}">
<f:validateRequired/>
</h:inputText>
Or, use the
required attribute that is supported by all input tags:
<h:inputText id="date" value="#{payment.date}" required="true"/>
Numerical input values may be required to be in a given range. Here is
a validator that checks that the supplied value is ≥ 10 and ≤ 10000:
<h:inputText id="amount" value="#{payment.amount}">
<f:validateLongRange minimum="10" maximum="10000"/>
</h:inputText>
Validation errors are handled in the same way as conversion errors.
You can supply a custom message for a component by setting the
requiredMessage or
validatorMessage attribute, like this:
<h:inputText id="card" value="#{payment.card}" required="true"
requiredMessage="#{msgs.cardRequired}"
validatorMessage="#{msgs.cardInvalid}">
<f:validateLength minimum="13"/>
</h:inputText>
Validation errors (and conversion errors) force a redisplay of the
current page, which can sometimes be problematic.
Suppose a
Cancel button is on a page with required fields.
If the user clicks
Cancel, leaving a required field blank, then
the validation mechanism forces the current page to be redisplayed.
Use the
immediate attribute to bypass validation, forcing the
command to be executed during the
Apply Request Values phase:
<h:commandButton value="Cancel" action="cancel" immediate="true"/>
JSF allows input validation through the annotation of bean properties,
like this:
public class PaymentBean {
@Size(min=13) private String card;
@Future public Date getDate() { ... }
...
}
Advantages of doing this over page-level validation:
- If your web application updates a bean in several pages, you
don’t need to add validation rules to each page
- Validation is handled consistently
Standard converters deal with numbers and dates.
If an application needs to convert string inputs to other types, it
must implement an application-specific converter class.
The
Converter interface (package
javax.faces.converter):
Object getAsObject(FacesContext context, UIComponent component, String newValue)
converts a string into an object of the desired type.
If the conversion cannot be carried out, create
a
FacesMessage that describes the error and throw a
ConverterException
String getAsString(FacesContext context, UIComponent component, Object value)
converts an object into a string representation to be displayed in the
client interface.
A custom validator must implement the
Validator interface
(package
javax.faces.validator) that has one method:
void validate(FacesContext context, UIComponent component, Object value)
If validation fails, generate a
FacesMessage and throw a
ValidatorException.
This section collects the example web applications used in this chapter.