As Published In
Oracle Magazine
September/October 2006

TECHNOLOGY: Frameworks


Harnessing the Active Data Model

By Steve Muench Oracle Employee ACE

Going beyond basic data access with custom service methods

One of the key benefits of using Oracle Application Development Framework (ADF) Business Components is its built-in support for an active data model. If you've worked with Oracle Forms or other 4GL tools, you'll find active data model support in Oracle JDeveloper using ADF Business Components to be very familiar. You design your application module by creating a set of master/detail view objects, and then you create a user interface by dragging and dropping data attributes or collections from the data model onto a visual page designer. At runtime, your application pages always reflect the current state of the data model, with no additional coding required. And you can modify the built-in data access functionality by adding custom methods to your application module, in much the same way you would add form-level procedures and functions in the Oracle Forms world.

In this column, I'll describe how the active data model works. I'll show you how to add custom service methods to application modules as well as how to use those custom methods when building a user interface.

Understanding the Active Data Model

Without ADF Business Components in your J2EE development toolkit, you'd likely spend a lot of time performing many tedious tasks when building user interfaces. These tasks include invoking methods of a business service to retrieve initial data, tracking the specific data that a client user interface (UI) has created or modified, passing those data changes back to service methods for validation and storage, and retrieving the data again to ensure that the display is up-to-date with any data changes made by server-side business logic. This "create, retrieve, update, delete, and save" cycle is very common in enterprise business applications, yet it takes a lot of work to develop from scratch.

ADF Business Components provide a more generic approach that can save you a lot of development time. With ADF Business Components, the application module implements a base set of generic service methods that enable an active data model. The client UI code works with the interfaces in the oracle.jbo package that provide a higher-level API to query, create, delete, modify, and save rows in the data model. In addition, when you build UI displays that use the Oracle ADF Model layer for declarative data binding, you usually don't need to write any client-side code at all to work with the active data model. Your displays are bound declaratively to view object instances in the data model as well as to any custom business service methods you create (in case you need to invoke other business service functions). When the client updates data, your ADF Business Components automatically validate and save the changes. And when custom business logic changes values in a row, your ADF Business Components automatically update the display with the latest information.

The two simple examples that follow show the benefits of using an active data model within an application: 

  • In a project management application, a manager assigns a task to an employee specified by that person's employee ID. At the moment the manager makes the assignment, business logic encapsulated in an entity object in the business domain layer automatically checks that the assigned employee ID is valid. Then another business rule updates the assigned date to the current date. After these changes are made, the user interface automatically shows the updated assigned date. 

  • In a page with a tree display that shows master/detail information for a given node, the user selects a node. A business service method in the application module then automatically performs a query to retrieve master/detail information. Finally, the display updates to reflect the new master/detail data.

If you don't use an active data model, you will have to write much more code in the client to handle the straight-forward, everyday CRUD (create, read, update, and delete)-style operations described earlier. By using an Oracle ADF application module to implement your business service, you can spend less time on plumbing and focus your time on the business logic to make the application work as your end users expect.

Adding a Custom Service Method

Whenever you have code in your business service layer that manipulates view objects, you should encapsulate that code within a custom method in your application module's Java class. Among the most common candidates for custom methods are code that configures view object properties to query the correct data to display, code that iterates over view object rows to return an aggregate calculation, and code that performs any kind of multistep procedural logic with one or more view objects.

By adopting this application best practice, you gain several important benefits. You can more easily create multiple client pages that call the same code, and you can easily improve your implementation later without affecting client interfaces. You can also simplify the work required to perform regression tests on your business service functions. Furthermore, you make it possible to invoke business functionality from within your pages declaratively (as well as programmatically).

To add a custom service method to an application module in Oracle JDeveloper, simply enable a custom Java class for your application module, navigate to it in the Java code editor, and type the Java code for a new public method into the application module's Java implementation class. Listing 1 shows a simple deleteCurrentEmpAndCommit() method that could be used in an HRService application module. This method accesses the current row in an EmpView view object instance in the data model and calls its remove() method to delete it. The deleteCurrentEmpAndCommit() method then accesses the current transaction and calls its commit() method to save the changes.

Code Listing 1: A simple custom service method in an application module 

public void deleteCurrentEmpAndCommit() { 
  Row empRow = getEmpView().getCurrentRow();
  if (empRow != null) {   
    empRow.remove();   
    getDBTransaction().commit(); 
  }
}

Although a custom application module method can accept arguments if necessary, note how easy it is for the code in custom methods to refer to a view object instance in the data model, using generated accessor methods such as getEmpView(). By calling the getCurrentRow() method on a view object (as shown in Listing 1), you can access the same current row for any view object the client user interface uses. As a result, there is often no need to pass parameters from the client if the goal is simply to pass values from current rows of other view object instances in the same application module's data model.

Publishing Custom Service Methods to Clients

When you add a public custom method to your application module class, you also need to include the method in the application module's client interface to let client UIs invoke it. In Oracle JDeveloper, to publish a method from your application module's custom Java class on the client interface, use the Client Interface panel of the Application Module Editor. Select one or more desired methods from the Available list, and click > to move them to the Selected list. Then click OK to save your changes.

When you publish custom service methods on the client interface, Oracle JDeveloper creates a Java interface with the same name as the application module in the common subpackage of your application module's package (as illustrated in Listing 2). For an application module named HRService in the oramag.frameworks.example package, this custom interface would be named HRService and reside in the oramag.frameworks.example.common package. The interface extends the base ApplicationModule interface in the oracle.jbo package, reflecting the fact that a client can access all of the base functionality your application module inherits from the ApplicationModuleImpl class.

Code Listing 2: An application module custom interface 

package oramag.frameworks.example.common;
import oracle.jbo.ApplicationModule;
public interface HRService extends ApplicationModule { 
  void deleteCurrentEmpAndCommit();
}

Whenever you add methods to or remove them from the Selected list in the Client Interface panel, the corresponding service interface file gets updated automatically. Oracle JDeveloper also generates a companion client proxy class that is used when you deploy your application module for access by a remote client. For the HRService application module in this example, the client proxy file is called HRServiceClient and is created in the oramag.frameworks.example.client subpackage.

You can include most custom methods in the client interface. For a method to be successfully added, all the types in its method signature must implement the java.io.Serializable interface and any checked exceptions must be JboException or a subclass. Your method can also throw any unchecked exception— java.lang.RuntimeException or subclass thereof—without any problems. If you add a method to the application module class but don't see it in the Available list, first check that it doesn't violate any of the rules above. If it seems that your added method should be legal, try recompiling the application module class and visiting the Application Module Editor again.

Calling a Custom Service Method

Once you've published a method on your application module's client interface you can invoke that method from a client, either declaratively or programmatically. As you would expect, the declarative approach is easy. Just drag the custom method from the Data Control palette and drop it onto a page in the visual editor. At runtime, when a user clicks the button associated with the method, Oracle ADF invokes the method automatically, passing as necessary any parameters whose values you can provide, by using declarative Expression Language (EL) expressions. 

 

Next Steps



 

READ more about Oracle JDeveloper 10g and Oracle ADF
oracle.com/technetwork/developer-tools/jdev/overview/index-094652.html
oracle.com/technetwork/developer-tools/jdev/index-090793.html
oracle.com/technetwork/developer-tools/jdev/documentation/index-098873.html

 DOWNLOAD Oracle JDeveloper 10g

 

To work programmatically with an application module's client interface, you can use an approach similar to the one in Listing 3. This code accesses the application module, casts it to the custom client interface, and then invokes the desired method. The code includes an ExampleBackingBean class with a JavaServer Faces (JSF) button event handler method named deleteButton_action(). The code uses the JSF FacesContext to create a ValueBinding to evaluate the EL expression for an HRService application module's data control provider. It casts the result to the custom HRService interface and then invokes the deleteCurrentEmpAndCommit() method. Finally, the code returns null, to indicate to the JSF runtime that it should remain on the same page. The active data model ensures that the page updates to reflect the deletion of the current row.

Code Listing 3: A simple custom service method in an application module 

package oramag.frameworks.example.backing;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import oramag.frameworks.example.common.HRService;
public class ExampleBackingBean {
  public String deleteButton_action() {
    String EL = "#{data.HRServiceDataControl.dataProvider}";
    FacesContext fc = FacesContext.getCurrentInstance();
    ValueBinding vb = fc.getApplication().createValueBinding(EL);
    HRService   svc = (HRService)vb.getValue(fc);
    svc.deleteCurrentEmpAndCommit();
    return null; // stay on same page.
  }
}

I've shown that to use an application module for your business service, you simply bind client UI controls such as fields, tables, and trees to the active view object instances in the application module's data model. Your UI display automatically updates to reflect any changes to the rows in the view object rowsets in that data model. The same benefit applies whether you're creating user interfaces for the Web or mobile devices using JSP or JSF or if you're creating desktop interfaces composed of windows and panels using Swing. The active data model capability in ADF Business Components automatically updates all changes, directly or indirectly, by your custom business service methods.

For more details about working with ADF Business Components, see the Oracle ADF Developer's Guide for Forms/4GL Developers manual on OTN.

 


Steve Muench is a consulting product manager for Oracle JDeveloper and an Oracle ACE. In his more than 16 years at Oracle, he has developed and supported Oracle tools and XML technologies and continues to evangelize them. Muench coauthored the Oracle ADF Developer's Guide for Forms/4GL Developers (Oracle, 2006) and wrote Building Oracle XML Applications (O'Reilly Media, 2000). He shares tips and tricks on OTN and in his Dive into BC4J and ADF blog.

 

Send us your comments