Extending the Change History service for a custom module

To enable change history for a custom noun, you must create Java classes that extend the abstract class AbstractChangeHistoryServiceDelegateImpl. After you create the classes, they must be registered in wc-business-object-mediator.xml for the customized module.

About this task

com.ibm.commerce.foundation.server.services.changehistory.utility.AbstractChangeHistoryServiceDelegateImpl regulates the data that is stored in the CMPRMYOBJ table and is used to display history.

After the Java files are created, they must be registered in wc-business-object-mediator.xml for the customized module. The change history service uses a foundation class that is common to all change history. The className and interfaceName are common to all nouns. For your customized setup, you must add <_config:mediator-property> elements to specify the name of your noun and the class to use more services.

Procedure

To enable the change history service for a custom module:
  1. In the Project-Server/ejbModule directory, create a package and name it com.mycompany.commerce.project.changehistory.
  2. Import ProjectChangeHistoryServiceImpl.java and ProjectCollectionChangeHistoryServiceImpl.java into the package.
  3. Both Java classes have five methods that you must override and provide your own implementation. The following methods must be implemented:
    1. getObjectCodeForObject() – Returns the value of the noun you want to display in the history tab. This method can be configured to get whatever noun attribute makes the most sense to display. For a recipe object, it makes the most sense to display the name field.
    2. getStatementToFindObjectCode() – Returns a SQL statement that is used to retrieve noun information from the database.
    3. getUniqueID() – Retrieves the unique identifier (primary key) of the noun.
    4. getObjectStoreID() – Retrieves the unique store identifier of the object.
    5. getResolvedCMCObject() – Gets the logical name of the object that is used in Management Center.
    Note: Depending on the complexity of your noun, other methods that are detailed in the documentation for com.ibm.commerce.foundation.server.services.changehistory.utility.AbstractChangeHistoryServiceDelegateImpl might also need customization.

    The following code is an example of the ProjectChangeHistoryServiceImpl.java file:

    package com.mycompany.commerce.project.changehistory;
    
    import com.ibm.commerce.foundation.server.services.changehistory.exception.ChangeHistoryApplicationDelegateException;
    import com.ibm.commerce.foundation.server.services.changehistory.utility.AbstractChangeHistoryServiceDelegateImpl;
    import com.mycompany.commerce.project.facade.datatypes.ProjectExternalIdentifierType;
    import com.mycompany.commerce.project.facade.datatypes.ProjectIdentifierType;
    import com.mycompany.commerce.project.facade.datatypes.ProjectType;
    import commonj.sdo.DataObject;
    
    public class ProjectChangeHistoryServiceImpl extends AbstractChangeHistoryServiceDelegateImpl {
    
    	private static final String UI_OBJECT_NAME = "Recipe";
    
    	/**
    	 * This method returns the value of your noun you want to be displayed in the Chnage History pane.
    	 * This can be configured to grab a name, number, etc, whatever makes the most sense for your noun. 
    	 * For example for an recipe object it makes the most sense to display the name field.
    	 */
    	@Override
    	protected String getObjectCodeForObject(Object noun) {
    		
    		if(noun instanceof ProjectType){
    			ProjectType pt = (ProjectType) noun;
    			ProjectIdentifierType pit = pt.getProjectIdentifier();
    			ProjectExternalIdentifierType peit = pit.getExternalIdentifier();
    			
    			if(peit != null){
    				return peit.getName();
    			}
    			else {
    				return null;
    			}
    		}else { 
    			return null;
    		}
    	}
    
    	/**
    	 * This method returns a string that is the SQL to the unique ID. This is used elsewhere in case 
    	 * the entire noun has not been retrieved then a SQL can be run to get the data instead.
    	 */
    	@Override
    	protected String getStatementToFindObjectCode() {
    		
    		return "select PRJNAME from XPROJECT where XPROJECT_ID=?";
    	}
    
    	/**
    	 * This method returns the unique ID of the change history object. Use getChangedDataObject() 
    	 * to get the noun object then cast it as a DataObject. Use getString() of the dataObject 
    	 * with the correct path as the parameter, here we want "ProjectIdentifier/UniqueID"
    	 */
    	@Override
    	public Long getUniqueID() {
    		
    		Object noun = getChangedDataObject();
    		if(noun instanceof DataObject){
    			DataObject newNoun = (DataObject) noun;
    			return Long.valueOf(newNoun.getString("ProjectIdentifier/UniqueID"));
    		}
    		else{
    		return null;
    		}
    	}
    
    	// This method queries the SQL to get the Store ID of the object
    	@Override
    	public Long getObjectStoreID() throws ChangeHistoryApplicationDelegateException {
    		Long storeId = null;
    		final String storeidSQL = "select STOREENT_ID from XPROJECT where XPROJECT_ID = ?";
    		String storeidString;
    		storeidString = executeQuery(storeidSQL);
    		if (storeidString != null) {
    			storeId = Long.valueOf(storeidString);
    		}
    		return storeId;
    	}
    	
    	// This method is to get the object logical name used in CMC
    	@Override
    	public String getResolvedCMCObject() {
    		return UI_OBJECT_NAME ;
    	}
    }

    The following code is an example of the ProjectCollectionChangeHistoryServiceImpl.java file:

    package com.mycompany.commerce.project.changehistory;
    
    import com.ibm.commerce.foundation.server.services.changehistory.exception.ChangeHistoryApplicationDelegateException;
    import com.ibm.commerce.foundation.server.services.changehistory.utility.AbstractChangeHistoryServiceDelegateImpl;
    import com.mycompany.commerce.project.facade.datatypes.ProjectCollectionExternalIdentifierType;
    import com.mycompany.commerce.project.facade.datatypes.ProjectCollectionIdentifierType;
    import com.mycompany.commerce.project.facade.datatypes.ProjectCollectionType;
    import commonj.sdo.DataObject;
    
    public class ProjectCollectionChangeHistoryServiceImpl extends AbstractChangeHistoryServiceDelegateImpl{
    
    	private static final String UI_OBJECT_NAME = "RecipeCollection";
    	/**
    	 * This method returns the value of the noun you want to be displayed in the Change History pane.
    	 * This can be configured to grab a name, number, etc, whatever makes the most sense for your noun.
    	 * For example for a recipe collection object it makes the most sense to display the name field.
    	 */
    	@Override
    	protected String getObjectCodeForObject(Object noun)
    			throws ChangeHistoryApplicationDelegateException {
    		if(noun instanceof ProjectCollectionType){
    			ProjectCollectionType pt = (ProjectCollectionType) noun;
    			ProjectCollectionIdentifierType pit = pt.getProjectCollectionIdentifier();
    			ProjectCollectionExternalIdentifierType peit = pit.getExternalIdentifier();
    			
    			if(peit != null){
    				return peit.getName();
    			}
    			else {
    				return null;
    			}
    		}else { 
    			return null;
    		}
    	}
    
    	/**
    	 * Returns a string that is the SQL to the unique id. This is used elsewhere in case the
    	 * entire noun hasn't been retireved then a sql can be run to get the data instead.
    	 */
    	@Override
    	 protected String getStatementToFindObjectCode() {
    		return "select PRJCOLNAME from XPRJCOL where XPRJCOL_ID=?";
    	}
    
    	/**
    	 * Returns the unique ID of the change history object. Use getChangedDataObject() to get 
    	 * the noun object then cast it as a DataObject. Use getString() of the dataObject with 
    	 * the correct path as the parameter, here we want "ProjectCollectionIdentifier/UniqueID"
    	 */
    	@Override
    	public Long getUniqueID() {
    		Object noun = getChangedDataObject();
    		if(noun instanceof DataObject){
    			DataObject newNoun = (DataObject) noun;
    			return Long.valueOf(newNoun.getString("ProjectCollectionIdentifier/UniqueID"));
    		}
    		else{
    		return null;
    		}
    	}
    		
    	// This method queries the SQL to get the Store ID of the object
    	@Override
    	public Long getObjectStoreID() throws ChangeHistoryApplicationDelegateException {
    		Long storeId = null;
    		final String storeidSQL = "select STOREENT_ID from XPRJCOL where XPRJCOL_ID = ?";
    		String storeidString = executeQuery(storeidSQL);
    		if (storeidString != null) {
    			storeId = Long.valueOf(storeidString);
    		}
    		return storeId;
    	}
    	
    	// This method gets the object logical name used in CMC
    	@Override
    	public String getResolvedCMCObject() {
    		return UI_OBJECT_NAME ;
    	}
    }
  4. Next, for each object you must add a mediator to register the Java classes you implemented in the previous step.
    1. Open WC_eardir/xml/config/com.mycompany.commerce.project/wc-business-object-mediator.xml.
    2. Find the Project object by locating this line:
      <_config:object logicalType="com.mycompany.commerce.project.facade.datatypes.ProjectType" physicalType=
         "com.mycompany.commerce.project.facade.server.entity.datatypes.Xproject">
    3. Immediately beneath the Project object, add the following mediator code for the Project object:
      1. Create a <_config:mediator> element with a className of .ibm.commerce.foundation.internal.server.services.changehistory.mediator.EchoBusinessObjectChangeHistoryMediatorImpl and an interfaceName of .ibm.commerce.foundation.server.services.dataaccess.bom.mediator.EchoBusinessObjectChangeHistoryMediator. See 1 in the sample file.
      2. Create a set of <_config:mediator-property> elements for the change control mediator. nounName indicates the name of the noun. For this tutorial, the value is Project. classNameForAdditionalService indicates the implementation class for handing the change history for this noun. For this tutorial, the value is ProjectChangeHistoryServiceImpl. See 2.
      3. Close the section with ending elements </_config:mediator-properties> and </_config:mediator>. See 3.
    4. Find the ProjectCollection object by locating this line:
      <_config:object logicalType="com.mycompany.commerce.project.facade.datatypes.ProjectCollectionType" physicalType=
         "com.mycompany.commerce.project.facade.server.entity.datatypes.Xprjcol">
    5. Immediately beneath the ProjectCollection object, add the following mediator code for the ProjectCollection object:
      1. Create a <_config:mediator> element with a className of .ibm.commerce.foundation.internal.server.services.changehistory.mediator.EchoBusinessObjectChangeHistoryMediatorImpl and an interfaceName of .ibm.commerce.foundation.server.services.dataaccess.bom.mediator.EchoBusinessObjectChangeHistoryMediator. See 4.
      2. Create a set of <_config:mediator-property> elements for the change control mediator. nounName indicates the name of the noun. For this tutorial, the value is ProjectCollection. classNameForAdditionalService indicates the implementation class for handing the change history for this noun. For this tutorial, the value is ProjectChangeHistoryServiceImpl. See 5.
      3. Close the section with ending elements </_config:mediator-properties> and </_config:mediator>. See 6.
    6. Save and close wc-business-object-mediator.xml.
    Defined object mediators for the Recipe and RecipeCollection objects
    1
    <!-- PROJECT CHANGE HISTORY MEDIATOR --> 
    
    <_config:mediator className="com.ibm.commerce.foundation.server.services.changehistory.mediator.
       EchoBusinessObjectChangeHistoryDelegateMediatorImpl" interfaceName="com.ibm.commerce.foundation.
       server.services.dataaccess.bom.mediator.EchoBusinessObjectChangeHistoryMediator">  
    2
     <_config:mediator-properties>
      <_config:mediator-property name="nounName" value="Project" />
      <_config:mediator-property name="classNameForAdditionalService" value="com.mycompany.commerce.project.changehistory.ProjectChangeHistoryServiceImpl" />
     </_config:mediator-properties>
    3
     </_config:mediator-properties>
    </_config:mediator>
    4
    <!-- PROJECTCOLLECTION CHANGE HISTORY MEDIATOR --> 
    
    <_config:mediator className="com.ibm.commerce.foundation.server.services.changehistory.mediator.
       EchoBusinessObjectChangeHistoryDelegateMediatorImpl" interfaceName="com.ibm.commerce.foundation.
       server.services.dataaccess.bom.mediator.EchoBusinessObjectChangeHistoryMediator">  
    5
     <_config:mediator-properties>
      <_config:mediator-property name="nounName" value="ProjectCollection" />
      <_config:mediator-property name="classNameForAdditionalService" value="com.mycompany.commerce.project.changehistory.ProjectChangeHistoryServiceImpl" />
     </_config:mediator-properties>
    6
     </_config:mediator-properties>
    </_config:mediator>