19 Using Validation in the ADF Model Layer
This chapter contains the following sections:
About ADF Model Layer Validation
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 a Fusion web application based on ADF Business Components, you won't need to use ADF Model validation unless you use data controls other than your application module data control.
ADF Model Layer Validation Use Cases and Examples
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.
Additional Functionality for ADF Model 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 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.
Defining Validation Rules in the ADF Model Layer
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.
How to Add ADF Model Layer Validation
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 19-1 describes the ADF Model validation rules that you can configure for a binding's attributes.
Table 19-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 |
Before you begin:
It may be helpful to have an understanding of the use of validation rules in the model layer. For more information, see 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 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.
What Happens at Runtime: Model Validation Rules
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.
What You May Need to Know About Default Error Handling
When exceptions occur, the default behavior is to display only leaf-level errors in ADF Faces error dialogs. The default error handling mechanism for ADF Controller retrieves the list of exceptions from the page binding container and determines how to display each error. If the exception is not a JboException
, a Faces error message is displayed with the exception message.
If the exception is a JboException
, the error handling mechanism drills down recursively into nested exceptions, and displays a single Faces error message for each unique exception. However, if the exception has JboWarning.HIDE_DETAIL_EXCEPTIONS_HINT
, the error handling mechanism will not drill down into nested exceptions.
Additionally, the error handling mechanism retrieves a list of binding errors for each exception and displays a Faces error message for the component associated with the binding that reported the error.
Customizing Error Handling
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. Returningnull
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 aString
object or HTML that will be reported to JSF for each error that occurs. Returningnull
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.
The following example shows 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.
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 the following example. Following this convention allows dynamic invocation by the class name alone.
ErrorHandlerClass="viewcontroller.MyErrorHandler" public MyErrorHandler() { super(); }
How to Customize the Detail Portion of a Message
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:
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>
How to Display an Informational Message from a Custom Error Handler
You can use an error handler to display an informative message in response to a warning in an application using custom validation in the ADF Model layer. For applications that use model layer validation, you need to use a custom error handler at the application CPX level, for all errors and warnings.
Before you begin:
It may be helpful to have an understanding of how custom validation in the model layer works. For more information, see Customizing Error Handling.
You may also find it helpful to understand additional functionality that can be added using other validation features. For more information, see Additional Functionality for ADF Model Layer Validation.
You must also launch JDeveloper, and open the application to which you want to add the custom error handler.
To display an informational message
How to Write an Error Handler to Deal with Multiple Threads
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.