Application Modules Contain Instances of Data Controls (a.k.a View Objects)

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

Application Modules Contain Instances of Data Controls (a.k.a View Objects)

One widely misunderstood aspect of application modules is that, at runtime, they act as a container of  instances of view objects. They do not own the view objects outright. Conceptually, application modules are analogous to a UI panel, which at runtime contains instances of UI controls.

For example, a simple Swing dialog panel class named MyLoginPanel might contain the following instances of UI controls:

  • An instance of a JButton class, held in a member variable named okButton
  • A second instance of a JButton class, held in a member variable named cancelButton
  • An instance of a JLabel class, held in a member variable named usernamePrompt
  • A second instance of a JLabel class, held in a member variabled named passwordPrompt
  • An instance of a JTextField class, held in a member variable named usernameField
  • A second instance of a JTextField class, held in a member variable named usernameField

These instances are held in named member variables in the MyLoginPanel class.

Typically for a UI panel, you would create the instances of these member controls using code like:

  JButton okButton = new JButton(...);
  JButton cancelButton = new JButton(...);
  JLabel usernamePrompt = new JLabel(...);
  JLabel passwordPrompt = new JLabel(...);
JTextField usernameField = new JTextField(...);
JTextField passwordField = new JTextField(...);

However, if you were thinking of something a little more clever and metadata-driven, you might represent the definition of the panel using XML and represent the panel's named member variables that hold instances of controls using metadata like this:

<Panel name="MyLoginPanel">
<MemberControlUsage name="okButton" className="javax.swing.JButton"/>
<MemberControlUsage name="cancelButton" className="javax.swing.JButton"/>
<MemberControlUsage name="usernamePrompt" className="javax.swing.JLabel"/>
<MemberControlUsage name="passwordPrompt" className="javax.swing.JLabel"/>
<MemberControlUsage name="usernameField" className="javax.swing.JTextField"/>
<MemberControlUsage name="passwordField" className="javax.swing.JTextField"/>
</Panel>

Your metadata-driven "smart" panel class, that would interpret this metadata-driven way of representing the panel "container" and its contained member control instances, cannot contain hard-coded Java that is specific to the MyLoginPanel. Instead, it would be generic code that uses Java's Class.forName() to dynamically instantiate instances of the appropriate classes as indicated in the XML. To hold the instances of controls constructed this way, in your generic code you would probably use a HashTable or HashMap to store the instances of the controls you've dynamically constructed, keyed by their member name. So conceptually, at runtime your generic smartpanel class would:

  • Read the XML metadata
  • Create a HashTable
  • For each member control instance indicated declaratively in the metadata, dynamically instantiate an instance of the appropriate class, and remember the instance in your hashtable with a statement like:

    yourHashtable.put( memberNameFromXML, instanceOfDynamicallyInstantiatedControl );

So, after reading our example XML metadata above, the hashtable inside your generic smartpanel container object would end up looking like this:

Contents of Your Hashtable
("okButton", <instance of JButton>)
("cancelButton", <instance of JButton>)
("usernamePrompt", <instance of JLabel>)
("passwordPrompt", <instance of JLabel>)
("usernameField", <instance of JTextField>)
("passwordField", <instance of JTextField>)

Lacking the hard-coded getter methods like getOkButton() and getUsernameField() to programmatically access these instances of controls, your generic container "smart panel" class would likely have a method like:

JComponent findControl(String controlMemberName);

Which would allow you at runtime to access an instance of one of your declaratively-specified controls, using the handy member name that you assigned that instance at the time you "designed" your XML metadata for that panel. That code might look like this:

/*
* Find JButton with member name "okButton" and work with it.
*/
JButton buttonToWorkWith = (JButton)mySmartPanel.findControl("okButton"); // Have to cast to JButton
buttonToWorkWith.setEnabled(false);

The BC4J application module works exactly like this. The difference is that whereas our generic "smart panel" was a simple container of instances of UI controls, the BC4J application module is a simple container of instances of Data Controls called view objects, which give the client access to rowsets of data.

You use the "Data Model" panel in the application module wizard/editor to help you setup the XML metadata that declaratively defines what instances of data controls you want to be able to interact with at runtime, and what member names you'd like to be able to refer to them by at runtime.

So, an application module's metadata description looks something like this:

<ApplicationModule name="HRAppService">
  <ViewUsage name="LookupEmployees" ViewObjectName="com.yourcompany.someapp.EmployeeView"/>

  <ViewUsage name="DepartmentMaintenance" ViewObjectName="com.yourcompany.someapp.DeptView"/>
  <ViewUsage name="EmployeesInDepartment" ViewObjectName="com.yourcompany.someapp.EmployeeView"/>
<ViewLinkUsage name="SomeLinkName" ViewLinkObjectName="com.yourcompany.someapp.Dept2EmpLink"/>


</ApplicationModule>

and the BC4J framework provides the generic "smart" class that:

  • Reads the AppModule XML descriptor metadata
  • Creates a HashTable
  • For each member data control instance indicated declaratively in the metadata (view object, view link, or even nested instance of application modules if needed), it dynamically instantiates an instance of the appropriate class, and remembers the instance in the hashtable.
  • Provides you API's like:

    ViewObject findViewObject( String memberName );

so you can write code at runtime that works with these instances of the data controls (i.e. view objects) like:

/*
* Find ViewObject instance with member name "LookupEmployees" and work with it.
*/
ViewObject myViewToWorkWith = myAppModule.findViewObject("LookupEmployees");
myViewToWorkWith.setWhereClauseParam(0,"SMITH");
myViewToWorkWith.executeQuery();
while (myViewToWorkWith.hasNext()) {
Row currentRow = myViewToWorkWith.next();
/* Do something fun here with the resulting rows */
}



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