This chapter describes how to use validation rules in the ADF model layer of your Oracle ADF application.
This chapter contains the following sections:
In the model layer, ADF Model validation rules can be set for a binding's attribute on a particular page. When a user edits or enters data in a field and submits the form, the bound data is validated against any set rules and conditions. If validation fails, the application displays an error message.
Note that you don't need to add additional ADF Model validation if you have already set validation rules in the business domain layer of your entity objects. In an ADF Business Components-based Fusion web application, you won't need to use ADF Model validation unless you use data controls other than your application module data controls.
If your application uses data controls that are not based on ADF Business Components, you can use ADF Model layer validation to ensure the quality of user-entered data.
Best Practice:
Use business layer validation whenever possible. However, the following are examples of when you might need to use model layer validation:
When your business layer does not support declarative validation.
When you want to validate before an expensive roundtrip begins (for example, for a binding to a web service).
When you need to validate a form created using parameters (for example, using the executeWithParams
operation).
You can also use client-side validation for cases where you want to validate before a roundtrip to the server. For more information, see the "Adding Validation" section in Developing Web User Interfaces with Oracle ADF Faces.
Many of the declarative validation features available for ADF Business Components objects are also available at the model layer, should your application warrant the use of model-layer validation in addition to business-layer validation.
You may find it helpful to understand other ADF validation features before you use model layer validation. Following are links to other functionality that may be of interest.
When you use the ADF Business Components application module data control, you do not need to use model-layer validation. Consider defining all or most of your validation rules in the centralized, reusable, and easier to maintain entity objects of your business layer. For more information, see Chapter 11, "Defining Validation and Business Rules Declaratively."
Many of the declarative validation features available at the page level are also available at the bean level, which you would implement on the data control structure file. This can be very useful, because validation rules on the data control structure file apply to all usages of the data control. For information about implementing validation rules on the data control structure file, see the "Adding Business Logic to Data Controls" chapter in the Developing Applications with Oracle ADF Data Controls.
You can configure ADF Model validation for a binding's attributes on the page definition file. Validation rules in the model layer are executed for a binding's attribute on a particular page when the containing form is submitted.
You can optionally set the skipValidation
property to true
to bypass the ADF Model validation. You can set skipValidation
to skipDataControls
to validate the bound objects without validating the transaction. For example, set skipValidation
to skipDataControls
if you have a table action that opens a popup window to accept data entries and you want to allow the view layer to validate those entries before the commit on the table. The skipValidation
property can be found in the Properties window after you have selected the root node of the page definition file in the Structure window.
You set ADF Model validation on the page definition file. You define the validation rule, and set an error message to display when the rule is broken.
Table 18-1 describes the ADF Model validation rules that you can configure for a binding's attributes.
Table 18-1 ADF Model Validation Rules
Validator Rule Name | Description |
---|---|
Compare |
Compares the attribute's value with a literal value |
List |
Validates whether or not the value is in a list of values |
Range |
Validates whether or not the value is within a range of values |
Length |
Validates the value's character or byte size against a size and operand (such as greater than or equal to) |
Regular Expression |
Validates the data using Java regular expression syntax |
Required |
Validates whether or not a value exists for the attribute |
It may be helpful to have an understanding of the use of validation rules in the model layer. For more information, see Section 18.2, "Defining Validation Rules in the ADF Model Layer."
You may also find it helpful to understand additional functionality that can be added using other validation features. For more information, see Section 18.1.2, "Additional Functionality for ADF Model Layer Validation."
You will need to complete this task:
Create a component on the page. The component must have binding attributes.
To create an ADF Model validation rule:
In the Applications window, double-click the page definition that contains the binding for which you want to create a rule.
In the Structure window, select the attribute, list, or table binding.
In the Properties window, click the More dropdown menu and choose Edit Validation Rule.
In the Validation Rules Editor dialog, expand the binding node, select the attribute name, and click New.
In the Add Validation Rule dialog, select a validation rule and configure the rule as needed.
Click the Failure Handling tab and configure the message to display when the rule is broken.
When a user submits data, as long as the submitted value is a non-null value or a string value of at least one character, then all validators on a component are called one at a time. Because the f:validator
tag on the component is bound to the validator
property on the binding, any validation routines set on the model are accessed and executed.
The process then continues to the next component. If all validations are successful, the Update Model Values phase starts and a local value is used to update the model. If any validation fails, the current page is redisplayed along with an error message.
You can report errors using a custom error handler that extends the default DCErrorHandlerImpl
class. You are not required to write any code to register your custom exception handler class. Instead, you select the root node of the DataBindings.cpx
file in the Structure window, and then use the Properties window to set the ErrorHandlerClass
property to the fully qualified name of the error handler you want it to use.
Your custom error handler can contain the following overridable methods:
reportException()
: Called to report any exception that occurs. It can be overridden to analyze reported exceptions.
getDisplayMessage()
: Returns the message that will be reported to JSF for each error that occurs. Returning null
is the way your custom error handler signals that a given exception should not be reported to the client.
getDetailedDisplayMessage()
: Returns the detail portion of the message as a String
object or HTML that will be reported to JSF for each error that occurs. Returning null
is the way your custom error handler signals that a given exception should not be reported to the client.
skipException()
: Returns a boolean depending on whether you want to display each item from the nested exception in the final error list displayed to the user. This method override lets you implement logic to check for specifics exception types and, based on the business scenario, determine whether to display it in the list.
Example 18-1 illustrates a custom error handler that extends the DCErrorHandlerImpl
class and shows the override for the skipException()
method that is needed to skip exceptions that should not appear in the list displayed to the user.
Example 18-1 Custom Error Handler
package view.controller.fwkext; import java.sql.SQLIntegrityConstraintViolationException; import java.util.ArrayList; import java.util.List; import oracle.adf.model.binding.DCBindingContainer; import oracle.adf.model.binding.DCErrorHandlerImpl; import oracle.jbo.CSMessageBundle; import oracle.jbo.DMLConstraintException; import oracle.jbo.JboException; public class CustomErrorHandler extends DCErrorHandlerImpl { List<ExceptionMapper> exceptionMapperList = new ArrayList<ExceptionMapper>(); public CustomErrorHandler() { super(); exceptionMapperList.add(new DisableJboExceptionCodesMapper()); } public void reportException(DCBindingContainer bc, Exception ex) { for (ExceptionMapper mapper : exceptionMapperList) { if (mapper.canMapException(ex)) { ex = mapper.mapException(ex); } } super.reportException(bc, ex); } /** * If an exception is a RowValException or a TxnValException and they * have nested exceptions, then do not display it. This example shows * an implementation that skips the SQLIntegrityConstraintViolationException * from displaying in the error final list displayed to the user. */ @Override protected boolean skipException(Exception ex) { if (ex instanceof DMLConstraintException) { return false; } else if (ex instanceof SQLIntegrityConstraintViolationException) { return true; } return super.skipException(ex); } }
Your error handler class must have a default constructor that matches the name of the custom class. For example, if you create a custom handler class MyErrorHandler
, the exception error handler would invoke the default constructor, as shown in Example 18-2. Following this convention allows dynamic invocation by the class name alone.
Example 18-2 Default Constructor
ErrorHandlerClass="viewcontroller.MyErrorHandler" public MyErrorHandler() { super(); }
If you plan to customize and use the detail portion of a message, you can create a custom error handler and implement the getDetailedDisplayMessage
method to retrieve and process that message. The finalized message will be passed to the view layer to be integrated with other messages.
To customize the detail portion of a message:
Create a custom error handler class that extends the default DCErrorHandlerImpl
class.
In that class, override the getDetailedDisplayMessage
method that returns a DCErrorMessage
object.
Example 18-3 shows an implementation of the getDetailedDisplayMessage
method in the custom error handler class.
Example 18-3 Custom Error Handler Class with getDetailDisplayMessage Method
public final class MyErrorMessageHandler extends DCErrorHandlerImpl { public MyErrorMessageHandler (){ super(); } public DCErrorMessage getDetailedDisplayMessage(BindingContext ctx, RegionBinding ctr, Exception ex) { ... return new MyDCErrorMesssage(ctr, ex); } }
Create a custom class that implements the DCErrorMessage
interface. The class must implement the getHTMLText
method and the getText
method.
You will add code to the getHTMLText
method to perform the actual processing, but you must also implement getText
to satisfy the interface requirements.
In the getHTMLText
implementation, add code to create and process the error message.
getHTMLText
of getDetailedDisplayMessage
should return the finalized version of the error message as an HTML fragment that will be inserted into the HTML code of the page. For this reason, you should perform all necessary preprocessing on the text message before the message is returned by getDetailedDisplayMessage
. For instance, you may want to retrieve the localized version of the message or change the right-to-left ordering of the message before it is returned.
Example 18-4 shows an implementation of this interface.
Example 18-4 Implementing the DCErrorMessage Interface
public final class MyDCErrorMesssage implements DCErrorMessage { RegionBinding m_regionBinding; Exception m_ex; public MyDCErrorMesssage(RegionBinding ctr, Exception ex) { super(); this.m_regionBinding = ctr; this.m_ex = ex; } public String getText() { ... return "Message String"; } public String getHTMLText() { ... /* Add code to process the message, including localization */ /* and right-to-left directional requirements. */ /* Return the message as the finalized HTML fragment.*/ return "<html><b>error</b> message details</html>"; } }
To format the message using HTML tags, you must enclose the message within <html></html>
tags, as shown in the example. Note that only the following HTML tags are allowed in error messages:
<span>
<b>
<a>
<i>
<em>
<br>
<hr>
<li>
<ol>
<ul>
<p>
<tt>
<big>
<small>
<pre>
Oracle ADF constructs an instance of the custom error handler for each BindingContext
object that is created. Because Oracle ADF serializes simultaneous web requests from the same logical end-user session, multiple threads generally will not use the same error handler at the same time. However, to guarantee a thread-safe custom error handler, use the setProperty()
API on JboException
. This method stores in the exception objects themselves any hints you might need later during the phase when exceptions are translated to JSF FacesMessage
objects for display.