Cache invalidation in the BOD command framework

Unlike Get services, which do not make changes to business objects, the Change, Process and Sync services will change the business objects within the system and may need to invalidate existing cache representations of the business objects they service. For example, when a particular CatalogEntry is changed, any JSP or cached service that is referencing that object needs to be invalidated. When you are using the BOD command framework with a tool, such as the Management Center, or integrating with external systems, you need to make noun and related noun invalidation policies. When you are using the BOD command framework with a storefront, you need to make service command invalidation policies to invalidate the views in the storefront.

Invalidating the noun

As part of the Change, Sync and Process controller commands, there is an attribute called uniqueIDXPath that can be set. This attribute is part of a property that can be defined on the command which indicates the path to find the UniqueID of the Nouns that were changed as part of this request. This command attribute is used for caching purposes to resolve the identifier of the objects involved with the request.

The uniqueIDXPath attribute is used when the getUniqueID() method is called. The purpose of the getUniqueID() method is to return a collection of the internal identifiers of the object that is involved with the service request. For the case of Change, Process and Sync, it is the objects that have changed and require invalidation.

Alternatively, the BOD service controller commands can extend the getUniqueID() method and implement it to return a Collection of UniqueID that represents the Nouns that were changed as part of the current request. This approach requires coding changes and does not leverage the properties configuration that can be set on a command.

Setting the UniqueID XPath attribute

The command registration of the BOD service controllers is found in the CMDREG table. This database record contains the implementation the interface is associated with. Along with this association, the PROPERTIES column can be used to set default properties on the command when it is instantiated. For the purpose of cache invalidation, any BOD service controller command that extends the Abstract BOD service commands can have this property set so it can be registered to issue invalidation requests when changes are performed on specific nouns.

The following SQL can be used to update the command properties to specify the XPath where to find the UniqueID of the nouns in the request.
update CMDREG set properties = properties || '&uniqueIDXPath;=NounIdentifier/UniqueID' 
where interfacename = 'bod service command controller interface'

Creating the noun invalidation policy

Once the command returns a collection of the UniqueID of the nouns that were changed as a result of the request, the cachespec.xml which defines the caching and cache invalidation needs to be configured to create the invalidation policy. Although it is not required, it is recommended that the cachespec.xml of each service module be located in the HTTPInterface Web module for that service module.

Similar to defining a caching policy for a Get service command, the invalidation identifier comprises the name of the noun that is invalidated and the uniqueID that is invalidated. This invalidation policy is configured as any command cache entry with the following additional guidelines.
  • The delay-invalidations property is set to true. This is to ensure that the invalidation occurs after the command executes to ensure the UniqueIDs have been resolved.
  • The method to invoke is getUniqueID, and the multipleIDs attribute is set to true. Because getUniqueID returns a collection of UniqueID, the multipleIDs attribute will create an invalidation key for each element of the returned collection.
The following XML is a sample invalidation policy created for ChangeCatalogEntryCmdImpl:
<cache-entry>
	<class>command</class>
	<name>com.ibm.commerce.catalog.facade.server.commands.ChangeCatalogEntryCmdImpl</name>
	<name>com.ibm.commerce.catalog.facade.server.commands.ProcessCatalogEntryCmdImpl</name>
	<property name="delay-invalidations">true</property>
	<invalidation>CatalogEntry
		<component id="getUniqueID" type="method" multipleIDs="true">
			<required>true</required>		
		</component>
	</invalidation>
</cache-entry>

Invalidating related nouns

When you change a noun, this may also cause changes to related nouns based on the action performed. For example, when moving a CatalogEntry from one CatalogGroup to another, not only does the CatalogEntry need to be invalidated, but the old and new parent CatalogGroup nouns also need to be invalidated.

All actions are represented as action commands that perform a specific action on either the noun (in the case of Process) or the noun part (in the case of the Change and Sync). These action commands are very specific and will typically be where changes to the related nouns is performed. Following our example, the command implementation that would be responsible for the CatalogGroup invalidation would be the implementation associated with the com.ibm.commerce.catalog.facade.server.commands.ChangeCatalogEntryPartCmd interface and /CatalogEntry[]/ParentCatalogGroupIdentifier XPath expression.

For invalidation purposes, as part of the command implementation, it will keep a Collection object that records all the related nouns that have changed. The collection is returned by a method on the command, for example getModifiedCatalogGroups(), which can be used by the cache invalidation policy. The suggested naming convention for these get methods is getModifiedNounNames to explicitly declare the different related nouns that are effected as part of this action command.

Creating the related noun invalidation policy

Once the command returns a collection of related Noun UniqueID that can be modified, the next step is to update the cachespec.xml of that service module with the invalidation command. The cachespec.xml is the same one used for registering the invalidation policy for the BOD controller commands.

The invalidation policy is very similar to the policy defined for the Change, Process or Sync controller commands. Set the delay-invalidation property to true, the method returns a collection of UniqueID to invalidate instead of one. The difference is that the method invoked is the custom getModifiedNounNames() method instead of the generic getUniqueID.

The following XML sample is an example of a custom invalidation policy for an action command that changes the Catalog Group relationship of a Catalog Entry:
<cache-entry>
	<class>command</class>
	<name>com.ibm.commerce.catalog.facade.server.commands.ChangeCatalogEntryParentCmdImpl</name>	
	<property name="delay-invalidations">true</property>
	<invalidation>categoryId
		<component id="getModifiedCatalogGroups" type="method" multipleIDs="true">
			<required>true</required>		
		</component>
	</invalidation>
</cache-entry>

Where a custom method, getModifiedCatalogGroup, is used to invalidate related catalog groups.

Catalog SOA commands invalidation rules for all stores

The following is an example of how to set up the invalidation rules for the new Catalog SOA commands for all stores. To use these rules, the cache entries define in this file need to be merged into the cachespec.xml file for caching the JSP pages and fragments.
Note: The following snippet is contained in the WC_installdir\samples\dynacache\invalidation\catalog\cachespec.xml file. However, this file cannot be used directly, as it does not contain the cache element.

<!-- This list of unique IDs is to indicate which Catalog nouns have been involved with the change/process -->
<!-- request and requires to be invalidated.                                                               -->

<cache-entry>
       <class>command</class>
       <name>com.ibm.commerce.catalog.facade.server.commands.ChangeCatalogCmdImpl</name>
  <name>com.ibm.commerce.catalog.facade.server.commands.ProcessCatalogCmdImpl</name>
       <property name="delay-invalidations">true</property>
       <invalidation>catalogId
              <component id="getUniqueID" type="method" multipleIDs="true">
                     <required>true</required>              
              </component>
       </invalidation>
</cache-entry>

<!-- This list of unique IDs is to indicate which CatalogGroup nouns have been involved with the change/process                        -->
<!-- request and requires to be invalidated.                                                                                           -->
<!-- The catalog id can be used to invalidate related pages when a catalog group is updated.                                           -->
<!-- For example, when the name of a category is renamed (categoryId=50400000003), the CategoryDisplay page for this category needs to -->
<!-- invalidate:                                                                                                                       -->
<!-- CategoryDisplay?catalogId=504&categoryId=50400000003                                                                              -->
<!-- Since the CategoryDisplay pages for its parent category (categoryId=50400000013) and sibling categories (categoryId=50400000014)  -->
<!-- also display the name of the category, they also need to invalidate.                                                              -->
<!-- CategoryDisplay?catalogId=504&categoryId=50400000013                                                                              -->
<!-- CategoryDisplay?catalogId=504&categoryId=50400000014                                                                              -->

<cache-entry>
       <class>command</class>
       <name>com.ibm.commerce.catalog.facade.server.commands.ChangeCatalogGroupCmdImpl</name>
  <name>com.ibm.commerce.catalog.facade.server.commands.ProcessCatalogGroupCmdImpl</name>
       <property name="delay-invalidations">true</property>
       <invalidation>categoryId
              <component id="getUniqueID" type="method" multipleIDs="true">
                     <required>true</required>              
              </component>
       </invalidation>
       <invalidation>catalogId
                     <component id="getCatalogId" type="method">
                            <required>true</required>
                     </component>
       </invalidation>
</cache-entry>

<!-- This list of unique IDs is to indicate which CatalogEntry nouns have been involved with the change/process -->
<!-- request and requires to be invalidated.                                                                    -->
       
<cache-entry>
       <class>command</class>
       <name>com.ibm.commerce.catalog.facade.server.commands.ChangeCatalogEntryCmdImpl</name>
  <name>com.ibm.commerce.catalog.facade.server.commands.ProcessCatalogEntryCmdImpl</name>
       <property name="delay-invalidations">true</property>
       <invalidation>productId
              <component id="getUniqueID" type="method" multipleIDs="true">
                     <required>true</required>              
              </component>
       </invalidation>
</cache-entry>

Sample catalog invalidation

Copy the contents of the WC_installdir\samples\dynacache\invalidation\catalog\cachespec.xml file to the end of the WAS_installdir\profiles\instance_name\installedApps\cell_name\WCServer_enterprise_archive\Stores.war\WEB-INF\cachespec.xml file immediately preceding the </cache> element.

Starter stores do not demonstrate how to invalidate related nouns. For example, if a product name is changed the product details page invalidated, but the category page containing the product name is not. You can invalidate cached related objects using these approaches:
  1. Time-based invalidation

    This approach is easy to implement, but could leave some entries stale for a period of time. For an example, see the MiniShopCarDisplay.jsp entry in the Madisons starter store cachespec.xml file. For information see, Time-based invalidation in the Cache invalidation topic.

  2. Database triggers on the CACHEIVL table

    For information see, Dynacache API and CACHEIVL table invalidation in the Cache invalidation topic.

  3. Custom Java code to issue invalidation messages using Dynacache APIs.

    This approach requires a good understanding of Dynacache APIs. For information see, IBM WebSphere Application ServerTM, Release 7 API Specification: Dynacache API and Mastering DynaCache in WebSphere Commerce.