Enabling Undo history for Recipes tool

To enable undo for a custom noun, you need to extend the abstract class ContentManagementResourceManagerImpl and create your own Java files. The classes in your Java files handle the logic for undoing changes to the custom noun.

About this task

The default undo logic in ContentManagementResourceManagerImpl is to scan an XML file for all tables that are related to the noun, and then remove the entries to undo. What tables are related to each object, and how these tables are referenced together are defined in wc-content-management.xml. You need to create an XML file called wc-content-management.xml. You use this file to define all the tables that are related to each noun and how they reference each other.

Important: If your custom object does not have complex relationships with other objects, you can use the default logic in ContentManagementResourceManagerImpl to process undo. However, the default undo logic does not contain any validation step before undo. You need to write more code to handle any special cases that are not covered by the default undo logic. A special case might be: Before you undo the creation of a product, check whether there are any newly created SKUs for this product. If so, you might want to prevent the undo to avoid creating orphan SKUs. If you want to override any methods to handle any special cases you might have, see ContentManagementResourceManagerImpl.

Procedure

To enable undo history for the Recipes tool:
  1. In the Project-Server/ejbModule directory, create a package and name it com.mycompany.commerce.project.contentmanagement.
  2. Import ProjectContentmanagementResourcemanagerImpl.java and ProjectCollectionContentmanagementResourcemanagerImpl.java into the package.
  3. Recipe and RecipeCollection objects do not have complex relationship with other objects, so the default logic processes undo without error. Therefore, you do not need to override any methods for undo in this case; you can rely on the default logic that is implemented in ContentManagementResourceManagerImpl. However, you must override the following methods, which are used for unlock purposes:
    • getComponentId() – Returns the component id of the object noun.
    • getObjectNoun() – Creates a skeleton noun where the identifier is populated only.
    • getObjectNounPath() – Returns the path that contains the object noun.

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

    package com.mycompany.commerce.project.contentmanagement;
    
    import com.ibm.commerce.contentmanagement.service.ContentManagementResourceManagerImpl;
    import com.mycompany.commerce.project.facade.datatypes.ProjectCollectionIdentifierType;
    import com.mycompany.commerce.project.facade.datatypes.ProjectCollectionType;
    import com.mycompany.commerce.project.facade.datatypes.ProjectFactory;
    
    /**
     * 
     * This class extends ContentManagementResourceManagerImpl to handle undo for Recipe collection object.
     * Since there is no special logic to handle, it relies on the default logic to handle undo for Recipe 
     * collection objects. It only overrides necessary methods.
     */
    
     public class ProjectCollectionContentmanagementResourcemanagerImpl extends
    		ContentManagementResourceManagerImpl {
    	
    	// The path contains the noun
    	private static final String NOUN_PATH = "com.mycompany.commerce.project.facade.datatypes";
    	
    	// The component id for this noun
    	protected static final String COMPONENT_ID = "com.mycompany.commerce.project";
    	
    	// The object represents this noun
    	private Object iObjectNoun;
    
    	// Returns the component id
    	@Override
    	protected String getComponentId() {
    		return COMPONENT_ID;
    	}
    
    	/**
    	 * Creates a skeleton noun with the only unique ID is populated.
    	 * @return the object noun
    	 */
    	@Override
    	protected Object getObjectNoun() {
    		if (iObjectNoun == null) {
    			ProjectCollectionType iProjectCollection = null; 
    			iProjectCollection = ProjectFactory.eINSTANCE.createProjectCollectionType();
    			ProjectCollectionIdentifierType iProjectCollectionIdentifier = ProjectFactory.
           eINSTANCE.createProjectCollectionIdentifierType();
    			iProjectCollectionIdentifier.setUniqueID(getObjectId().toString());
    			iProjectCollection.setProjectCollectionIdentifier(iProjectCollectionIdentifier);
    			iObjectNoun = iProjectCollection;
    		}
    		return iObjectNoun;
    	}
    
    	// Returns the path contains the object noun
    	@Override
    	protected String getObjectNounPath() {
    		return NOUN_PATH;
    	}
    }

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

    package com.mycompany.commerce.project.contentmanagement;
    
    import com.ibm.commerce.contentmanagement.service.ContentManagementResourceManagerImpl;
    import com.mycompany.commerce.project.facade.datatypes.ProjectIdentifierType;
    import com.mycompany.commerce.project.facade.datatypes.ProjectType;
    import com.mycompany.commerce.project.facade.datatypes.ProjectFactory;
    
    /**
     * This class extends ContentManagementResourceManagerImpl to handle undo for Recipes object.
     * Since there is no special logic to handle, it relies on the default logic to handle undo 
     * for Recipe objects. It only overrides necessary methods.
     */
    
     public class ProjectContentmanagementResourcemanagerImpl extends
    		ContentManagementResourceManagerImpl {
    
        //The path that contains the noun
    	private static final String NOUN_PATH = "com.mycompany.commerce.project.facade.datatypes";
    	
    	// The component id for this noun
    	protected static final String COMPONENT_ID = "com.mycompany.commerce.project";
    	
    	// The object represents this noun
    	private Object iObjectNoun;
    
    	// Returns the component id
    	@Override
    	protected String getComponentId() {
    		return COMPONENT_ID;
    	}
    
    	/**
    	 * Creates a skeleton noun with the only unique ID is populated.
    	 * @return the object noun
    	 */
    	@Override
    	protected Object getObjectNoun() {
    		if (iObjectNoun == null) {
    			ProjectType iProject = null; 
    			iProject = ProjectFactory.eINSTANCE.createProjectType();
    			ProjectIdentifierType iProjectIdentifier = ProjectFactory.eINSTANCE.createProjectIdentifierType();
    			iProjectIdentifier.setUniqueID(getObjectId().toString());
    			iProject.setProjectIdentifier(iProjectIdentifier);
    			iObjectNoun = iProject;
    		}
    		return iObjectNoun;
    	}
    
    	// Returns the path contains the object noun
    	@Override
    	protected String getObjectNounPath() {
    		return NOUN_PATH;
    	}
    }
    Importing the above two classes results in some errors. These errors occur because the ContentManagementResourceManagerImpl class cannot be found.
  4. To resolve these errors, complete the following steps to add Content-Server-FEP.jar from the WC project in Project-Server project.
    1. Right-click Project-Server project.
    2. Click Build Path > Configure Build Path.
    3. In the Libraries tab, click Add Jars.
    4. Expand the WC project, select Content-Server-FEP.jar, then click OK.
    5. Make sure Content-Server-FEP.jar is displayed in the build path.
      Project build path configuration
    6. Click OK.
  5. Next, define all tables that are related to each noun and how they reference each other in the wc-content-management.xml file. In the WC_eardir/xml/config/com.mycompany.commerce.project directory, create wc-content-management.xml, and add the following code for recipe and recipe collection objects:
    1. Browse to the WC_eardir/xml/config/com.mycompany.commerce.project/ directory.
    2. Create a file that is called wc-content-management.xml.
    3. Add the following code for Recipe and RecipeCollection objects:
      1. Add the configuration file start element wc:ContentManagementConfiguration. See 1 in the sample file.
      2. Set the container name and ID in node wc:ContentManagementContainer. See 2.
        Note: The -1 to -7 container IDs are reserved by WebSphere Commerce for other tools. Do not use these container ID values. To avoid potential container ID conflicts, use values of less than -10000. For example:
        <wc:ContentManagementContainer name="com.mycompany.commerce.project" id="-10001">
      3. For each noun, create a wc:ContentManagementNoun node. For this node, set the noun name, top table to hold the object data, and the implementation class for handling the content management (the class you implemented in step 2.) In this case, there are two nouns: project and project collection. See 3.
      4. Create wc:ConfigGroup section. This section indicates the UI Object name in wc:ContentManagementUIObject element. In the Recipes tool, the names "Recipe" for Project and "RecipeCollection" for ProjectCollection are used. Next, create a list of wc:ContentManagementRelatedTable elements to define all tables that are related to the object. For each wc:ContentManagementRelatedTable, indicate the name for table name, a whereClause, and values for querying the data. See 4.
      5. Next, create a list of wc:ContentManagementRelatedTable elements to define all tables that are related to the object. For each wc:ContentManagementRelatedTable, indicate the name for table name, a whereClause, and values for querying the data. See 4.
      6. Close the section with ending elements </wc:ContentManagementContainer> and </wc:ContentManagementConfiguration>. See 5.
      7. Save and close wc-content-management.xml.
    Defined tables, how they relate to each noun, and how they reference each other
    1
    <?xml version="1.0" encoding="UTF-8">
    
    <wc:ContentManagementConfiguration xmlns:wc="http://www.ibm.com/xmlns/prod/WebSphereCommerce"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    
    xsi:schemaLocation="http://www.ibm.com/xmlns/prod/WebSphereCommerce ../xsd/wc-content-management.xsd">
    2
        <wc:ContentManagementContainer name="com.mycompany.commerce.project" id="-10001">
    3
        <wc:ContentManagementNoun name="Project" topTable="XPROJECT" className="com.mycompany.commerce.
          project.contentmanagement.ProjectContentmanagementResourcemanagerImpl">
    4
          <wc:ConfigGroup id="-1">
    	 	   <wc:ContentManagementUIObject name="Recipe" />
    		   <wc:ContentManagementRelatedTable name="XPROJECT" whereClause="XPROJECT_ID=?" values="${objectId}"/>
    		   <wc:ContentManagementRelatedTable name="XPRJDES" whereClause="XPROJECT_ID=?" values="${objectId}"/>
    		   <wc:ContentManagementRelatedTable name="XPRJMTR" whereClause="XPROJECT_ID=?" values="${objectId}"/>
    		   <wc:ContentManagementRelatedTable name="XPRJMTRDES" whereClause="XPRJMTR_ID=?" values="${objectId}"/>
    		   <wc:ContentManagementRelatedTable name="XPRJMTRCATREL" whereClause="XPRJMTR_ID=?" values="${objectId}"/>
    		   <wc:ContentManagementRelatedTable name="XPRJINS" whereClause="XPROJECT_ID=?" values="${objectId}"/>
    		   <wc:ContentManagementRelatedTable name="XPRJINSDES" whereClause="XPRJINS_ID=?" values="${objectId}"/>
    		   <wc:ContentManagementRelatedTable name="XPRJCATREL" whereClause="XPROJECT_ID=?" values="${objectId}" />
    		   <wc:ContentManagementRelatedTable name="XPRJPRJCOLREL" whereClause="XPROJECT_ID=?" values="${objectId}"/>
    	   </wc:ConfigGroup>
        </wc:ContentManagementNoun>	
    3
    	  <wc:ContentManagementNoun name="ProjectCollection" topTable="XPRJCOL" className="com.mycompany.commerce.
          project.contentmanagement.ProjectCollectionContentmanagementResourcemanagerImpl">
    4
          <wc:ConfigGroup id="-1">
    			 <wc:ContentManagementUIObject name="RecipeCollection" />
    			 <wc:ContentManagementRelatedTable name="XPRJCOL" whereClause="XPRJCOL_ID=?" values="${objectId}"/>
    			 <wc:ContentManagementRelatedTable name="XPRJCOLDES" whereClause="XPRJCOL_ID=?" values="${objectId}" />
    			 <wc:ContentManagementRelatedTable name="XPRJPRJCOLREL" whereClause="XPRJCOL_ID=?" values="${objectId}"/>
    		  </wc:ConfigGroup>
    	  </wc:ContentManagementNoun>
    		
    	</wc:ContentManagementContainer>
    
    </wc:ContentManagementConfiguration>
    5
     </wc:ContentManagementContainer>
    
    </wc:ContentManagementConfiguration>