Most Commonly Used Methods in ADF Business Components Oracle JDeveloper Tip

Most Commonly Used Methods in ADF Business Components

Author: Steve Muench, ADF Development Team
Date: January 19, 2006
Revision 1.9 (Revision History)

Abstract

This paper provides a high-level description of the key ADF Business Components classes in the Oracle Application Development Framework, summarizing the methods that ADF developers write, call, and override most frequently.


Contents

        Overview
        Logical Architecture of Services Built with ADF Business Components
        Most Commonly Used Methods in the Client Tier
                ApplicationModule Interface
                Transaction Interface
                ViewObject Interface
                RowSet Interface
                RowSetIterator Interface
                Row Interface
                StructureDef Interface
                AttributeDef Interface
                AttributeHints Interface
        Most Commonly Used Methods In the Business Service Tier
                Controlling Custom Java Files For Your Components
                ApplicationModuleImpl Class
                DBTransactionImpl2 Class
                EntityImpl Class
                EntityDefImpl Class
                ViewObjectImpl Class
                ViewRowImpl Class
                Setting Up Your Own Layer of Framework Base Classes
        Conclusion

Overview

Service-oriented J2EE Applications built using the ADF framework encapsulate their business logic into one or more business services. Clients access these business services either as web services or, when the client is a user interface, using the ADF data-binding layer that implements the Data Controls and Bindings from JSR-227. The data controls abstract the back-end business service implementations and binding objects link front-end user interface controls in a declarative way to back-end data.

ADF supports business services implemented as simple Java objects, web services, EJB Session beans, and framework-based Java objects that inherit built-in functionality from the ADF Business Components base classes. These ADF Business Components are business-tier building-block classes, and related design-time extensions to JDeveloper, that give you a prescriptive architecture for building richly-functional and cleanly layered J2EE business services with great performance. This paper offers a high-level description of the key components that comprise ADF Business Components, and provides a summary of the methods that developers leveraging ADF BC base classes write, call, and override most frequently while building their J2EE-compliant business services.

Logical Architecture of Services Built with ADF Business Components

You can use business services you build with ADF Business Components in one of three ways:

  1. As lightweight local Java service classes,
  2. As EJB session beans, or
  3. As stateless web services

In all three cases, there is a clean separation between the client tier code that invokes the service and the business service tier where the service's implementation details reside.

With the J2EE web service option, your web service client interacts with the service using a web service proxy class generated by the client tool environment based on the service's WSDL service description. The methods that appear on your web service are the custom methods you've written on your business service component.

With the local Java service class and the EJB session bean options, your Java client code interacts with either the base ADF component interfaces or custom component interfaces that JDeveloper 10g generates for you automatically after indicating which custom methods should appear on the component's client interface.

Since ADF adopts this best-practice approach of having your client work with interfaces instead of directly with implementation classes, it offers the additional benefit of allowing you to change between deploying your business service as a local Java class or an EJB session bean without changing your client code. Along with the custom service interface, JDeveloper generates appropriate client-side proxy implementation classes that implement your custom interface. As such, it's an implementation detail you don't need to worry about yourself. With either 2-tier or 3-tier deployment of your application modules, thing just work...which is nice.

Figure 1 shows the relationships between the key components in the Oracle Application Development Framework. The dashed vertical line in the diagram represents the clean separation of component interfaces that are available on the client, and which ones are only available in the business tier implementation.

Relationship Between Key ADF Business Components Classes
Figure 1: Relationship Between Key ADF Business Components Classes

Whenever you deploy an ADF Business Components project using a Business Components deployment profile in JDeveloper 10g, two separate JAR files get created, further emphasizing this logical separation between business tier and client tier:

  • YourProjectNameCSMT.jar

    This archive contains all of the implementation classes that comprise your project's business service application module components and other ADF BC components that your application modules use. We picked the MT suffix in the name to represent Middle Tier. When deploying your application module as an EJB Session Bean, this JAR file lives on the EJB middle tier. It never is downloaded to the remote client.

  • YourProjectNameCSCommon.jar

    This archive contains any custom client interfaces, generated custom remote client proxy classes, custom domains, and message bundles that are accessible by both the client-tier and the business service tier. We picked the suffix Common in the archive name to remind you that this jar is common to both tiers. This file is generally relatively quite small compared to the middle-tier JAR.

The following sections briefly explain each component and give tips about the methods J2EE developers using ADF Business Components will use most frequently for each kind of component.

Most Commonly Used Methods in the Client Tier

All of the interfaces described in this section are designed for use by client-layer code and are part of the oracle.jbo.* package.


NOTE:

The corresponding implementation classes for these oracle.jbo.* interfaces are consciously designed to not be directly accessed by client code. As we'll see in the Most Commonly Used Methods In the Business Service Tier section below, the implementation classes live in the oracle.jbo.server.* package and generally have the suffix Impl in their name to help remind you not to using them in your client-layer code.


ApplicationModule Interface

The ApplicationModule See Javadoc for ApplicationModule is a business service component that acts as a transactional container for other ADF components and coordinates with them to implement a number of J2EE design patterns important to business application developers. These design pattern implementations enable your client code to work easily with updateable collections of value objects, based on fast-lane reader SQL queries that retrieve only the data needed by the client, in the way the client wants to view it. Changes made to these value objects are automatically coordinated with your persistent business domain objects in the business service tier to enforce business rules consistently and save changes back to the database.

If you want to... Call this ApplicationModule interface method...
Access an existing view object instance by name findViewObject()
Creating a new view object instance from an existing definition createViewObject()
Creating a new view object instance from a SQL Statement createViewObjectFromQueryStmt()

Note:

This incurs runtime overhead to describe the "shape" of the dynamic query's SELECT list. We recommend using this only when you cannot know the SELECT list for the query at design-time. Furthermore, if you are creating the dynamic query based on some kind of custom runtime repository, you can follow this tip to create (both read-only and updateable) dynamic view objects without the runtime-describe overhead with a little more work. If only the WHERE needs to be dynamic, create the view object at design time, then set the where clause dynamically as needed using ViewObject API's.

Access a nested application module instance by name findApplicationModule()
Create a new nested application module instance from an existing definition createApplicationModule()
Find a view object instance in a nested application module findViewObject()

Note:

To find an instance of a view object belonging to a nested application module you use a dot notation nestedAMInstanceName.VOInstanceName

Accessing the current transaction object getTransaction()

In addition to generic ApplicationModule access, JDeveloper 10g can generate you a custom YourApplicationModuleName interface containing service-level custom methods that you've chosen to expose to the client. You do this by visiting the Client Interface tab of the Application Module editor, and shuttling the methods you'd like to appear in your client interface into the Selected list. JDeveloper will also generate an appropriate YourApplicationModuleNameClient client proxy implementation class that is used automatically by your remote client in the case that you deploy your application module as an EJB Session Bean or whenever you use your application module in Batch Mode.

Transaction Interface

The Transaction See Javadoc for Transaction interface exposes methods allowing the client to manage pending changes in the current transaction.

If you want to... Call this Transaction interface method...
Commit pending changes commit()
Rollback pending changes rollback()
Execute a one-time database command or block of PL/SQL executeCommand()

Note:

Commands that require retrieving OUT parameters, that will be executed more than once, or that could benefit by using bind variables should not use this method. Instead, expose a custom method on your application module class as described here.

Validate all pending invalid changes in the transaction validate()
Change the default locking mode setLockingMode()

Note:

You can set the locking mode in your configuration by setting the property jbo.locking.mode to one of the four supported values: none, optimistic, pessimistic, optupdate. If you don't explicitly set it, it will default to pessimistic. For web applications, we recommend using optimistic or optupdate modes.

Decide whether to use bundled exception reporting mode or not. setBundledExceptionMode()

Note:

ADF controller layer support sets this parameter to true automatically for web applications.

Decide whether entity caches will be cleared upon a successful commit of the transaction. setClearCacheOnCommit()

Note:

Default is false

Decide whether entity caches will be cleared upon a rollback of the transaction. setClearCacheOnRollback()

Note:

Default is true

Clear the entity cache for a specific entity object. clearEntityCache()

ViewObject Interface

A ViewObject See Javadoc for ViewObject encapsulates a database query and simplifies working with the RowSet of results it produces. You use view objects to project, filter, join, or sort business data using SQL from one or more tables into exactly the format that the user should see it on the page or panel. You can create "master/detail" hierarchies of any level of depth or complexity by connecting view objects together using view links. View objects can produce read-only query results, or by associating them with one ore more entity objects at design time, can be fully updateable. Updateable view objects can support insertion, modification, and deletion of rows in the result collection, with automatic delegation to the correct business domain objects.

Every ViewObject aggregates a "default rowset" for simplifying the 90% of use cases where you work with a single RowSet of results for the ViewObject's query. A ViewObject implements all the methods on the RowSet interface by delegating them to this default RowSet. That means you can invoke any RowSet methods on any ViewObject as well.

Every ViewObject implements the StructureDef interface to provide information about the number and types of attributes in a row of its rowsets. So you can call StructureDef methods right on any view object.

If you want to... Call this ViewObject interface method...
Set an additional runtime WHERE clause on the rowset setWhereClause()

Note:

This WHERE clause augments any WHERE clause specified at design time in the base view object. It does not replace it.

Set a dynamic ORDER BY clause setOrderByClause()
Create a Query-by-Example criteria collection createViewCriteria()

Note:

You then create one or more ViewCriteriaRow objects using the createViewCriteriaRow() method on the ViewCriteria object you created. Then, you add() these view criteria rows to the view criteria collection and apply the criteria using the method below.

Apply a Query-by-Example criteria collection applyViewCriteria()
Set a query optimizer hint setQueryOptimizerHint()
Access the attribute definitions for the key attributes in the view object getKeyAttributeDefs()
Add a dynamic attribute to rows in this view object's rowsets addDynamicAttribute()
Clear all rowsets produced by a view object clearCache()
Remove view object instance an its resources remove()
Set an upper limit on the number of rows that the view object will attempt to fetch from the database. setMaxFetchSize()

Note:

Default is -1 which means to impose no limit on how many rows would be retrieved from the database if you iterate through them all. By default they are fetched lazily as you iterate through them.

In addition to generic ViewObject access, JDeveloper 10g can generate you a custom YourViewObjectName interface containing view-object level custom methods that you've chosen to expose to the client. You do this by visiting the Client Interface tab of the View Object editor, and shuttling the methods you'd like to appear in your client interface into the Selected list. JDeveloper will also generate an appropriate YourViewObjectNameClient client proxy implementation class that is used automatically by your remote client in the case that you deploy your application module as an EJB Session Bean or whenever you use your application module in Batch Mode.

RowSet Interface

A RowSet See Javadoc for RowSet is a set of rows, typically produced by executing a ViewObject's query.

Every RowSet aggregates a "default rowset iterator" for simplifying the 90% of use cases where you only need a single iterator over the rowset. A RowSet implements all the methods on the RowSetIterator interface by delegating them to this default RowSetIterator. This means you can invoke any RowSetIterator method on any RowSet (or ViewObject, since it implements RowSet as well for its default RowSet).

If you want to... Call this RowSet interface method...
Set a where clause bind variable value setWhereClauseParam()

Note:

Bind variable ordinal positions are zero-based

Avoid view object row caching if data is being read only once setForwardOnly()
Force a rowset's query to be (re)executed executeQuery()
Estimate the number of rows in a view object's query result getEstimatedRowCount()
Produce XML document for rows in View Object rowset writeXML()
Process all rows from an incoming XML document readXML()
Set whether rowset will automatically see new rows based on the same entity object created through other rowsets setAssociationConsistent()
Create secondary iterator to use for programmatic iteration createRowSetIterator()

Note:

If you plan to find and use the secondary iterator by name later, then pass in a string name as the argument, otherwise pass null for the name and make sure to close the iterator when done iterating by calling its closeRowSetIterator() method.

RowSetIterator Interface

A RowSetIterator See Javadoc for RowSetIterator is an iterator over the rows in a RowSet. By default it allows you to iterate both forward and backward through the rows.

If you want to... Call this RowSetIterator interface method...
Get the first row of the iterator's rowset first()
Test whether there are more rows to iterate hasNext()
Get the next row of iterator's rowset next()
Find row in this iterator's rowset with a given Key value findByKey()

Note:

It's important that the Key object that you pass to findByKey be created using the exact same datatypes as the attributes that comprise the key of the rows in the view object you're working with.

Create a new row to populate for insertion createRow()

Note:

The new row will already have default values set for attributes which either have a static default value supplied at the entity object or view object level, or if the values have been populated in an overridden create() method of the underlying entity object(s).

Create a view row with an initial set of foreign key and/or discriminator attribute values createAndInitRow()

Note:

You use this method when working with view objects that can return one of a "family" of entity object subtypes. By passing in the correct discriminator attribute value in the call to create the row, the framework can create you the correct matching entity object subtype underneath.

Insert a new row into the iterator's rowset insertRow()

Note:

It's a good habit to always immediately insert a newly created row into the rowset. That way you will avoid a common gotcha of creating the row but forgetting to insert it into the rowset.

Get the last row of the iterator's rowset last()
Get the previous row of the iterator's rowset previous()
Reset the current row pointer to the slot before the first row reset()
Close an iterator when done iterating closeRowSetIterator()
Set a given row to be the current row setCurrentRow()
Remove the current row removeCurrentRow()
Remove the current row to later insert it at a different location in the same iterator. removeCurrentRowAndRetain()
Remove the current row from the current collection but do not remove it from the transaction. removeCurrentRowFromCollection()
Set/change the number of rows in the range (a "page" of rows the user can see) setRangeSize()
Scroll to view the Nth page of rows (1-based) scrollToRangePage()
Scroll to view the range of rows starting with row number N scrollRangeTo()
Set row number N in the range to be the current row setCurrentRowAtRangeIndex()
Get all rows in the range as a Row array getAllRowsInRange()

Row Interface

A Row See Javadoc for Row is generic value object. It contains attributes appropriate in name and Java type for the ViewObject that it's related to.

If you want to... Call this Row interface method...
Get the value of an attribute by name getAttribute()
Set the value of an attribute by name setAttribute()
Produce an XML document for a single row writeXML()
Eagerly validate a row validate()
Read row attribute values from XML readXML()
Remove the row remove()
Flag a newly created row as temporary (until updated again) setNewRowState(Row.STATUS_INITIALIZED)
Retrieve the attribute structure definition information for a row getStructureDef()
Get the Key object for a row getKey()

In addition to generic Row access, JDeveloper 10g can generate you a custom YourViewObjectNameRow interface containing your type-safe attribute getter and setter methods, as well as any desired row-level custom methods that you've chosen to expose to the client. You do this by visiting the Client Row Interface tab of the View Object editor, and shuttling the methods you'd like to appear in your client interface into the Selected list. JDeveloper will also generate an appropriate YourViewObjectNameRowClient client proxy implementation class that is used automatically by your remote client in the case that you deploy your application module as an EJB Session Bean or whenever you use your application module in Batch Mode.

StructureDef Interface

A StructureDef See Javadoc for StructureDef is an interface that provides access to runtime metadata about the structure of a Row.

In addition, for convenience every ViewObject implements the StructureDef interface as well, providing access to metadata about the attributes in the resulting view rows that its query will produce.

If you want to... Call this StructureDef interface method...
Access attribute definitions for all attributes in the view object row getAttributeDefs()
Find an attribute definition by name findAttributeDef()
Get attribute definition by index getAttributeDef()
Get number of attributes in a row getAttributeCount()

AttributeDef Interface

An AttributeDef See Javadoc for AttributeDef provides attribute definition information for any attribute of a View Object row or Entity Object instance like attribute name, Java type, and SQL type. It also provides access to custom attribute-specific metadata properties that can be inspected by generic code you write, as well as UI hints that can assist in rendering an appropriate user interface display for the attribute and its value.

If you want to... Call this AttributeDef interface method...
Get the Java type of the attribute getJavaType()
Get the SQL type of the attribute getSQLType()

Note:

The int value corresponds to constants in the JDBC class java.sql.Types

Determine the kind of attribute getAttributeKind()

Note:

If it's a simple attribute, it returns one of the constants ATTR_PERSISTENT, ATTR_SQL_DERIVED, ATTR_TRANSIENT, ATTR_DYNAMIC, ATTR_ENTITY_DERIVED. If it is an 1-to-1 or many-to-1 association/viewlink accessor it returns ATTR_ASSOCIATED_ROW. If it is an 1-to-many or many-to-many association/viewlink accessor it returns ATTR_ASSOCIATED_ROWITERATOR

Get the Java type of elements contained in an Array-valued attribute getElemJavaType()
Get the SQL type of elements contained in an Array-valued attribute getElemSQLType()
Get the name of the attribute getName()
Get the index position of the attribute getIndex()
Get the precision of a numeric attribute or the maximum length of a String attribute getPrecision()
Get the scale of a numeric attribute getScale()
Get the underlying column name corresponding to the attribute getColumnNameForQuery()
Get attribute-specific custom property values getProperty(), getProperties()
Get the UI AttributeHints object for the attribute getUIHelper()
Test whether the attribute is mandatory isMandatory()
Test whether the attribute is queriable isQueriable()
Test whether the attribute is part of the primary key for the row isPrimaryKey()

AttributeHints Interface

The AttributeHints See Javadoc for AttributeHints interface related to an attribute exposes UI hint information that attribute that you can use to render an appropriate user interface display for the attribute and its value.

If you want to... Call this AttributeHints interface method...
Get the UI label for the attribute getLabel()
Get the tool tip for the attribute getTooltip()
Get the formatted value of the attribute, using any format mask supplied getFormattedAttribute()
Get the display hint for the attribute getDisplayHint()

Note:

Will have a String value of either Display or Hide.

Get the preferred control type for the attribute getControlType()
Parse a formatted string value using any format mask supplied for the attribute parseFormattedAttribute()

Most Commonly Used Methods In the Business Service Tier

The implementation classes corresponding to the oracle.jbo.* interfaces described above are consciously designed to not be directly accessed by client code. They live in a different package named oracle.jbo.server.* and have the Impl suffix in their name to help remind you not to using them in your client-layer code.

In your business service tier implementation code, you can use any of the same methods that are available to clients above, but in addition you can also:

  • Safely cast any oracle.jbo.* interface to its oracle.jbo.server.* package implementation class and use any methods on that Impl class as well.
  • Override any of the base framework implementation class' public or protected methods to augment or change its default functionality by writing custom code in your component subclass before or after calling super.methodName().

This section provides a summary of the most frequently called, written, and overridden methods for the key ADF Business Components classes.

Controlling Custom Java Files For Your Components

Before examining the specifics of individual classes, it's important to understand how you can control which custom Java files each of your components will use. When you don't need a customized subclass for a given component, you can just let the base framework class handle the implementation at runtime.

Each business component you create comprises a single XML component descriptor, and zero or more related custom Java implementation files. Each component that supports Java customization has a Java tab in its component editor in the JDeveloper 10g IDE. By checking or unchecking the different Java classes, you control which ones get created for your component. If none of the boxes is checked, then your component will be an XML-only component, which simply uses the base framework class as its Java implementation. Otherwise, tick the checkbox of the related Java classes for the current component that you need to customize. JDeveloper 10g will create you a custom subclass of the framework base class in which you can add your code.


NOTE:

You can setup global IDE preferences for which Java classes should be generated by default for each ADF business component type by selecting Tools | Preferences... | Business Components and ticking the checkboxes to indicate what you want your defaults to be.


A best practice is to always generate Entity Object and View Row classes, even if you don't require any custom code in them other than the automatically-generated getter and setter methods. These getter and setter methods offer you compile-time type checking that avoids discovering errors at runtime when you accidentally set an attribute to an incorrect kind of value.

ApplicationModuleImpl Class

The ApplicationModuleImpl See Javadoc for ApplicationModuleImpl class is the base class for application module components. Since the application module is the ADF component used to implement a business service, think of the application module class as the place where you can write your service-level application logic. The application module coordinates with view object instances to support updateable collections of value objects that are automatically "wired" to business domain objects. The business domain objects are implemented as ADF entity objects.

Methods You Typically Call on ApplicationModuleImpl