Skip Headers

Oracle® Application Development Framework Developer's Guide 10g Release 3 (10.1.3) B25386-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# 12.4 Creating Custom Validation

You can add your own validation logic to meet your specific business needs. If you need custom logic for a component on a single page, you can create a custom validation method on the page's backing bean. Creating the method on a backing bean is also useful when you need validation to access other fields on the page. For example, if you have separate date fields (month, day, year) and each has its own validator, users will not get an error if they enter February 30, 2005. Instead, a backing bean for the page can contain a validation method that validates the entire date.

If you need 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.

## 12.4.1 How to Create a Custom Validation Method

When you need custom validation for a component on a single page, you can create a method that provides the needed validation on a backing bean.

To add a validation method:

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

2. In the visual editor, double-click the component to launch 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.

   Tip: If you have turned on automatic component binding, a method signature is automatically created for you on the page's backing bean. You need only to add the logic.

   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 needed validation logic. This logic should use `javax.faces.validator.ValidatorException` to throw the appropriate exceptions and `javax.faces.application.FacesMessage` to generate the corresponding error messages. For more information about the `Validator` interface and `FacesMessage`, see the Javadoc for `javax.faces.validator.Validator` and `javax.faces.application.FacesMessage`, or visit `http://java.sun.com/`.

## 12.4.2 What Happens When You Create a Validation Method

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

Example 12-4 Managed Bean Code for a Validation Method

    public void inputText_validator(FacesContext facesContext,
                                     UIComponent uiComponent, Object object) {
            // Add event code here...
    }

The SREdit page in the SRDemo application uses a validation method to ensure that the new date entered is not earlier than the original date. Example 12-5 shows the validation method on that page's backing bean.

Example 12-5 SREdit Date Validation Method

    public void assignedDateValidator(FacesContext facesContext,
                                      UIComponent uiComponent,
                                      Object newValue) {
        //The new value is passed into us
        Timestamp newAssignedDate = (Timestamp)newValue;

        //Get the start date for the SR which is already bound on this screen
        Timestamp requestDate =
            (Timestamp)ADFUtils.getBoundAttributeValue(getBindings(),
                                                       "requestDate");
        // Now compare and raise an error if the rule is broken
        if (newAssignedDate.compareTo(requestDate) < 0)
            {
              throw new ValidatorException(JSFUtils.getMessageFromBundle
               ("sredit.error.assignedBeforeStart", FacesMessage.SEVERITY_ERROR));
            }

     }

JDeveloper binds the validator attribute of the component to the backing bean's validation method using an EL expression. Example 12-6 shows the code JDeveloper adds to the SREdit page.

Example 12-6 JSF Code for a Custom Validation Method

    <af:selectInputDate value="#{bindings.assignedDate.inputValue}"
                        label="#{bindngs.assignedDate.label}"
                        ...
                        validator="#{backing_SREdit.assignedDateValidator}">

Tip: JDeveloper also adds an `af:validator` tag that is bound to the `validator` property of the associated binding. This allows the JSF lifecycle to access any ADF Model layer validation you may have set for the associated attribute. If you do not set any ADF Model layer validation, you may remove this binding.

When the form containing the input component is submitted, the method to which the validator attribute is bound is executed.

## 12.4.3 How to Create a Custom Validator

Creating a custom validator requires writing the business logic for the validation by overriding the `validate` method in an implementation of the `Validator` interface, and then registering the validator with the application. You can also create a tag for the validator, or you can use the `af:validator` tag and nest the custom validator as a property of 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`, and they support the `validate()` method.

Note: If the JavaScript `form.submit()` function is called, the ADF Faces support for client-side validation is bypassed. ADF Faces provides a `submitForm()` method that you can use instead, or you can use the `autoSubmit` attribute on ADF Faces input components.

To create a custom validator:

1. Create a Java class that implements the `javax.faces.validator.Validator` interface. The implementation must contain a constructor, a set of accessor methods for any attributes, and a `validate` method that overrides the validate method on the `Validator` interface.

   Alternatively, you can implement the `javax.faces.FormatValidator` interface, which has accessor methods for setting the `formatPatterns` attribute. This attribute specifies the acceptable patterns for the data entered into the input component. For example, if you want to validate the pattern of a credit card number, you create a `formatPatterns` attribute for the allowed patterns. The implementation must contain a constructor, a set of accessor methods for any attributes, and a `validate` method that overrides the `validate` method on the `Validator` interface.

   For both interfaces, the `validate` method takes the `FacesContext` instance, the component, and the data to be validated. For example:

       public void inputText_validator(FacesContext facesContext,
                                       UIComponent uiComponent,
                                       Object object) {
       ..
       }

   For more information about these classes, refer to the Javadoc or visit `http://java.sun.com/`.

2. Add the needed validation logic. This logic should use `javax.faces.validator.ValidatorException` to throw the appropriate exceptions and `javax.faces.application.FacesMessage` to generate the corresponding error messages. For more information about the `Validator` interface and `FacesMessage`, see the Javadoc for `javax.faces.validator.Validator` and `javax.faces.application.FacesMessage`, or visit http://java.sun.com/.

   Note: To allow the page author to configure the attributes from the page, you need to create a tag for the validator. See step 5 for more information. If you don't want the attributes configured on the page, then you must configure them in this implementation class.

3. Make your custom validator implementation serializable or implement `StateHolder`, and the `saveState(FacesContext)` and `restoreState(FacesContext, Object)` methods of `StateHolder` if your application saves state on the client. For more information, see the Javadoc for the `StateHolder` interface of `javax.faces.`component.

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.

5. Optionally create a tag for the validator that sets the attributes for the class. You create a tag by adding an entry for the tag in the application's tag library definition file (TLD). To do so:

   - Open or create a TLD for the application. For more information about creating a TLD, visit http://java.sun.com/.

   - Define the validator ID and class as registered in the `faces-config.xml` file.

   - Define any properties or attributes as registered in that configuration file.

   Note: If you do not create a tag for the validator, you must configure any attributes in the `Validator` implementation.

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 `oracle.adf.view.faces.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.

For a complete example of how to add client-side validation to a validator implementation, see "Client-Side Converters and Validators" in Development Guidelines for Oracle ADF Faces Applications.

To use the custom validators on a JSF page

To use a custom validator that has a tag on a JSF page, you need to manually nest it inside the component's tag. Example 12-7 shows a custom validator 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 12-7 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 validator without a custom tag, you must nest the validator's ID (as configured in `faces-config.xml` file) inside the `af:validator` tag. Follow these steps to do so.

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 validator tag.

Example 12-8 shows the code on a JSF page for a validator using the `validator` tag.

Example 12-8 A Custom Validator Bound to the Validator Attribute on a JSF Page

    <h:inputText id="empnumber" required="true">
      <f:Validator validatorID="emValidator"/>
    </h:inputText>

## 12.4.4 What Happens When You Use a Custom Validator

When you use a custom validator, the application accesses the validator class referenced in either the custom tag or the 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 validation fails, associated messages are placed in the message queue in `FacesContext`.