Externalizable Business Objects

What are externalizable business objects?

An Externalizable Business Object (EBO) is a class that implements an interface that extends the ExternalizableBusinessObject interface. (Note that there is an interface involved that extends the EBO interface). This interface will define getter methods corresponding to the properties that are exposed.

An EBO is a business object with the following properties:

  • All business objects belong to a module. An EBO will be owned by an optional module and accessed by a (optional or core) module that does not own it.
  • It has the potential to be stored in a data repository that may be different from the main database, if the implementing institution so desires.
  • Any access to the EBO from another module will be read-only.

Creating an Externalizable Business Object

The Contracts and Grants (CG) is an optional module within KFS, and some CG business objects will be accessed/referenced by the Chart of Accounts (COA) module. For example, the CG business object Cfda (for Catalog of Federal Domestic Assistance) is accessed as a reference object of the COA module's Account business object.

Step 1: Create a sub-interface to Externalizable Business Object

The first step is to create an interface that extends ExternalizableBusinessObject that has getter methods for the fields that should be exposed to other modules. If the getter method returns a BusinessObject that is not in a core module, then the return type should be an interface that extends ExternalizableBusinessObject as well.

package org.kuali.kfs.integration.cg;

import org.kuali.kfs.kns.bo.ExternalizableBusinessObject;

public interface ContractsAndGrantsCfda extends ExternalizableBusinessObject {
    public String getCfdaNumber(); 
    public String getCfdaProgramTitleName();
    public boolean getCfdaStatusCode();
    public String getCfdaMaintenanceTypeId();
}

All EBO sub-interfaces should be in a sub-package of an "integration" package corresponding to the module that owns it. For example, since Cfda is a CG business object, it is in the org.kuali.kfs.integration.cg package.

Step 2: Register the module-specific integration sub-package to the appropriate module service

Now that we've created an EBO interface, we need to let the appropriate module that owns it know that it is responsible for the EBO interface. To do so, we register an additional package under the "packagePrefixes" section of the module configuration.

In our example, the CG module will be responsible for the ContractsAndGrantsCfda interface because the module will own the package in which the interface resides.

<bean id="cgModuleConfiguration" parent="cgModuleConfiguration-parentBean" />

<bean id="cgModuleConfiguration-parentBean" class="org.kuali.kfs.sys.FinancialSystemModuleConfiguration" abstract="true">
  <!-- other properties of the module configuration bean -->
  <property name="packagePrefixes">
    <list>
      <value>org.kuali.kfs.module.cg</value>
      <value>org.kuali.kfs.integration.businessobject.cg</value>  <!-- this item was added to support EBOs -->
    </list>
  </property>
</bean>

Step: Specify the implementation class of the ExternalizableBusinessObject sub-interface

This step only applies if the actual implementation class is a business object that is persisted in OJB.

The base implementation of the module service, ModuleServiceBase, assumes that the EBO is implemented by a class that is persisted in OJB (i.e. really internal to KFS).

If the actual implementation does not reside within OJB (i.e. the data comes from another data repository), then the developer will need to subclass ModuleServiceBase and override the appropriate methods related to EBOs.

The next step is to specify the implementation classes for the ExternalizableBusinessObject sub-interface. This allows the system to determine, given a ExternalizableBusinessObject, what is the concrete implementation class?

<bean id="cgModuleConfiguration" parent="cgModuleConfiguration-parentBean" />

<bean id="cgModuleConfiguration-parentBean" class="org.kuali.kfs.sys.FinancialSystemModuleConfiguration" abstract="true">
  <!-- other properties of the module configuration bean -->
  <property name="packagePrefixes">
    <list>
      <value>org.kuali.kfs.module.cg</value>
      <value>org.kuali.kfs.integration.businessobject.cg</value>
    </list>
  </property>
  <property name="externalizableBusinessObjectImplementations">
    <map>
      <entry key="org.kuali.kfs.integration.businessobject.cg.ContractsAndGrantsCfda" value="org.kuali.kfs.module.cg.businessobject.Cfda" />
    </map>
  </property>
</bean>

In the "externalizableBusinessObjectImplementations" property, we define a map of EBO sub-interface class to concrete class mappings. The concrete class will implement the sub-interface. For the above example, it indicates that when a ContractsAndGrantsCfda is encountered, that the Cfda concrete should be used.

Upon completion of this step, when the data dictionary tries to access metadata about the ContractsAndGrantsCfda interface, metadata from Cfda is returned because it has been registered that ContractsAndGrantsCfda's has been implemented by Cfda.

Step 4: Implement relationships to EBOs

See Externalizable Business Objects 1-to-1 references and Externalizable Business Objects 1-to-n references