Skip Headers
Oracle® Application Server TopLink Application Developer's Guide
10g Release 2 (10.1.2)
Part No. B15901-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

Customizing the Project

OracleAS TopLink projects, descriptors, and mapping are normally created using OracleAS TopLink Mapping Workbench. The output of OracleAS TopLink Mapping Workbench is an XML file that contains the mapping information required to store persistent objects in the database.

OracleAS TopLink Mapping Workbench does not offer access to all the customization available to the OracleAS TopLink descriptors that make up the project. In these situations, to customize the mapping information, you can specify an amendment method to be run at deployment time.Each OracleAS TopLink descriptor can have an amendment method.

This section describes some of the available customization topics and techniques, including:

Customizing OracleAS TopLink Descriptors with Amendment Methods

Amendment methods are static methods that run at deployment time and enable you to implement descriptor customization code.

For more information about amendment methods, see the Oracle Application Server TopLink Mapping Workbench User's Guide.

Using After Load Methods

Some OracleAS TopLink features cannot be configured from OracleAS TopLink Mapping Workbench. To use these features, amend the descriptor after it is loaded as part of the project. After load methods are a type of amendment method that enables you to modify descriptors in code after you create the project object (either from an XML project or a project class).

To access descriptors from the project object or the session object (after the session object is created from the project), write a Java method that takes the name of the descriptor as a single parameter. You can then send messages to the descriptor or any of its specific mappings to configure advanced features. Make all descriptor changes before the session logs in. Any descriptor change made after login is ignored.

For more information, see "Amending Descriptors After Loading" in the Oracle Application Server TopLink Mapping Workbench User's Guide.

Use any of the following APIs to implement after load methods:

  • project.getDescriptors();

  • session.getDescriptors();

  • session.getDescriptor(Class domainClass);

For more information about these APIs, see the Oracle Application Server TopLink API Reference.

Descriptor Events

The descriptor event manager enables you to create events that trigger other events in your application. You use the Event Manager to invoke specific events when OracleAS TopLink reads, updates, deletes, or inserts objects on the database.

Descriptor events enable you to:

  • Synchronize persistent objects with other systems, services, and frameworks

  • Maintain nonpersistent attributes of which OracleAS TopLink is not aware

  • Notify other objects in the application when the persistent state of an object changes

  • Implement complex mappings or optimizations not directly supported by OracleAS TopLink mappings.

You specify descriptor events in OracleAS TopLink Mapping Workbench.

For more information, see "Specifying Events" in the Oracle Application Server TopLink Mapping Workbench User's Guide.

Receiving Descriptor Events

Applications receive descriptor events in several ways:

Implement the Descriptor Event Listener Interface

Register objects that implement the DescriptorEventListener interface with the descriptor event manager. The descriptor event manager then notifies the object when any event occurs for that descriptor.

Subclass the Descriptor Event Adapter Class

Use the DescriptorEventAdapter class if your application does not require all the methods defined in the DescriptorEventListener interface. The DescriptorEventAdapter implements the DescriptorEventListener interface and defines an empty method for each method in the interface. To use the adapter, subclass it and then register your new object with the descriptor event manager.

Register an Event Method with a Descriptor

Register a public method as an event method. The descriptor then calls the event method when a database operation occurs. The event method must:

  • Be public so that OracleAS TopLink can call it

  • Return void

  • Take a DescriptorEvent as a parameter

Registering Descriptor Event Listeners

If you want an object other than the domain object to handle these events, then register it as a listener with the descriptor event manager. If you want a LockManager to receive events for all Employees, then modify your descriptor amendment to register the LockManager as the listener.

Any object you register as a listener must implement the DescriptorEventListener interface. The amendment method appears in Example 3-44.

Example 3-44 Registering a Descriptor Event Listeners

public static void addToDescriptor(Descriptor descriptor) {
    descriptor.getEventManager().addListener(LockManager.activeManager());
}

Reference

Table 3-5 summarizes the most common public methods for DescriptorEventManager. For more information about the available methods for DescriptorEventManager, see the Oracle Application Server TopLink API Reference.

Table 3-5 Elements for the Descriptor Event Manager

Element Default Method Name
Events selectors (Defaults specified in listener interface implementation) All events take DescriptorEvent:

postBuild

postRefresh

preWrite

postWrite

preDelete

postDelete

preInsert

postInsert

preUpdate

postUpdate

aboutToInsert

aboutToUpdate

postClone

postMerge

All events take String methodName:

setPostBuildSelector

setPostRefreshSelector

setPreWriteSelector

setPostWriteSelector

setPreDeleteSelector

setPostDeleteSelector

setPreInsertSelector

setPostInsertSelector

setPreUpdateSelector

setPostUpdateSelector

setAboutToInsertSelector

setAboutToUpdateSelector

setPostCloneSelector

setPostMergeSelector

Listener registration Descriptor-Event reference (available methods on Descriptor-Event) Source object if it implements the listener interface only; aboutToInsert/ Update, / Build only; postMerge / Clone / write events within a Unit of Work addListener (DescriptorEventListener listener)

getSource()

getSession()

getQuery()

getDescriptor()

getRow()

getOriginalObject()


Supported Events

The DescriptorEventManager supports several methods, including those in Table 3-6.

Table 3-6 Supported Events

Triggering Method Type Supported Events Description
Post-X Method Post-Build Occurs after an object is built from the database.
Post-X Method Post-Clone Occurs after an object has been cloned into a Unit of Work.
Post-X Method Post-Merge Occurs after an object has been merged from a Unit of Work.
Post-X Method Post-Refresh Occurs after an object is refreshed from the database.
Updating Method Pre-Update Occurs before an object is updated in the database. This may be called in a Unit of Work even if the object has no changes and does not require an update.
Updating Method About-to-Update Occurs when the row of an object is updated in the database. This method is called only if the object has changes in the Unit of Work.
Updating Method Post-Update Occurs after an object is updated in the database. This may be called in a Unit of Work even if the object has no changes and does not require an update.
Inserting Method Pre-Insert Occurs before an object is inserted in the database.
Inserting Method About-to-Insert Occurs when the row of an object is inserted in the data­base.
Inserting Method Post-Insert Occurs after an object is inserted into the database.
Writing Method Pre-Write Occurs before an object is inserted or updated into the database. This occurs before Pre-Insert/Update.
Writing Method Post-Write Occurs after an object is inserted or updated into the database. This occurs after Pre-Insert/Update.
Deleting Method Pre-Delete Occurs before an object is deleted from the database.
Deleting Method Post-Delete Occurs after an object is deleted from the database.

Updating Change Sets

In release 10g (9.0.4.6), OracleAS TopLink modified the way users can update change sets when changes have been made to an aggregate within a DescriptorEvent.

Note the following example:

If you have an aggregate Address with the attributes Street and City, you can update an aggregate within a DescriptorEvent by calling the method updateAttributeWithObject, passing in the entire updated clone aggregate object and the attribute name of the AggregateObjectMapping from the non-aggregate parent object.

customer.address.cty= "NewCity";

event.updateAttributeWithObject("address",customer.address);

Descriptor Copy Policy

The OracleAS TopLink Unit of Work feature uses copies of object (clones) rather than the original objects to perform its tasks. You can construct clones as follows:

  • The Unit of Work calls the object default constructor to create a copy. This is the default method to create a clone.

  • You specify a method on the object, and the Unit of Work calls this method to generate the clone. For example, add the following method to the descriptor:

    descriptor.createCopyPolicy("clone");
    
    

    When the Unit of Work requires a clone of this object, it calls the clone() method to create the copy.

  • You specify the method by adding the following code to the descriptor:

    useCloneCopyPolicy(String)
    
    

    The String in this method is the name of another method that clones the object.

The most common way to use any policy other than the default (using the object default constructor) is to create an amendment method and specify it in OracleAS TopLink Mapping Workbench when you configure the class.

For more information about amendment methods, see "Customizing OracleAS TopLink Descriptors with Amendment Methods".

See "Setting the Copy Policy in Java" for more information about implementing descriptor copy policy in code.

Descriptor Query Manager

You can add queries to a descriptor (named queries) for execution later in the application. For example, you can add the following code to a descriptor:

ReadObjectQuery aQuery = new ReadObjectQuery(Employee.class);
descriptor.getQueryManager().addQuery("readAnEmployee", aQuery);

You can accomplish this with an amendment method.

For more information about amendment methods, see "Customizing OracleAS TopLink Descriptors with Amendment Methods".

Replacing Descriptor Queries

You can replace all queries in an OracleAS TopLink descriptor with user defined queries. Doing this enables you to change query behavior or to substitute stored procedures for the queries.

Example 3-45 Substituting a Stored Procedure for a Query

This example illustrates how to force the read object descriptor call to use a stored procedure.

ReadObjectQuery query = new ReadObjectQuery();
StoredProcedureCall call = new StoredProcedureCall();
call.setProcedureName("READ_RDM_EMP");
query.setCall(call);
descriptor.getQueryManager().setReadObjectQuery
(query);

Instantiation Policy

An instantiation policy specifies how objects are instantiated.

Overriding the Instantiation Policy Using Java Code

The Descriptor class provides the following methods to specify how objects get instantiated:

  • useDefaultConstructorInstantiationPolicy(): Instructs OracleAS TopLink to use the default constructor to create new instances of objects built from the database. This method can be private, protected, or default/package.

  • useFactoryInstantiationPolicy(Object, String): Instructs OracleAS TopLink to send the message specified by the String parameter to an object factory specified by the Object parameter to create objects from the database. The object factory method can be public, private, protected, or default/package and requires no arguments.

  • useMethodInstantiationPolicy(String): Instructs OracleAS TopLink to send the message contained in the string parameter to create objects that are populated with data from the database. This method can be a public or static method on the descriptor class, or it can be private, protected, or default/package. It must return a new instance of the class.

  • useFactoryInstantiationPolicy(Class factoryClass, String methodName): Instructs OracleAS TopLink to send the message contained in the String parameter to an instance of the specified factoryClass. This method must return a new instance of the descriptor class. To instantiate the factory, OracleAS TopLink invokes the default constructor of the specified factoryClass. Both the factoryClass default constructor and the method invoked on the factory can be private, protected, or default/package.

  • useFactoryInstantiationPolicy(Class factoryClass, String methodName, String factoryMethodName): Instructs OracleAS TopLink to send the message contained in the first String parameter, methodName, to an instance of the specified factoryClass. This method must return a new instance of the descriptor class. To instantiate the factory, OracleAS TopLink invokes the second String, methodName on the specified factoryClass. This method must be a static method on the factoryClass and must return an instance of the factoryClass. The factory class static factory method and the method invoked on the factory can be private, protected, or default/package.

Setting the Wrapper Policy Using Java Code

The Descriptor class provides methods used in conjunction with the wrapper policy:

  • setWrapperPolicy(oracle.toplink.descriptors.WrapperPolicy): can be invoked to provide a wrapper policy for the descriptor

  • getWrapperPolicy(): returns the wrapper policy for a descriptor

Creating EJB Projects and OracleAS TopLink Descriptors in Java

You can create mappings and OracleAS TopLink descriptors to access features that are not available in OracleAS TopLink Mapping Workbench.

To define a project using Java code:

  1. Implement a project class that extends the oracle.toplink.sessions.Project class.

  2. Compile the project class.

  3. Edit the toplink-ejb-jar.xml deployment descriptor so that the value for the project-class element is the fully-qualified project class name.

    For more information about creating project classes, see the Oracle Application Server TopLink Mapping Workbench User's Guide.


    Note:

    Use OracleAS TopLink Mapping Workbench to create a Java Project class from an existing project. This provides a starting point for a custom project class. For more information, see the Oracle Application Server TopLink Mapping Workbench User's Guide.

    You can also use OracleAS TopLink Mapping Workbench Export Project to Java Source... menu command to create a starting point for coding the project class manually.


Example 3-46 illustrates how you can specify OracleAS TopLink projects in code.

Example 3-46 Specifying an OracleAS TopLink Project in Code

/**
* The class EmployeeProject is an example of an OracleAS TopLink project defined in Java code. The individual parts of the project - the Login and the descriptors, are built inside of methods that are called by the constructor. Note that EmployeeProject extends the class oracle.toplink.sessions.Project.
*/
public class EmployeeProject extends oracle.toplink.sessions.Project{

/**
* Supply a zero argument constructor that initializes all aspects of the project. Make sure that the login and all the descriptors are initialized and added to the project.
*/
public EmployeeProject(){
applyPROJECT();
applyLOGIN();
buildAddressDescriptor();
buildEmployeeDescriptor();
// other methods to build all descriptors for the project
/**
* Project-level properties, such as the name of the project, should be specified here.
*/
protected void applyPROJECT(){
setName("Employee");
}
protected void applyLOGIN()
{
    oracle.toplink.sessions.DatabaseLogin login = 
      new oracle.toplink.sessions.DatabaseLogin();

    // use platform appropriate for underlying database
    login.setPlatformClassName( "oracle.toplink.internal.databaseaccess.
      OraclePlatform");

    // if no sequencing is used, setLogin() will suffice
    setLoginAndApplySequenceProperties(login);
}

/**
* Descriptors are built by defining table info, setting properties (caching, etc.) and by adding mappings to the descriptor.
*/
protected void buildEmployeeDescriptor() {
    oracle.toplink.publicinterface.Descriptor descriptor = 
      new oracle.toplink.publicinterface.Descriptor();
}

// SECTION: DESCRIPTOR
// specify the class to be made persistent
descriptor.setJavaClass(examples.ejb.cmp11.advanced.EmployeeBean.class);

// specify the tables to be used and primary key
Vector tables = new Vector();
tables.addElement("EJB_EMPLOYEE");
descriptor.setTableNames(tables);
descriptor.addPrimaryKeyFieldName("EJB_EMPLOYEE.EMP_ID");

// SECTION: PROPERTIES
descriptor.setIdentityMapClass(
oracle.toplink.internal.identitymaps. FullIdentityMap.class);
descriptor.setExistenceChecking("Check cache");
descriptor.setIdentityMapSize(100);

// SECTION: COPY POLICY
descriptor.createCopyPolicy("constructor");

// SECTION: INSTANTIATION POLICY
descriptor.createInstantiationPolicy("constructor");

// SECTION: DIRECTTOFIELDMAPPING
oracle.toplink.mappings.DirectToFieldMapping firstNameMapping =
  new oracle.toplink.mappings .DirectToFieldMapping();
firstNameMapping.setAttributeName("firstName");
firstNameMapping.setIsReadOnly(false);
firstNameMapping.setFieldName("EJB_EMPLOYEE.F_NAME");
descriptor.addMapping(firstNameMapping);

// … Additional mappings are added to the descriptor using the addMapping() method.
},}

To deploy the OracleAS TopLink project, specify the project class name in the project-class element in the toplink-ejb-jar.xml file for your entity beans.

For example:

<session>
    <name>EmployeeDemo</name>
    <project-class>oracle.toplink.demos.ejb.cmp.wls.employee.EmployeeProject
    </project-class>
    <login>
        <connection-pool>ejbPool</connection-pool>
    </login>
</session>