Skip Headers
Oracle® Application Development Framework Developer's Guide For Forms/4GL Developers
10g (10.1.3.1.0)

Part Number B25947-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

9.2 Understanding the Validation Cycle

Each entity row tracks whether or not its data is valid. When an existing entity row is retrieved from the database, the entity is assumed to be valid. When the first persistent attribute of an existing entity row is modified, or when a new entity row is created, the entity is marked invalid.

In addition, since a composed child entity row is considered an integral part of its composing parent entity object, any change to composed child entity rows causes the parent entity to be marked invalid.

When an entity is in an invalid state, the declarative validation you have configured and the programmatic validation rules you have implemented are evaluated again before the entity can be consider valid again. You can determine whether a given entity row is valid at runtime by calling the isValid() method on it.

9.2.1 Types of Entity Object Validation Rules

Entity object validation rules fall into two basic categories: attribute-level and entity-level.

9.2.1.1 Attribute-Level Validation Rules

Attribute-level validations are triggered for a particular entity object attribute when either the end user or program code attempts to modify the attribute's value. Since you cannot determine the order in which attributes will be set, attribute-level validation rules should be only used when the success or failure of the rule depends exclusively on the candidate value of that single attribute.

The following examples are attribute-level validations:

  • The value of the AssignedDate of a service request should not be a date in the past.

  • The ProdId attribute of a service request should represent an existing product.

9.2.1.2 Entity-Level Validation Rules

All other kinds of validation rules are entity-level validation rules. These are rules whose implementation requires considering two or more entity attributes, or possibly composed children entity rows, in order to determine the success or failure of the rule.

The following examples are attribute-level validations.

  • The value of the AssignedDate of a service request should be a data that comes after the RequestDate.

  • The ProdId attribute of a service request should represent an existing product.

Entity-level validation rules are triggered by calling the validate() method on a Row. This will occur when:

  • You call the method explicitly on the entity object

  • You call the method explicitly on a view row with an entity row part that is invalid

  • A view object's iterator calls the method on the current row in the view object before allowing the current row to change

  • Transaction commit processing validates an invalid entity in the pending changes list before proceeding with posting the changes to the database.

9.2.2 Understanding Commit Processing and Validation

Transaction commit processing happens in three basic phases:

  1. Ensure any invalid entity rows on the pending changes list are valid.

  2. Post the pending changes to the database by performing appropriate DML operations.

  3. Commit the transaction.

If you have business validation logic in your entity objects that executes queries or stored procedures that depends on seeing the posted changes in the SELECT statements they execute, they should be coded in the beforeCommit() method described in Section 9.6.3, "Validating Conditions Related to All Entities of a Given Type". This method fires after all DML has been applied so queries or stored procedures invoked from that method can "see" all of the pending changes that have been saved, but not yet committed.


Caution:

The transaction-level postChanges() method that exists to force the transaction to post unvalidated changes without committing them is not recommended for use in web applications unless you can guarantee that the transaction will definitely be committed or rolled-back during the same HTTP request. Failure to heed this advice can lead to strange results in an environment where both application modules and database connections can be pooled and shared serially by multiple different clients.

9.2.3 Avoiding Infinite Validation Cycles

If your validation rules contain code that updates attributes of the current entity or other entities, then the act of validating the entity can cause that or other entities to become invalid. As part of the transaction commit processing phase that attempts to validate all invalid entities in the pending changes list, the transaction will perform up to 10 passes on the pending changes list in an attempt to reach a state where all pending entity rows are valid.

If after 10 passes, there are still invalid entities in the list, you will see the following exception:

JBO-28200: Validation threshold limit reached. Invalid Entities still in cache

This is as sign that you need to debug your validation rule code to avoid inadvertently invalidating entities in a cyclic fashion.

9.2.4 What Happens When Validations Fail

When an entity object's validation rules throw exceptions, the exceptions are bundled and returned to the client. If the validation failures are thrown by methods you've overridden to handle events during the transaction postChanges processing, then the validation failures cause the transaction to rollback any database INSERT, UPDATE, or DELETE statements that might have been performed already during the current postChanges cycle.

9.2.5 Understanding Entity Objects Row States

When an entity row is in memory, it has an entity state that reflects the logical state of the row. Figure 9-2 illustrates the different entity row states and how an entity row can transition from one state to another. When a entity row is first created, its status is New. You can use the setNewRowState() method to mark the entity as being Initialized, which removes it from the transaction's list of pending changes until the user sets at least one of its attributes, at which time it returns to the New state. The Unmodified state reflects an entity that has been retrieved from the database and has not yet been modified. It is also the state that a New or Modified entity transitions too after the transaction successfully commits. During the transaction in which it is pending to be deleted, an Unmodified entity row transitions to the Deleted state. Finally, if a row that was New and got removed before the transaction commits, or Unmodified and got successfully deleted, the row transition to the Dead state.

Figure 9-2 Diagram of Entity Row States and Transitions

Image of diagram of entity row states and transitions

You can use the getEntityState() method to access the current state of an entity row in your business logic code.


Note:

If you use the postChanges() method to post pending changes without committing the transaction yet, the getPostState() method returns the entity's state from the point of view of it's being posted to the database or not. For example, a new entity row that has been inserted into the database due to your calling the postChanges()method programmatically — but which has not yet been committed — will have a different value for getPostState() and getEntityState(). The getPostState() method will reflect an "Unmodified" status since the new row has been posted, however the getEntityState() will still reflect that the entity is New in the current transaction.