6 Validating and Converting Input

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:

6.1 Introduction to ADF Faces Converters and Validators

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."

6.2 Conversion, Validation, and the JSF Lifecycle

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."

6.3 Adding Conversion

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

ColorConverter

af:convertColor

Converts java.lang.String objects to java.awt.Color objects. You specify a set of color patterns as an attribute of the converter.

DateTimeConverter

af:convertDateTime

Converts java.lang.String objects to java.util.Date objects. You specify the pattern and style of the date as attributes of the converter.

NumberConverter

af:convertNumber

Converts java.lang.String objects to java.lang.Number objects. You specify the pattern and type of the number as attributes of the converter.


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.

Some oracle.jbo.domain datatypes are automatically converted. For some oracle.jbo.domain datatypes that are not handled automatically, you can add a oracle.jbo.domain converter to your component as described in Section 6.3.4, "How to Add oracle.jbo.domain Converters."

6.3.1 How to Add a Standard ADF Faces Converter

You can also manually insert a converter into a UI component.

To add ADF Faces converters that have tags:

  1. In the Structure window, right-click the component for which you would like to add a converter.

  2. 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.

  3. Choose a converter tag (for example, ConvertDateTime).

  4. 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 Standard ADF Faces 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."

6.3.2 How to Set Attributes on a Standard ADF Faces Converter

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.

Example 6-3 af:convertNumber Set to Currency Attribute

<af:inputText label="type=currency" value="#{validate.currency}">
  <af:convertNumber type="currency"/>
</af:inputText>

6.3.3 What Happens at Runtime

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.

6.3.4 How to Add oracle.jbo.domain Converters

For oracle.jbo.domain datatypes that are not automatically converted, you will need to reference the oracle.jbo.domain converter in your component. These converters are automatically registered and do not need a tag.

Table 6-2 lists the oracle.jbo.domain datatype converters.

Table 6-2 oracle.jbo.domain Datatype Converters

oracle.jbo.domain Converter Description

ordDomainConverter

Handles oracle.jbo.domain.ord datatypes

genericDomainConverter

Handles generic oracle.jbo.domain datatypes


To add a oracle.jbo.domain converter, you can add the converter to the converter attribute as shown in Example 6-4.

Example 6-4 Adding genericDomain Converter using the converter attribute

<af:inputText  ...  converter="oracle.genericDomain"/> 

Or you can add the f:converter tag and reference the converter using the converterId attribute as shown in Example 6-5.

Example 6-5 Adding genericDomain Converter using f:converter

<af:inputText ...
     <f:converter converterId="oracle.genericDomain"/>
</af:inputText> 

6.4 Creating Custom JSF Converters

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.

6.4.1 How to Create a Custom JSF Converter

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:

  1. 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 API documentation or visit http://download.oracle.com/docs/cd/E17410_01/javaee/index.html.

  2. 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 API documentation for javax.faces.convert.ConverterException and javax.faces.application.FacesMessage, or visit http://download.oracle.com/docs/cd/E17410_01/javaee/index.html.

  3. 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.

  4. 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-6 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-6 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-7 shows the signature for TrFacesMessage and Example 6-8 shows the signature for TrFacesException.

Example 6-7 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-8 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-9 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-9 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-10.

Example 6-10 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 the converter attribute to register the custom converter on a component, as shown in the following code:
<af:inputText value="#{myBean.myProperty}"/>

The myProperty data type has the same type as the custom converter.

6.4.2 What Happens When You Use a Custom Converter

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.

6.5 Adding Validation

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.

Figure 6-1 Date Range Validator with Error Message

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. 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."

6.5.1 How to Add Validation

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."

6.5.1.1 Adding ADF Faces Validation

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."

6.5.1.2 Using Validation Attributes

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.

6.5.1.3 Using ADF Faces Validators

ADF Faces Validators are separate classes that can be run on the server or client. Table 6-3 describes the validators and their logic.

Table 6-3 ADF Faces Validators

Validator Tag Name Description

ByteLengthValidator

af:validateByteLength

Validates the byte length of strings when encoded. The maximumLength attribute of inputText is similar, but it limits the number of characters that the user can enter.

DateRestrictionValidator

af:validateDateRestriction

Validates that the entered date is valid with some given restrictions.

DateTimeRangeValidator

af:validateDateTimeRange

Validates that the entered date is within a given range. You specify the range as attributes of the validator.

DoubleRangeValidator

af:validateDoubleRange

Validates that a component value is within a specified range. The value must be convertible to a floating-point type.

LengthValidator

af:validateLength

Validates that the length of a component value is within a specified range. The value must be of type java.lang.String.

LongRangeValidator

af:validateLongRange

Validates that a component value is within a specified range. The value must be any numeric type or String that can be converted to a long data type.

RegExpValidator

af:validateRegExp

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 Section 6.6, "Creating Custom JSF Validation."

To add ADF Faces validators:

  1. In the Structure window, right-click the component for which you would like to add a validator.

  2. 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.

  3. Choose a validator tag (for example, ValidateDateTimeRange).

  4. 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.

6.5.2 What Happens at Runtime

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.

Figure 6-2 Server-Side Validation Error

Server-side validation error for too many characters.

6.5.3 What You May Need to Know About Multiple Validators

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."

6.6 Creating Custom JSF Validation

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.

6.6.1 How to Create a Backing Bean Validation Method

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:

  1. Insert the component that will require validation into the JSF page.

  2. In the visual editor, double-click the component to open the Bind Validator Property dialog.

  3. 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.

  4. 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 API documentation for javax.faces.validator.ValidatorException and javax.faces.application.FacesMessage, or visit http://download.oracle.com/docs/cd/E17410_01/javaee/index.html.

6.6.2 What Happens When You Create a Backing Bean Validation Method

When you create a validation method, JDeveloper adds a skeleton method to the managed bean you selected. Example 6-11 shows the code JDeveloper generates.

Example 6-11 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.

6.6.3 How to Create a Custom JSF Validator

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:

  1. 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 API documentation or visit http://download.oracle.com/docs/cd/E17410_01/javaee/index.html.

  2. 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 API documentation for javax.faces.validate.ValidatorException and javax.faces.application.FacesMessage, or visit http://download.oracle.com/docs/cd/E17410_01/javaee/index.html.

  3. 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.

  4. 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:

  1. Write a JavaScript version of the validator, passing relevant information to a constructor.

  2. 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-12 shows a validator in Java.

    Example 6-12 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-13.

    Example 6-13 Client-side JavaScript Validator

    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.

    Example 6-14 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-14 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.

  1. 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.

  2. 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-15 shows the code on a JSF page for a validator using the f:validator tag.

Example 6-15 A Custom Validator Nested Within a Component on a JSF Page

<af:inputText id="empnumber" required="true">
  <f:validator validatorID="emValidator"/>
</af:inputText>

6.6.4 What Happens When You Use a Custom JSF Validator

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.