The ADF Business Components Active Data Model

Send me a mail
 Dive into Oracle ADF   Click to see the XML version of this web page.   (Updated: 2/3/2008; 9:26:40 PM.)
Tips and tricks from Steve Muench on Oracle ADF Framework and JDeveloper IDE

The ADF Business Components Active Data Model

One of the key simplifying benefits of ADF Business Components for the business tier is the support the application module component provides for an "active data model" of data collections. For developers coming from a Forms/4GL background, it works just like they are used to in their previous tools. Let me explain...

Rather than having to think of these collections as something you "pass back" from a method, your client simply binds to the active view object collections in the AM data model -- which in data control terminology are just data collection-valuedf properties of the data control. Anything that causes the values or rows in those data collections in the data model to change, including the work performed directly or indirectly by your custom method code, will result in automatically having the right data displayed in the page with no extra work on the developers part. Under the covers the application module component implements the SOA architecture with a base set of generic service methods to make this "active data model" feature just work for you, and the use of the ADF client interfaces (oracle.jbo.*) or the ADF binding layer on top of them hides any of the lower-level SOA-method calling complexity needed for most business application building use cases to get this useful functionality.

I call the AM data model an "active" data model because the ADF BC data control implements the complete set of rich, automatic data-change notification functionality provided by the data control interfaces. This means that when data is refreshed or modified in any way in your middle-tier service, the client automatically sees those changes with no developer effort to keep track of when you might need to refresh the data.

You can easily apply your Oracle Forms intuition to the way this works, and it's quite concious that the system is designed this way so that you can! The custom AM methods returning void are like form-level PL/SQL procedures conceptually. Any work that those procedures perform to any data in any block of the form, the UI that might currently be visible to the user just updates to reflect the current situation in the data blocks automatically without the developer having to pass that data back and forth. There was no need in Forms to write PL/SQL functions that returned record groups of the right structure that matched the structure of your data blocks or code that took the results of the function and "put it back" into the data blocks. The data blocks themselves are Oracle Forms' "active data model" idea. We've of course been able to add lots more rich reuse functionality in ADF BC over what Forms offers, but the basic idea of this active data model is conceptually similar.

Take a simple, concrete example of a business rule on an "Emp" entity object which has been coded to increase the employees salary by 100 if the "Job" attribute changes from "CLERK" to "ANALYST". This code lives in your ADF entity object so its business rules are enforced consistently no matter how many different application use cases you might implement that work with your employee business object. Imagine a screen (either Swing or JSF or JSP/Struts) that allows the operator to edit employee information. If the user edits the "Job" attribute in any view object based on the "Emp" EO such that the value changes from "CLERK" to "ANALYST", the user interface automatically updates to show the salary value that is 100 greater based on the business rules, which is the kind of UI most end users will expect reflecting the latest data. Without an active data model, you are forced to code your custom methods to follow a design pattern that always returns the data just updated back to the client (including returning all instances in a collection that might have been updated) so that the same kind of automatic refresh would occur.

So, in an ADF application coupled with a user interface (as opposed, perhaps, to a web service implemented using ADFBC) while you can, you don't really need to use custom methods that return collection types or specific "Row" objects. You have your pages with iterators that are bound to the view objects in the AM's "active" data model, and you can have your custom methods accept any necessary parameters, but just return void. Any changes to data, or to the current row, or to the rows in the view object's rowset (due to a re-execute of a query, for example) caused by any code directly or indirectly executed inside your custom method will "just be there" on the current page/panel in the view layer by virtue of the automatic data change notification.

Instead of writing lots of code in controller-layer backing beans that performs service-layer processing just write a custom AM method returning void and then expose that method on your AM's custom interface. Then, it shows up in the data control palette and you can drop it as a button or link onto your page. If you want this logic to be declaratively executed instead of requiring the user to press a button/link on the page, just create an "invokeAction" in the executeable section and define its "Refresh" and "RefreshCondition" properties to indicate what phase of the page processing lifecycle and under what boolean-valued EL condition you'd like it to be executed.

One common expression that we've added in JDeveloper/ADF 10.1.3 Production to cater to a lot of use cases is the adfFacesContext.postback boolean flag. Using a RefreshCondition of "#{adfFacesContext.postback == true}" or "#{adfFacesContext.postback == false}" (depending on whether you want something to happen when the page is handling a postback or not) you can handle a lot of use cases that used to require code without writing a line now.



© Copyright 2008 Steve Muench. Click here to send an email to the editor of this weblog.
Last update: 2/3/2008; 9:26:40 PM.