Oracle® Fusion Middleware Web User Interface Developer's Guide for Oracle Application Development Framework 11g Release 1 (11.1.1) B31973-05 |
|
![]() Previous |
![]() Next |
This chapter describes how to add conversion and validation capabilities to ADF Faces input components in your application. It also describes how to handle and display any errors, including those not caused by validation.
This chapter includes the following sections:
Section 6.1, "Introduction to ADF Faces Converters and Validators"
Section 6.2, "Conversion, Validation, and the JSF Lifecycle"
ADF Faces input components support conversion capabilities. A web application can store data of many types, such as int
, long
, and date
in the model layer. When viewed in a client browser, however, the user interface has to present the data in a manner that can be read or modified by the user. For example, a date field in a form might represent a java.util.Date
object as a text string in the format mm/dd/yyyy
. When a user edits a date field and submits the form, the string must be converted back to the type that is required by the application. Then the data is validated against any rules and conditions. Conversely, data stored as something other than a String
type can be converted to a String
for display and updating. Many components, such as af:inputDate,
automatically provide a conversion capability.
ADF Faces input components also support validation capabilities. If the required
attribute of an input component is set to true
you can set one or more validator attributes or you can use the ADF Faces validator components. In addition, you can create your own custom validators to suit your business needs.
Validators and converters have a default hint message that is displayed to users when they click in the associated field. For converters, the hint usually tells the user the correct format to use for input values, based on the given pattern. For validators, the hint is used to convey what values are valid, based on the validation configured for the component. If conversion or validation fails, associated error messages are displayed to the user. These messages can be displayed in dialogs, or they can be displayed on the page itself next to the component whose conversion or validation failed. For more information about displaying messages in an ADF Faces application, see Chapter 17, "Displaying Tips, Messages, and Help."
When a form with data is submitted, the browser sends a request value to the server for each UI component whose editable value
attribute is bound. Request values are decoded during the JSF Apply Request Values phase and the decoded value is saved locally on the component in the sumbittedValue
attribute. If the value requires conversion (for example, if it is displayed as a String
type but stored as a DateTime
object), the data is converted to the correct type during the Process Validation phase on a per-UI-component basis.
If validation or conversion fails, the lifecycle proceeds to the Render Response phase and a corresponding error message is displayed on the page. If conversion and validation are successful, then the Update Model phase starts and the converted and validated values are used to update the model.
When a validation or conversion error occurs, the component whose validation or conversion failed places an associated error message in the queue and invalidates itself. The current page is then redisplayed with an error message. ADF Faces components provide a way of declaratively setting these messages.
For detailed information about how conversion and validation works in the JSF Lifecycle, see Chapter 4, "Using the JSF Lifecycle with ADF Faces."
A web application can store data of many types (such as int
, long
, date
) in the model layer. When viewed in a client browser, however, the user interface has to present the data in a manner that can be read or modified by the user. For example, a date field in a form might represent a java.util.Date
object as a text string in the format mm/dd/yyyy
. When a user edits a date field and submits the form, the string must be converted back to the type that is required by the application. Then the data is validated against any rules and conditions. You can set only one converter on a UI component.
When you create an af:inputText
component and set an attribute that is of a type for which there is a converter, JDeveloper automatically adds that converter's tag as a child of the input component. This tag invokes the converter, which will convert the String
type entered by the user back into the type expected by the object.
The JSF standard converters, which handle conversion between String
types and simple data types, implement the javax.faces.convert.Converter
interface. The supplied JSF standard converter classes are:
BigDecimalConverter
BigIntegerConverter
BooleanConverter
ByteConverter
CharacterConverter
DateTimeConverter
DoubleConverter
EnumConverter
FloatConverter
IntegerConverter
LongConverter
NumberConverter
ShortConverter
Table 6-1 shows the converters provided by ADF Faces.
Table 6-1 ADF Faces Converters
Converter | Tag Name | Description |
---|---|---|
|
Converts |
|
|
Converts |
|
|
Converts |
As with validators, the ADF Faces converters are also run on the client side.
if no converter is explicitly added, ADF Faces will attempt to create a converter based on the data type. Therefore, if the value is bound to any of the following types, you do not need to explicitly add a converter:
java.util.Date
java.util.Color
java.awt.Color
java.lang.Number
java.lang.Integer
java.lang.Long
java.lang.Short
java.lang.Byte
java.lang.Float
java.lang.Double
Unlike the converters listed in Table 6-1, the JavaScript-enabled converters are applied by type
and used instead of the standard ones, overriding the class
and id
attributes. They do not have associated tags that can be nested in the component.
You can also manually insert a converter into a UI component.
To add ADF Faces converters that have tags:
In the Structure window, right-click the component for which you would like to add a converter.
In the context menu, choose Insert inside <UI component>, then ADF Faces to insert an ADF Faces converter, or JSF Core to insert a JSF converter.
Choose a converter tag (for example, ConvertDateTime).
In the Property Inspector, set values for the attributes, including any messages for conversion errors. For additional help, right-click any of the attributes and choose Help.
You can set multiple patterns for some ADF Faces converters. For more information, see Section 6.3.2, "How to Set Attributes on a Converter".
ADF Faces lets you customize the detail portion of a conversion error message. By setting a value for a MessageDetailxyz attribute, where xyz is the conversion error type (for example, MessageDetailconvertDate
), ADF Faces displays the custom message instead of a default message, if conversion fails. For more information about creating messages, see Chapter 17, "Displaying Tips, Messages, and Help."
Patterns specify the format of data accepted for conversion. Multiple patterns allow for more than one format. For example, a user could enter dates using a slash (/) or hyphen (-) as a separator. Not all converters support multiple patterns, although pattern matching is flexible and multiple patterns may not be needed.
Example 6-1 illustrates the use of a multiple pattern for the af:convertColor
tag in which "255-255-000" and "FFFF00" are both acceptable values.
Example 6-1 af:convertColor Multiple Patterns
<af:inputColor colorData="#{adfFacesContext.colorPalette.default49}" id="sic3" label="Select a color" value="#{demoColor.colorValue4}" chooseId="chooseId"> <af:convertColor patterns="rrr-ggg-bbb RRGGBB #RRGGBB" transparentAllowed="false"/> </af:inputColor>
Example 6-2 illustrates the use of an af:convertDateTime
tag in which "6/9/2007" and "2007/9/6" are both acceptable values.
Example 6-2 af:convertDateTime Multiple Patterns
<af:inputDate id="mdf5" value="2004/09/06" label="attached converter"> <af:convertDateTime pattern="yyyy/M/d" secondaryPattern="d/M/yyyy" /> </af:inputDate>
Example 6-3 illustrates an af:convertNumber
tag with the type
attribute set to currency
to accepts "$78.57" and "$078.57" as values for conversion.
When the user submits the page containing converters, the ADF Faces validate()
method calls the converter's getAsObject()
method to convert the String
value to the required object type. When there is not an attached converter and if the component is bound to a bean property in the model, then ADF checks the model's data type and attempts to find the appropriate converter. If conversion fails, the component's value
attribute is set to false
and JSF adds an error message to a queue that is maintained by FacesContext
. If conversion is successful and there are validators attached to the component, the converted value is passed to the validators. If no validators are attached to the component, the converted value is stored as a local value that is later used to update the model.
You can create your own converters to meet your specific business needs. You can create custom JSF converters that run on the server-side using Java, and then also create a JavaScript version that can run on the client-side. However, unlike creating custom validators, you can create only converter classes. You cannot add a method to a backing bean to provide conversion.
Creating a custom converter requires writing the business logic for the conversion by creating an implementation of the Converter
interface that contains the getAsObject()
and getAsString()
methods, and then registering the custom converter with the application. You then use the f:converter
tag and set the custom converter as a property of that tag, or you can use the converter
attribute on the input component to bind to that converter.
You can also create a client-side version of the converter. ADF Faces client-side converters work in the same way standard JSF conversion works on the server, except that JavaScript is used on the client. JavaScript converter objects can throw ConverterException
exceptions and they support the getAsObject()
and getAsString()
methods.
To create a custom JSF converter:
Create a Java class that implements the javax.faces.converter.Converter
interface. The implementation must contain a public no-args
constructor, a set of accessor methods for any attributes, and getAsObject
and getAsString
methods to implement the Converter
interface.
The getAsObject()
method takes the FacesContext
instance, the UI component, and the String
value to be converted to a specified object, for example:
public Object getAsObject(FacesContext context, UIComponent component, java.lang.String value){ .. }
The getAsString()
method takes the FacesContext
instance, the UI component, and the object to be converted to a String
value. For example:
public String getAsString(FacesContext context, UIComponent component, Object value){ .. }
For more information about these classes, refer to the Javadoc or visit http://java.sun.com/
.
Add the needed conversion logic. This logic should use javax.faces.convert.ConverterException
to throw the appropriate exceptions and javax.faces.application.FacesMessage
to generate the corresponding error messages. For more information about the Converter
interface and the FacesMessage
error handlers, see the Javadoc for javax.faces.convert.ConverterException
and javax.faces.application.FacesMessage
, or visit http://java.sun.com/
.
If your application saves state on the client, your custom converter must implement the Serializable
interface or the StateHolder
interface, and the saveState(FacesContext)
and restoreState(FacesContext, Object)
methods of the StateHolder
interface. For more information, see the Javadoc for the StateHolder
interface of javax.faces.component
package.
Register the converter in the faces-config.xml
file.
Open the faces-config.xml
file and select the Overview tab in the editor window. The faces-config.xml
file is located in the <View_Project>/WEB-INF
directory in the JDeveloper Application Navigator.
In the window, select Converters and click New. Click Help or press F1 for additional help in registering the converter.
To create a client-side version of the converter:
Write a JavaScript version of the converter, passing relevant information to a constructor. Example 6-4 shows the code to implement the interface org.apache.myfaces.trinidad.convert.ClientConverter
, which has two methods. The first method is getClientScript()
, which returns an implementation of the JavaScript Converter
object. The second method is getClientConversion()
, which returns a JavaScript constructor that is used to instantiate an instance of the converter.
Example 6-4 Interface Converter
function TrConverter() { } /** * Convert the specified model object value, into a String for display * @param value Model object value to be converted * @param label label to identify the editableValueHolder to the user * @return the value as a string or undefined in case of no converter mechanism is * available (see TrNumberConverter). */ TrConverter.prototype.getAsString = function(value, label){} /** * Convert the specified string value into a model data object * which can be passed to validators * @param value String value to be converted * @param label label to identify the editableValueHolder to the user * @return the converted value or undefined in case of no converter mechanism is * available (see TrNumberConverter). */ TrConverter.prototype.getAsObject = function(value, label){}
The TrConverter
interface can throw a TrConverterException
exception, which should contain a TrFacesMessage
error message. Example 6-5 shows the signature for TrFacesMessage
and Example 6-6 shows the signature for TrFacesException
.
Example 6-5 TrFacesMessage Signature
/** * Message similar to javax.faces.application.FacesMessage * @param summary - Localized summary message text * @param detail - Localized detail message text * @param severity - An optional severity for this message. Use constants * SEVERITY_INFO, SEVERITY_WARN, SEVERITY_ERROR, and * SEVERITY_FATAL from the FacesMessage class. Default is * SEVERITY_INFO */ function TrFacesMessage( summary, detail, severity )
Example 6-6 TrFacesException Signature
/** * TrConverterException is an exception thrown by the getAsObject() or getAsString() * method of a Converter, to indicate that the requested conversion cannot be performed. * @param facesMessage the TrFacesMessage associated with this exception * @param summary Localized summary message text, used to create only if facesMessage is null * @param detail Localized detail message text, used only if facesMessage is null */ function TrConverterException( facesMessage, summary, detail
Example 6-7 shows an example of a customer converter, SimpleNumberConverter, written in Java that will run on the server. The custom converter has to implement the ClientConverter
interface.
Example 6-7 Custom Converter SimpleNumberConverter in Java
public class SimpleNumberConverter implements javax.faces.convert.Converter, org.apache.myfaces.trinidad.convert.ClientConverter { public SimpleNumberConverter(boolean isInteger) { _isInteger = isInteger; } // CONVERTER INTERFACE public Object getAsObject(FacesContext context, UIComponent component, String value) { // convert to object } String getAsString(FacesContext context, UIComponent component, Object value) { // convert to string } // CLIENTCONVERTER INTERFACE /** * Called to retrieve the appropriate client * conversion code for the node and context. * For HTML, this will be javascript that will be embedded in a * script tag. For HTML this method is expected to return a * constructor of the javascript Converter object * returned by getClientScript(). */ public String getClientConversion(FacesContext context, UIComponent component) { return "new SimpleNumberConverter(" + Boolean.toString(_isInteger) + ")"; } public Collection<String> getClientImportNames() { // return empty collection } public String getClientLibrarySource(FacesContext context) { return null; } public String getClientScript(FacesContext context, UIComponent component) { return null; } private boolean _isInteger; }
You must also create a JavaScript implementation of the custom converter for the client, as shown in Example 6-8.
Example 6-8 Client-side Implementation of SimpleNumberConverter in JavaScript
/*** constructor of client side SimpleNumberConverter class*/function SimpleNumberConverter(isInteger){ this._isInteger = isInteger;}// Inherit object properties from base class if desired.SimpleNumberConverter.prototype = new SimpleConverter();SimpleNumberConverter.prototype.getAsString = function(number,label){ // convert to string}SimpleNumberConverter.prototype.getAsObject = function(numberString,label){ // convert to object}
To use a custom converter on a JSF page:
Bind your converter class to the converter
attribute of the input component.
Note: If a custom converter is registered in an application under a class for a specific data type, whenever a component's value references a value binding that has the same type as the custom converter object, JSF will automatically use the converter of that class to convert the data. In that case, you do not need to use theconverter attribute to register the custom converter on a component, as shown in the following code:
<af:inputText value="#{myBean.myProperty}"/> The |
When you use a custom converter, the application accesses the converter class referenced in the converter
attribute, and executes the getAsObject
or getAsString
method as appropriate. These methods access the data from the component and execute the conversion logic.
You can add validation so that when a user edits or enters data in a field and submits the form, the data is validated against any set rules and conditions. If validation fails, the application displays an error message. For example, in Figure 6-1 a specific date range for user input with a message hint is set by the af:validateDateTimeRange
component and an error message is displayed in the message popup window when an invalid value is entered.
On the view layer use ADF Faces validation when you want client-side validation. All validators provided by ADF Faces have a client-side peer. Many components have attributes that provide validation. For information, see Section 6.5.1.2, "Using Validation Attributes." In addition, ADF Faces provides separate validation classes that can be run on both the client and the server. For details, see Section 6.5.1.3, "Using ADF Faces Validators." You can also create your own validators. For information about custom validators, see Section 6.6.3, "How to Create a Custom JSF Validator."
Set ADF Faces validation on the input component and an error message is displayed inline or in a popup window on the page. For more information about displaying messages created by validation errors, see Chapter 17, "Displaying Tips, Messages, and Help."
By default, ADF Faces syntactic and semantic validation occurs on both the client and server side. Client-side validation allows validators to catch and display data without requiring a round-trip to the server.
ADF Faces provides the following types of validation:
UI component attributes: ADF Faces input components provide attributes that can be used to validate data. For example, you can supply simple validation using the required
attribute on ADF Faces input components to specify whether or not a value must be supplied. When the required
attribute is set to true
, the component must have a value. Otherwise the application displays an error message. For more information, see Section 6.5.1.2, "Using Validation Attributes."
Default ADF Faces validators: The validators supplied by the JSF framework provide common validation checks, such as validating date ranges and validating the length of entered data. For more information, see Section 6.5.1.3, "Using ADF Faces Validators."
Custom ADF Faces validators: You can create your own validators and then select them to be used in conjunction with UI components. For more information, see Section 6.6, "Creating Custom JSF Validation."
Many ADF Faces UI components have attributes that provide simple validation. For example, the af:chooseDate
component is used in conjunction with an af:inputDate
component for easy date selection. The af:chooseDate
component has maxValue
and minValue
attributes to specify the maximum and minimum number allowed for the Date value.
For additional help with UI component attributes, in the Property Inspector, right-click the attribute name and choose Help.
ADF Faces Validators are separate classes that can be run on the server or client. Table 6-2 describes the validators and their logic.
Table 6-2 ADF Faces Validators
Validator | Tag Name | Description |
---|---|---|
|
Validates the byte length of strings when encoded. The |
|
|
Validates that the entered date is valid with some given restrictions. |
|
|
Validates that the entered date is within a given range. You specify the range as attributes of the validator. |
|
|
Validates that a component value is within a specified range. The value must be convertible to a floating-point type. |
|
|
Validates that the length of a component value is within a specified range. The value must be of type |
|
|
Validates that a component value is within a specified range. The value must be any numeric type or |
|
|
Validates the data using Java regular expression syntax. |
Note: To register a custom validator on a component, use a standard JSFf:validator tag. For information about using custom validators, see Section 6.6, "Creating Custom JSF Validation." |
To add ADF Faces validators:
In the Structure window, right-click the component for which you would like to add a validator.
In the context menu, choose Insert inside <UI component>, then ADF Faces to insert an ADF Faces validator, or JSF Core to insert a JSF reference implementation validator.
Choose a validator tag (for example, ValidateDateTimeRange).
In the Property Inspector, set values for the attributes, including any messages for validation errors. For additional help, right-click any of the attributes and choose Help.
ADF Faces lets you customize the detail portion of a validation error message. By setting a value for a MessageDetailxyz attribute, where xyz is the validation error type (for example, MessageDetailmaximum
), ADF Faces displays the custom message instead of a default message, if validation fails.
When the user submits the page, ADF Faces checks the submitted value and runs conversion on any non-null value. The converted value is then passed to the validate()
method. If the value is empty, the required
attribute of the component is checked and an error message is generated if indicated. If the submitted value is non-null, the validation process continues and all validators on the component are called in order of their declaration.
Note: ADF Faces provides extensions to the standard JSF validators, which have client-side support. |
ADF Faces validation is performed during the Process Validations phase. If any errors are encountered, the components are invalidated and the associated messages are added to the queue in the FacesContext
instance. Once all validation is run on the components, control passes to the model layer, which runs the Validate Model Updates phase. As with the Process Validations phase, if any errors are encountered, the components are invalidated and the associated messages are added to the queue in the FacesContext
instance.
The lifecycle then goes to the Render Response phase and redisplays the current page. ADF Faces automatically displays an error icon next to the label of any input component that generated an error, and displays the associated messages in a popup window unless the af:message
component inline
attribute is set to true
. Figure 6-2 shows a server-side validation error.
You can set zero or more validators on a UI component. You can set the required
attribute and use validators on a component. However, if you set the required
attribute to true
and the value is null
or a zero-length string, the component is invalidated and any other validators registered on the component are not called.
This combination might be an issue if there is a valid case for the component to be empty. For example, if the page contains a Cancel button, the user should be able to click that button and navigate off the page without entering any data. To handle this case, you set the immediate
attribute on the Cancel button's component to true
. This attribute allows the action to be executed during the Apply Request Values phase. Then the default JSF action listener calls FacesContext.renderResponse()
, thus bypassing the validation whenever the action is executed. For more information see Chapter 4, "Using the JSF Lifecycle with ADF Faces."
You can add your own validation logic to meet your specific business needs. If you want custom validation logic for a component on a single page, you can create a validation method on the page's backing bean.
If you want to create logic that will be reused by various pages within the application, or if you want the validation to be able to run on the client side, you should create a JSF validator class. You can then create an ADF Faces version, which will allow the validator to run on the client.
When you want custom validation for a component on a single page, create a method that provides the required validation on a backing bean.
To add a backing bean validation method:
Insert the component that will require validation into the JSF page.
In the visual editor, double-click the component to open the Bind Validator Property dialog.
In the Bind Validator Property dialog, enter or select the managed bean that will hold the validation method, or click New to create a new managed bean. Use the default method signature provided or select an existing method if the logic already exists.
When you click OK in the dialog, JDeveloper adds a skeleton method to the code and opens the bean in the source editor.
Add the required validation logic. This logic should use the javax.faces.validator.ValidatorException
exception to throw the appropriate exceptions and the javax.faces.application.FacesMessage
error message to generate the corresponding error messages. For more information about the Validator
interface and FacesMessage
, see the Javadoc for javax.faces.validator.ValidatorException
and javax.faces.application.FacesMessage
, or visit http://java.sun.com/
.
When you create a validation method, JDeveloper adds a skeleton method to the managed bean you selected. Example 6-9 shows the code JDeveloper generates.
Example 6-9 Managed Bean Code for a Validation Method
public void inputText_validator(FacesContext facesContext, UIComponent uiComponent, Object object) { // Add event code here... }
When the form containing the input component is submitted, the method to which the validator
attribute is bound is executed.
Creating a custom validator requires writing the business logic for the validation by creating a Validator
implementation of the interface, and then registering the custom validator with the application. You can also create a tag for the validator, or you can use the f:validator
tag and the custom validator as an attribute for that tag.
You can then create a client-side version of the validator. ADF Faces client-side validation works in the same way that standard validation works on the server, except that JavaScript is used on the client. JavaScript validator objects can throw ValidatorExceptions
exceptions and they support the validate()
method.
To create a custom JSF validator:
Create a Java class that implements the javax.faces.validator.Validator
interface. The implementation must contain a public no-args
constructor, a set of accessor methods for any attributes, and a validate
method to implement the Validator
interface.
public void validate(FacesContext facesContext, UIComponent uiComponent, Object object) throws ValidatorException { .. }
For more information about these classes, refer to the Javadoc or visit http://java.sun.com/
.
Add the needed validation logic. This logic should use the javax.faces.validate.ValidatorException
exception to throw the appropriate exceptions and the javax.faces.application.FacesMessage
error message to generate the corresponding error messages. For more information about the Validator
interface and FacesMessage
, see the Javadoc for javax.faces.validate.ValidatorException
and javax.faces.application.FacesMessage
, or visit http://java.sun.com/
.
If your application saves state on the client, your custom validator must implement the Serializable
interface, or the StateHolder
interface, and the saveState(FacesContext)
and restoreState(FacesContext, Object)
methods of the StateHolder
interface. For more information, see the Javadoc for the StateHolder
interface of the javax.faces.component
package.
Register the validator in the faces-config.xml
file.
Open the faces-config.xml
file and select the Overview tab in the editor window. The faces-config.xml
file is located in the <View_Project>/WEB-INF
directory.
In the window, select Validators and click New. Click Help or press F1
for additional help in registering the validator.
To create a client-side version of the validator:
Write a JavaScript version of the validator, passing relevant information to a constructor.
Implement the interface org.apache.myfaces.trinidad.validator.ClientValidator
, which has two methods. The first method is getClientScript()
, which returns an implementation of the JavaScript Validator
object. The second method is getClientValidation()
, which returns a JavaScript constructor that is used to instantiate an instance of the validator.
Example 6-10 shows a validator in Java.
Example 6-10 Java Validator
public String getClientValidation( FacesContext context, UIComponent component) { return ("new SSNValidator('Invalid social security number.','Value \"{1}\" must start with \"123\".')"); }
The Java validator calls the JavaScript validator shown in Example 6-11.
To use a custom validator on a JSF page:
To use a custom validator that has a tag on a JSF page, you must manually nest it inside the component's tag.
Example 6-12 shows a custom validator tag nested inside an inputText
component. Note that the tag attributes are used to provide the values for the validator's properties that were declared in the faces-config.xml
file.
Example 6-12 A Custom Validator Tag on a JSF Page
<h:inputText id="empnumber" required="true"> <hdemo:emValidator emPatterns="9999|9 9 9 9|9-9-9-9" /> </h:inputText>
To use a custom validator without a custom tag:
To use a custom validator without a custom tag, nest the validator's ID (as configured in faces-config.xml
file) inside the f:validator
tag. The validator's ID attribute supports EL expression such that the application can dynamically determine the validator to use.
From the Structure window, right-click the input component for which you want to add validation, and choose Insert inside component > ADF Faces Core > Validator.
Select the validator's ID from the dropdown list and click OK.
JDeveloper inserts code on the JSF page that makes the validator ID a property of the f:validator
tag.
Example 6-13 shows the code on a JSF page for a validator using the f:validator
tag.
When you use a custom JSF validator, the application accesses the validator class referenced in either the custom tag or the f:validator
tag and executes the validate()
method. This method accesses the data from the component in the current FacesContext
and executes logic against it to determine if it is valid. If the validator has attributes, those attributes are also accessed and used in the validation routine. Like standard validators, if the custom validation fails, associated messages are placed in the message queue in the FacesContext
instance.