This chapter includes the following sections:
ADF Faces provides the ability to both convert and validate user provided data to help ensure data integrity. Use the Converters to convert the values on ADF forms to the type that the application accepts them and use Validators to impose validations on the input components.
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. You can add one or more validator tags to the component. 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 information about displaying messages in an ADF Faces application, see Displaying Tips, Messages, and Help.
ADF Faces converters is a set of converters that extends the standard JSF converters. Since ADF Faces converters for input components operate on the client-side, errors in conversion can be caught at the client and thus avoid a round trip to the server. You can easily drag and drop ADF Faces converters into an input component.
ADF Faces validators also augment the standard JSF validators. ADF Faces validators can operate on both the client and server side. The client-side validators are in written JavaScript and validation errors caught on the client-side can be processed without a round-trip to the server.
You use ADF Faces converters to convert input from an input component into the format the model expects. A typical use case is using an input component for entering numbers and including a converter to convert the string entered by the user into a number for the model to process. For example, an af:inputText
component is used for a product Id attribute. You add the af:convertNumber
converter to the af:inputText
component to convert from String
to Number
. Another example is when you have an inputText component for an attribute for the cost of a product. You can use af:convertNumber
to convert the input string into the proper currency format.
You add validators to input components in the same way to validate the input string. For instance, you can add a validator to the af:inputText
component to check that the number of digits for the product Id are within the proper range. You add af:validateLength
to af:inputText
and set the minimum
and maximum
attributes to define the valid digit length.
You may find it helpful to understand other ADF Faces features before you implement your converters and validators. Following are links to other sections that may be useful.
For detailed information about how conversion and validation works in the JSF Lifecycle, see Using the JSF Lifecycle with ADF Faces .
ADF Faces lets you customize the detail portion of a conversion error message instead of a default message. For information about creating messages, see Displaying Tips, Messages, and Help.
Instead of entering values for attributes that take strings as values, you can use property files. These files allow you to manage translation of these strings. See Internationalizing and Localizing Pages.
The conversion and validation capabilities supported by ADF Faces are basically performed at different phases of JSF lifecycle. You can learn about the phase at which conversion and validation takes place in JSF lifecycle and also learn about what happens when the conversion or validation fails.
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 submittedValue
attribute. If the value requires conversion (for example, if it is displayed as a String
type but stored as a java.util.Date
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 Using the JSF Lifecycle with ADF Faces .
ADF Faces converters are used to convert input from an input component into the format the model expects. You can use JDeveloper to automatically inserts a converter to the UI component or you can manually insert a converter into a UI component.
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. 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 7-1 shows the converters provided by ADF Faces.
Table 7-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 7-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.
Before you begin:
It may be helpful to have an understanding of converters. See Adding Conversion.
You may also find it helpful to understand functionality that can be added using other ADF Faces features. See Additional Functionality for ADF Faces Converters and Validators.
To add ADF Faces converters that have tags:
Some converters support multiple patterns. 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. Note that not all converters support multiple patterns, although pattern matching is flexible and multiple patterns may not be needed.
The following example illustrates the use of a multiple pattern for the af:convertColor
tag in which "255-255-000" and "FFFF00" are both acceptable values.
<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>
The following example illustrates the use of an af:convertDateTime
tag in which "6/9/2007" and "2007/9/6" are both acceptable values.
<af:inputDate id="mdf5" value="2004/09/06" label="attached converter"> <af:convertDateTime pattern="yyyy/M/d" secondaryPattern="d/M/yyyy" /> </af:inputDate>
The following example illustrates an af:convertNumber
tag with the type
attribute set to currency
to accept "$78.57" and "$078.57" as values for conversion.
<af:inputText label="type=currency" value="#{validate.currency}" id="it1"> <af:convertNumber type="currency"/> </af:inputText>
Negative numbers are used in financial applications and have attribute level support for client-side conversion using the af:convertNumber
tag with the negativePrefix and negativeSuffix attributes to format negative values using specified prefix and suffix characters. For example, financial applications often format negative numbers using parentheses, where (99.00) represents the negative value for 99.00.
These attributes accomplish the same thing as specifying a converter pattern on the number converter, like #;(#)
, where the characters following the ";
" in the pattern indicate the negative pattern and the open and close parenthesis in the expression represent the negative prefix and suffix respectively for negative numbers. However, converter patterns are not processed on the client side and require a server roundtrip to format the output.
You can eliminate the need for a server roundtrip to perform the conversion using the af:convertNumber
tag. This client-side conversion will override any implied negative prefix/suffix using the converter pattern.
The following example illustrates an af:convertNumber
tag with the negativePrefix and negativeSuffix attributes set to "(
" and ")
" respectively to accept values a user might enter such as "-99.00" and convert them to "(99.00)". With this setting, the conversion is handled on the client as soon as the user tabs out of the text input.
<af:inputText label="type=number" id="it3"> <af:convertNumber negativePrefix="(" negativeSuffix=")" type="number"/> </af:inputText>
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 valid
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.
af:convertNumber
supports either server-side or client-side conversion. The converter first attempts to perform number formatting, parsing and conversions on the fly within the browser thereby eliminating the need to perform a server roundtrip for formatting input numbers. However, client conversion is skipped in the following situations:
If the pattern
attribute is specified. The converter will only run on the server.
If the input string contains more than 15 digits, which is the maximum precision supported by JavaScript number. The converter will only run on the server.
When af:convertNumber
displays an input value with more decimal digits than specified by maxFractionDigits
, by default it uses Java's HALF_EVEN
method to round off the value.
If you want af:convertNumber
to use a method other than HALF_EVEN
(such as HALF_UP
or FLOOR
), follow these tips:
To configure a particular instance of af:convertNumber
, set the roundingMode attribute to the desired value.
For example:
<af:convertNumber roundingMode="FLOOR" ... />
To configure all instances of af:convertNumber
in your application, add the rounding-mode attribute in trinidad-config.xml
and set it accordingly.
For example:
<trinidad-config xmlns="http://myfaces.apache.org/trinidad/config"> ... <rounding-mode>FLOOR</rounding-mode> </trinidad-config>
The value of roundingMode must be supported by Java's RoundingMode
. The value can be specified as a string in the .jspx
or the config file, or as an EL expression bound to a method that returns RoundingMode
type value.
Note:
Input value cannot be rounded at client-side unless theroundingMode
is set to half-up
. If roundingMode
is not set to half-up
, the input number is retained unaltered at client-side for a subsequent postback to perform the actual rounding on the server-side.For more information about RoundingMode
, see the Java API documentation.
You should use a four-digit year pattern with a date converter to avoid ambiguity. If you are using a two-digit year format as the pattern, all four-digit year values appear as two digit year values. For example, if you are using a two-digit year format (such as MM-dd-yy
) as the pattern, the date values 03-01-1910
and 03-01-2010
appear as 03-01-10
in the input field and could be interpreted incorrectly, though the server stores the correct year value.
Figure 7-1 shows the date values as they appear in the inputDate
component, with an outputText
component below that shows the original values stored on the server.
Figure 7-1 Date Converter With Two-Digit Year Format
If you are using a two-digit year format, all strings containing two-digit years will be resolved into a date within two-digit-year-start
and two-digit-year-start + 100
. For example, if two-digit-year-start
value is 1912
, the string 01/01/50
gets resolved to 01/01/1950
. To enter dates outside this range, the end user should enter a date with the full (four-digit) year. For information about two-digit-year-start
element and how to configure it, see What You May Need to Know About Elements in trinidad-config.xml.
Note:
While using a two-digit year format, two digit years will be placed in the range determined by two-digit-year-start
even if the user is editing an existing value.
For example, assuming two-digit-year-start
is set to 1950
(resolving year values to the range 1950
through 2050
) and the inputDate
component has value 03/01/1776
(displayed as 03/01/76
). If the user modifies the value to 03/01/77
, the new date would be 03/01/1977
, not 03/01/1777
as may be expected.
If you want to use a 12-hour format (for example, MM/dd/yyyy - hh:mm
) as the pattern with af:convertDateTime
, you should also include the am/pm placeholder in the pattern (for example, MM/dd/yyyy - hh:mm a
), otherwise the picker will not show am/pm options and the user will not be able to save the am/pm information. Figure 7-2 shows the inputDate
component with and without am/pm placeholders in their patterns.
Figure 7-2 Using AM/PM Placeholder With af:convertDateTime
If you want to display timezone information by including the timezone placeholder (z
) in the convertDateTime
pattern (example, yyyy-MM-dd hh:mm:ss a z
), note that the trinidad convertDateTime
overrides the display of the timezone names. When used in conjunction with inputText
or outputText
, the converter displays the timezone in the format GMT +
x
. When used in conjunction with inputDate
, the timezone is displayed from a selection of pre-configured display values, such as (UTC-08:00) Los Angeles - Pacific Time (PT)
.
You can create your own converters to meet your specific business needs. There are different procedures to create custom ADF Faces server-side converters or client-side converters.
Custom JSF converters run on the server-side using Java. ADF Faces Converters behave as JSF converters, but also support client-side conversion and validation using Javascript.
Creating a custom ADF Faces converter requires writing the business logic for the conversion and then registering the custom converter with the application. To use the custom ADF Faces converter, you use the f:converter
tag and set the custom ADF Faces converter as a property of that tag, or you can use the converter
attribute on the input component to bind to that converter.
To create a server-side converter, you must:
The ADF Framework supports client-side conversion and validation to minimize postbacks to the server. Client-side implementation is generally optional - if no client-side implementation is available, the framework will simply invoke the server-side converter during postback, just as in JSF.
Client-side implementation is required if the converter is used in conjunction with certain components which support client interaction without postback, such as inputNumberSlider
, inputNumberSpinbox
, and inputDate
. To determine if a client converter is required for a component, refer to the component's tagdoc.
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 client-side converter, you must:
ADF Faces converters are implemented on the server-side similarly to custom JSF converters.
If your application saves state on the client, the custom ADF Faces converter must implement the Serializable
interface or the StateHolder
interface, and the saveState(FacesContext)
and restoreState(FacesContext, Object)
methods of the StateHolder
interface. See the Javadoc for the StateHolder
interface of javax.faces.component
package, or visit http://docs.oracle.com/javaee/index.html
.
You should register the converter in the faces-config.xml
file.
Click Help or press F1 for additional help in registering the converter.
Write a client JavaScript version of the converter, passing relevant information to a constructor, as shown in the following example.
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){}
If errors are encountered, the client can throw a TrConverterException
exception to show a TrFacesMessage
error message.
The following example shows the signature for TrFacesMessage
.
/** * 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){ .. }
The following example shows the signature for TrFacesException
.
/** * 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){ .. }
Change the server converter to implement ClientConverter
interface, which indicates that the class supports client-side conversion. For information on the interface methods, see the ClientConverter
javadoc on http://myfaces.apache.org
.
The following example shows a custom javascript converter implementation for social security number.
function ssnGetAsString(value) { return value.substring(0,3) + '-' + value.substring(3,5) + '-' + value.substring(5); } function ssnGetAsObject(value) { if (!value) return (void 0); var len=value.length; var messageKey = SSNConverter.NOT; if (len < 9 ) messageKey = SSNConverter.SHORT; else if (len > 11) messageKey = SSNConverter.LONG; else if (len == 9) { if (!isNaN(value)) return value; } else if (len == 11 && value.charAt(3) == '-' && value.charAt(6) == '-') { var result = value.substring(0,3) + value.substring(4,6) + value.substring(7); if (!isNaN(result)) return result; } if (messageKey!=void(0) && this._messages!=void(0)) return new ConverterException(this._messages[messageKey]); return (void 0); } function SSNConverter(messages) { this._messages = messages; } SSNConverter.prototype = new Converter(); SSNConverter.prototype.getAsString = ssnGetAsString; SSNConverter.prototype.getAsObject = ssnGetAsObject; SSNConverter.SHORT = 'S'; SSNConverter.LONG = 'L'; SSNConverter.NOT = 'N';
The following example shows a custom Java class that implements server implementation for social security number. The details of the Java code has been removed from the getAsObject()
and getAsString()
methods.
package oracle.adfdemo.view.faces.convertValidate; import javax.faces.application.FacesMessage; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; import oracle.adf.view.faces.converter.ClientConverter; /** * <p>Social Security number converter.</p> * */ public class SSNConverter implements Converter, ClientConverter { public static final String CONVERTER_ID = "oracle.adfdemo.SSN"; public Object getAsObject( FacesContext context, UIComponent component, String value) { // some Java code ... } public String getAsString( FacesContext context, UIComponent component, Object value) { // some Java code ... } public String getClientConversion( FacesContext context, UIComponent component) { // in a real app the messages would be translated return "new SSNConverter({" + "S:'Value \"{0}\" in \"{1}\" is too short.'," + "L:'Value \"{0}\" in \"{1}\" is too long.'," + "N:'Value \"{0}\" in \"{1}\" " + "is not a social security number.'})"; } public String getClientScript( FacesContext context, UIComponent component) { // check if the script has already been returned this request Object scriptReturned = context.getExternalContext().getRequestMap().get(CONVERTER_ID); // if scriptReturned is null the script hasn't been returned yet if ( scriptReturned == null) { context.getExternalContext().getRequestMap().put(CONVERTER_ID, Boolean.TRUE); return _sSSNjs; } // if scriptReturned is not null, then script has already been returned, // so don't return it again. else return null; } private static final String _sSSNjs = "function ssnGetAsString(value)"+ "{return value.substring(0,3) + '-' " + "+ value.substring(3,5) + '-' + value.substring(5);}" + "function ssnGetAsObject(value)" + "{if (!value)return (void 0);" + "var len=value.length;"+ "var messageKey = SSNConverter.NOT;" + "if (len < 9 )"+ "messageKey = SSNConverter.SHORT;" + "else if (len > 11)"+ "messageKey = SSNConverter.LONG;" + "else if (len == 9)" + "{ if (!isNaN(value))" + "return value;" + "}" + "else if (len == 11 && value.charAt(3) == '-' && " + "value.charAt(6) == '-')" + "{" + "var result = value.substring(0,3) + value.substring(4,6) + " + "value.substring(7);"+ "if (!isNaN(result))"+ "return result;" + "}" + "if (messageKey!=void(0) && this._messages!=void(0))" + "return new ConverterException(this._messages[messageKey]);" + "return void(0);}" + "function SSNConverter(messages)" + "{this._messages = messages;}" + "SSNConverter.prototype = new Converter();" + "SSNConverter.prototype.getAsString = ssnGetAsString;" + "SSNConverter.prototype.getAsObject = ssnGetAsObject;" + "SSNConverter.SHORT = 'S';" + "SSNConverter.LONG = 'L';" + "SSNConverter.NOT = 'N';"; }
If a custom ADF Faces 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 the converter attribute to register the custom converter on a component, as shown in the following code:
<af:inputText value="#{myBean.myProperty}"/>
where myProperty
data type has the same type as the custom converter. Alternatively, you can bind your converter class to the converter attribute of the input component.
The af:clientConverter tag provides UI developers with a declarative alternative to register a custom client-only converter script, while still allowing the use of pre-programmed methods.
protected
attribute. The af:clientConverter
tag is useful in situations where the data formatting requirements needs be delayed to the point of page rendering where it is safe to format protected data.getAsString
and getAsObject
attributes to accept an inline JavaScript expression. The tag also offers the getAsStringMethod
and getAsObjectMethod
attributes to call a JavaScript method instead.af:clientConverter
tag:ADF Faces input components support validation capabilities. You can add validation for an input component using UI component attributes, Default ADF Faces validators, and Custom ADF Faces validators.
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 7-3 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.
Figure 7-3 Date Range Validator with Error Message
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. See 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 Using ADF Faces Validators. You can also create your own validators. For information about custom validators, see How to Create a Custom JSF Validator.
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. See 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. See 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. See Creating Custom JSF Validation.
When validation is added, validation errors can be displayed inline or in a popup window on the page. For information about displaying messages created by validation errors, see Displaying Tips, Messages, and Help.
Many ADF Faces UI components have attributes that provide simple validation. For example, the af:inputDate
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 Properties window, right-click the attribute name and choose Help.
ADF Faces Validators are separate classes that can be run on the server or client. Table 7-2 describes the validators and their logic.
Table 7-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 JSF f:validator
tag. For information about using custom validators, see Creating Custom JSF Validation.
To add ADF Faces validators:
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. The Update Model phase only happens when if there are no errors converting or validating. 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. If the component generates an error, ADF Faces automatically highlights the error. For instance, ADF Faces renders a red box around an inputText component when there is a validation error, as shown in Figure 7-4.
For information about adding error messages when a validation or conversion error occurs, see Displaying Hints and Error Messages for Validation and Conversion.
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. See Using the JSF Lifecycle with ADF Faces .
In ADF Faces, you can add your own validation logic to meet your specific business needs. You can create custom validation by adding a method that provides the required validation on a backing bean or by using JSF validators.
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.
Before you begin:
It may be helpful to have an understanding of custom JSF validation. See Creating Custom JSF Validation.
You may also find it helpful to understand functionality that can be added using other ADF Faces features. See Additional Functionality for ADF Faces Converters and Validators.
To add a backing bean validation method:
When you create a validation method, JDeveloper adds a skeleton method to the managed bean you selected. The following example shows the code JDeveloper generates.
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.
Before you begin:
It may be helpful to have an understanding of custom JSF validation. See Creating Custom JSF Validation.
You may also find it helpful to understand functionality that can be added using other ADF Faces features. See Additional Functionality for ADF Faces Converters and Validators.
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 information about these classes, refer to the Javadoc or visit http://docs.oracle.com/javaee/index.html
.
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 information about the Validator
interface and FacesMessage
, see the Javadoc for javax.faces.validate.ValidatorException
and javax.faces.application.FacesMessage
, or visit http://docs.oracle.com/javaee/index.html
.
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.
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.
The faces-config.xml
file is located in the View_Project
> WEB-INF
node in the JDeveloper Applications window.
In the editor window, click the Overview tab.
Choose Validators and click Add to add the validator information.
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.
The following example shows a validator in Java.
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 the following example.
function SSNValidator(summary, detail) { this._detail = detail; this._summary = summary; }
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.
The following example 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.
<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 > JSF > Validator.
With input component selected, in the Properties window, 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.
The following example shows the code on a JSF page for a validator using the f:validator
tag.
<af:inputText id="empnumber" required="true"> <f:validator validatorID="emValidator"/> </af:inputText>
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 executes logic against the value that is to be validated 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.