Imagine that you start with two database tables that look like the diagram at the right. The valid values for the AUTHORIZER column come from the set of USERID values in the SYS_USER table, and similarly for the valid values of the NEXT_AUTHORIZER column.
To create a panel or page in which the user sees the data for authorization rules, but sees the initials of the authorizer and next authorizer instead of their userid, you will need to create a SQL query that joins the AUTHORIZATION_RULE table to the SYS_USER table twice in order to join-in the initials for the authorizer and the initials for the next authorizer who typically would be two different users.
BC4J view objects give you the full power to use any possible SQL statements that you can conjure up, however complex. In this case, our SQL statement might look like this:
AuthUser.INITIALS AS AUTHUSERINITIALS,
NextAuthUser.INITIALS AS NEXTAUTHUSERINITIALS
FROM AUTHORIZATION_RULE Authorization,
WHERE (Authorization.AUTHORIZER = AuthUser.USERID)
AND (Authorization.NEXT_AUTHORIZER = NextAuthUser.USERID)
BC4J view objects give you a handy component to manage your SQL queries, and automatically handle delegating any data creations, updates, and deletes in the result set back to your business tier components that are related to the data queried in the view. To design a view object which does this delegation for you, you first need to have some underlying entity objects that represent your application business objects and which eventually can contain encapsulated business logic. These entity objects also manage the details of persisting changes make back to the database.
For example, you might create Java components at the left here to map to your base tables. The associations between BC4J entity object components can be inferred from the foreign keys during a reverse engineering, or created by hand using the JDeveloper BC4J wizards.
When you design your view object, you can indicate which entity objects have attributes that appear in the SQL queries select list. These are called entity "usages" since your view object is making use of one or more entity instances in each row of its result set. In the case of our query above, we'll have one entity usage for AuthorizationRule, and two separate entity usages related to SysUser: one representing the user who is the authorizer, and the other that represents the user who is the next authorizer. Just as we use SQL table aliases in the query above to help distinguish one from the other, BC4J view objects assign alias names to these entity usages.
A UML diagram of our AuthorizationView component, encapsulating the query above, might show these entity usages as contained shapes, and show their entity usage alias names for reference. In BC4J, one of the entity usages is known as the "primary entity usage", and often it is marked as being updateable. The second and subsequent entity usages are typically marked as participating for "Reference" information. This is controlled by a declarative setting that you can see on the "Entities" tab of the View Object editor.
When an entity usage participates for "Reference", then whenever the foreign key value in the updateable entity changes, the BC4J framework automatically keeps the corresponding reference values up to date. Practically speaking, in this example, it means that if the user updates the value of the "Authorizer" attribute from smuench to ssaviolo, then the corresponding authorizer's initials would update from "spm" to "ss" accordingly. The framework knows these are related through the associations that have been defined between the AuthorizationRule entity object, and the SysUser entity object. A similar automatic update occurs for an update of the NextAuthorizer attribute value.
You can experiment with this using the little sample project I've posted here called TwoReferenceEntities.zip
It has an application module that looks like the UML diagram at the left. The application module component contains an instance of our AuthorizationView view object named "Authorizations". (In the sample project the app module and VO instance names differ a little bit, from the diagram).
In order to try the sample, you'll need to:
- Make sure you have a connection named "scott" defined that connects to a SCOTT account
- Run the CreateTables.sql script to create the two sample tables and populate a few rows.
Then, if you select the application module in the JDeveloper navigator and select "Test..." from the right-mouse menu, you can test it using the Business Component Tester. By double-clicking on the view object instance name in the tree-view at the left, you will see the data in the tables. Try changing the values the Authorizer and NextAuthorizer fields to values like smuench, ssaviolo, or anorlin, and see how the corresponding initials synch up for you.
If you deploy the application module as an EJB session bean to your OC4J application server -- which you can do by selecting "Deploy" from the right-mouse menu of the BC4J deployment profile in the project -- you can use the tester to try out the application module in "remote" mode. You can do this by launching the BC4J tester and picking the "TestModule9iAS" configuration from the "Business Component Configuration Name:" poplist in the upper-right corner of the "Oracle Business Component Browser - Connect" dialog.
When you run in remote mode, after deploying the EJB, by default we operate in SYNC_LAZY mode instead of SYNC_IMMEDIATE mode (the default when not running remotely). In other words, when running remote, if you type a new Authorizer like "ssaviolo" when it was previously "smuench", then the initials won't update immediately.
However, if you click on the (Validate) icon in the tester, the initials will update since then we will make a round-trip to the server. The SYNC_LAZY mode is there to reduce network traffic between a remote client, and the middle-tier service component that it's talking to.
In the tester, if you select the AppModule icon in the tree, and then select "Properties" from the right-mouse, you'll see a table of properties and values. Next to the property "AppModule.SyncMode" you'll see "0" by default, which corresponds to SYNC_LAZY. If you double-click on the "0" value, a poplist will appear that will let you set it to SYNC_IMMEDIATE.
After doing this, close the properties dialog, and then go try again to change the Authorizer or NextAuthorizer user id. You'll see it now updates immediately. As a developer, you can make use of our reference feature, as well as our SYNC_LAZY or SYNC_IMMEDIATE modes, depending on your needs, without having to implement the details of how they work under the covers.
NOTE: The diagrams here are from our improved JDeveloper 10g UML and Database diagrammers in the production release candidate builds (still not ready for OTN yet, but getting there in the first quarter of 2004!)