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:
- In the Project-Server/ejbModule directory, create a package and name it com.mycompany.commerce.project.contentmanagement.
- Import ProjectContentmanagementResourcemanagerImpl.java and ProjectCollectionContentmanagementResourcemanagerImpl.java into the package.
- 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. - To resolve these errors, complete the following steps
to add Content-Server-FEP.jar from the WC project
in Project-Server project.
- Right-click Project-Server project.
- Click Build Path > Configure Build Path.
- In the Libraries tab, click Add Jars.
- Expand the WC project, select Content-Server-FEP.jar, then click OK.
- Make sure Content-Server-FEP.jar is displayed
in the build path.
- Click OK.
- 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:
- Browse to the WC_eardir/xml/config/com.mycompany.commerce.project/ directory.
- Create a file that is called wc-content-management.xml.
- Add the following code for Recipe and RecipeCollection objects:
- Add the configuration file start element
wc:ContentManagementConfiguration
. See 1 in the sample file. - 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">
- 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. - Create
wc:ConfigGroup
section. This section indicates the UI Object name inwc:ContentManagementUIObject
element. In the Recipes tool, the names "Recipe" for Project and "RecipeCollection" for ProjectCollection are used. Next, create a list ofwc:ContentManagementRelatedTable
elements to define all tables that are related to the object. For eachwc:ContentManagementRelatedTable
, indicate the name for table name, awhereClause
, andvalues
for querying the data. See 4. - Next, create a list of
wc:ContentManagementRelatedTable
elements to define all tables that are related to the object. For eachwc:ContentManagementRelatedTable
, indicate the name for table name, awhereClause
, andvalues
for querying the data. See 4. - Close the section with ending elements
</wc:ContentManagementContainer>
and</wc:ContentManagementConfiguration>
. See 5. - Save and close wc-content-management.xml.
- Add the configuration file start element
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>