Appreciating the Entity Object
By Steve Muench
Declare and configure Oracle ADF entity objects instead of hand-coding Java.
As you've seen in my previous columns, an Oracle Application Development Framework (ADF) entity object represents a business domain entity such as an order, a part, a customer, or a service request. By creating a set of associated Oracle ADF entity objects that represents the full business domain model inside your J2EE applications, you can significantly boost developer productivity. Furthermore, the many built-in features of Oracle ADF entity objects reduce most common, arduous tasks to straightforward declarative choices, freeing you from having to write Java code. In this column, I highlight some of the capabilities you can leverage to make your development life easier.
Working with Entities and Tables
When you create an entity object, you have two basic options to choose from. You can reverse-engineer an entity object from an existing table, or you can create one from scratch. The Business Components from Tables wizard in Oracle JDeveloper lets you create a set of associated entity objects from one or more tables you select, and the Entity Object wizard enables you to create a single entity object from scratch. In either case, the appropriate wizard lets you name your entity objects and organize them into an appropriate Java package. You can also rename or move them to a different package later, by right-clicking on the entity object in the Application Navigator and choosing the appropriate menu option.
If you prefer to work visually, you can perform both of the above tasks directly from a diagram. To reverse-engineer an entity object, start by choosing File->New... and then choose the Business Tier->ADF Business Components category to start the Business Components Diagram wizard. This wizard creates an empty diagram, into which, using the Connection Navigator, you can drop one or more tables, which are then reverse-engineered to create entity objects. You can also drop a new entity object directly from the Component Palette to the diagram. You can perform tasks such as adding, deleting, and renaming attributes directly on the diagram. You can also double-click on an entity, in either the diagram or the Application Navigator, to edit its declarative properties with the Entity Object Editor.
If an entity object's underlying database table does not exist yet, Oracle JDeveloper can create one for you. To create the table for one or more entity objects, right-click on the package associated with the objects in the Application Navigator and choose Create Database Objects... from the context menu. You can also automatically synchronize your entity objects with changes made to the database schema, simply by choosing Synchronize with Database... from the same context menu.
Declarative XML: No Java Required
For each entity object you create, Oracle JDeveloper creates an XML component descriptor file in the directory corresponding to the package to which it belongs. This file is the key to all of the declarative features I discuss in this column. Using only the information contained in this file, Oracle ADF provides all of the insert, update, delete, and row-locking functionality you would expect from an Oracle Forms data block. If your entity object doesn't require custom Java code, this XML file is sufficient to describe the entity entirely with no other Java files needed. In this case, the XML file becomes the only required entity object artifact.
You can select the class types for which Oracle JDeveloper automatically generates Java classes, by choosing Tools->Preferences and selecting the Business Components category. By default, Oracle JDeveloper generates the entity object row class for all of your entities. If you disable autogeneration of this class, you can create the Java file later for any entity object, by selecting the Java panel in the Entity Object Editor and Generate Java Class in the Entity Object Class section.
All of the declarative settings that describe and control an entity object's runtime behavior reside in the entity's XML component descriptor file. You change the settings stored in this file by using the various panels of the Entity Object Editor.
On the Attributes panel, you create or delete the attributes that represent the data associated with an entity object. On the Tuning panel, you set options to make database operations more efficient when you create, modify, or delete multiple entities of the same type in a single transaction. On the Publish panel, you define events that your entity object will use to notify others of changes in its state. On the Subscribe panel, you allow your entity object to be notified when selected events from other entity objects fire. On the Authorization panel, you define role-based updatability permissions for any or all attributes. And on the Custom Properties panel, you define custom metadata that you can access at runtime on the entity.
One panel worthy of special attention is the Validation panel. Here, you can see and manage the declarative validation rules for the entity object and any of its attributes. The framework enforces entity-level validation rules when a user tries to commit pending changes or navigate among rows. It also enforces attribute-level validation rules when the user changes the value of a specified attribute. When specifying a validation rule, you supply an appropriate error message, and you can translate it into other languages, if required by your application. Oracle JDeveloper provides a set of common validation rules, including a method validator that invokes a custom validation method in your entity object's optional Java class. However, the most interesting aspect of validation rules is that Java-savvy team members can create libraries of additional rules to apply commonly occurring validations to your project, across all of your entity objects. Once a developer creates these additional rules, other team members can use them in the same way they use the built-in rules, by adding them to their entity objects and setting a few declarative properties that govern their runtime behavior.
The bulk of an entity object's declarative functionality is related to its attributes. As you might expect, you edit attribute settings by using the Entity Object Editor. In the editor, you select the desired attribute and an attribute panel appears where you can see and set properties such as name and Java datatype.
The Attributes panel also shows other properties related to the attribute's runtime behavior. The Mandatory property specifies whether a value is required. The Default field specifies a fixed default value for the attribute. The Updatable radio-button group determines when the user can set the attribute value ("always," "at creation time," or "never"). The Primary Key property indicates whether the attribute is part of the key that uniquely identifies the entity.
The Persistent property specifies whether an attribute value corresponds to a column in the underlying table or is just a transient value. If the attribute is persistent, you can specify the name of the underlying column in the Database Column area (in the lower half of the panel). You can also indicate its column type with precision and scale information, such as VARCHAR2(40) or NUMBER(4,2) . The framework enforces the maximum length, precision, and scale characteristics of the attribute value at runtime, using this information.
If you know that the underlying column value will be updated by a database trigger during an insert or update operation, you can select Refresh After Insert or Refresh After Update, respectively, to have the framework automatically keep the Java object in sync with the database row. These properties are particularly useful for creating sequence-assigned primary keys. Assuming that you have created a BEFORE INSERT FOR EACH ROW trigger on your table that performs the primary key assignment, the Refresh After Insert property will automatically become enabled if you specify a DBSequence datatype for this primary key attribute in the entity object. The framework also automatically handles sequence-assigned primary key issues when creating multilevel related entities (such as when you create new customer, new order, and new line items all in one transaction).
If an attribute's datatype is Number , String , or Date , you can use the History Column property to have the framework automatically maintain an attribute's value for auditing purposes. If you choose Version Number from the History Column drop-down list, Oracle ADF will automatically increment the value of the numeric attribute every time the object is updated. If you choose Created By, Created On, Modified By, or Modified On, the value will be updated with the current user's username or the current date, respectively, when the object is created or modified.
At runtime, the framework provides automatic "lost update" detection for entity objects, to ensure that a user doesn't unknowingly modify data that another user has updated and committed in the meantime. Typically the framework performs this check by comparing the values each persistent entity attribute originally had, at the time the underlying row was locked, with the corresponding column values in the database. However, if you already have a single column, such as a version number or a current date, that autoupdates whenever the row gets updated, you can identify that attribute as a change indicator. By doing so, you can optimize "lost update" detection to compare only that single attribute.
Labels, Tooltips, and Format Masks
In addition to the properties above, there is more information you might want to specify for your attributes. You can add special hints—such as format masks, descriptive labels, and extended tooltips—to specify information about how you want end users to see the data. To add these hints, select an attribute in the Entity Object Editor and choose the Control Hints tab to see all the hints you can set. The most common ones are Label Text, Tooltip Text, and Format Mask. By including this information here, you don't have to add it later when you build various user interfaces that display this data.
For example, consider the Hiredate attribute of an Employee entity object. You might set the label text to "Date of Hire," the tooltip text to "Date on which the employee was hired," and the format mask to "dd-MMM-yyyy." If you set the format mask, the date will display appropriately in any Swing or Web user interface you build with Oracle JDeveloper and ADF. Note that I did not say to specify the format mask as "DD-MON-YYYY." Because we work in the Java world when dealing with entity objects, the format masks follow Java platform standards instead of Oracle Database TO_CHAR() format standards. To find the proper Java format masks to use, you can simply search the Sun Microsystems JDK documentation for java.text.SimpleDateFormat or java.text.DecimalFormat .
If you develop applications for a multilingual user community, you'll also need to create locale-specific translations for your labels and tooltips. Oracle JDeveloper leverages Java's built-in internationalization features and stores the locale-dependent UI hints and validation rule error messages inside a message bundle file created for each component. For example, given an entity object named Employee , the corresponding message bundle would be named EmployeeImplMsgBundle.java. This message bundle contains keys and messages that are used at runtime, based on the user's current locale setting. You can create alternative versions of this file, with different suffixes for each locale your application supports, to provide translated versions of your labels, tooltips, and even format masks. For example, by creating a file called EmployeeImplMsgBundle_it_ch.java to support users who speak Italian and live in Switzerland, you can have the localized strings in that file be used automatically at runtime.
I've covered a lot of ground quickly in talking about Oracle ADF entity objects. Hopefully, this discussion has helped you understand the many ways in which ADF can improve your application development productivity, even before you write a line of Java code. For an example of a fully documented, end-to-end Oracle ADF Web application that illustrates many best practices for using Oracle ADF components, check out the Oracle ADF Toy Store demo on OTN.
Steve Muench is a consulting product manager for Oracle JDeveloper and an Oracle ACE. Since 1990, he has developed and supported Oracle tools and XML technologies and continues to evangelize them. Muench wrote Building Oracle XML Applications (O'Reilly Media, 2000) and shares tips and tricks on OTN (oracle.com/technetwork) and in his Dive into BC4J and ADF blog (radio.weblogs.com/0118231/).