Typically when servlet caching is enabled in WCS for Store JSPs, top level browsing pages like ProductDisplay, CategoryDisplay, HomePage are cached. These pages are cached on the input parameters to the view.
For example, ProductDisplay view will be cached on productId or partNumber, storeId, langId, catalogId. Once the page is cached, the next step is to identify the dependency Id's based on the content displayed by the view, so that the cache can be invalidated whenever the content of the page changes.
So for example, if page displays both offerPrice and listPrice, then dependency Id's will be added for each price, so that even if one of the price changes entire cache gets invalidated.
Prior to Feature Pack 7, the ProductDisplay page was built by IT team and they typically updated the cachespec.xml to add dependency ids, cache attributes etc., based on page contents.
But starting with feature pack 7, business users have ability to use commerce composer to modify the page contents ( add / remove widgets ) as well as schedule the priority, start date / end date for the layouts. Which means, ProductDisplay page dependency Id's cannot be statically added to cachespec.xml during Code and UT phase. The dependency Id's needs to be added dynamically at runtime based on the layout attributes set by business users.
WebSphere Application Server cache module provides a way to programmatically decide whether to cache a page or not and also to add dependency Id's and set cache time out values at run time. This is achieved through MetaDataGenerator class and <metadatagenerator> tag in cachespec.xml.
WCS makes use of this feature to manage the cache properties dynamically at runtime.
So a new class com.ibm.commerce.pagelayout.cache.PageDesignMetaDataGenerator is created and following tag is added to top level cache entries in cachespec.xml
<metadatagenerator>com.ibm.commerce.pagelayout.cache.PageDesignMetaDataGenerator</metadatagenerator>
PageDesignMetaDataGenerator gets executed for every request. This metaDataGenerator class will identify all the eMarketing Spots and activities responsible for displaying the layout. (Commerce composer uses Marketing runtime under the hood to associate layouts with pageObjects like product pages, category pages, static pages). Once the eMarketingSpots are identified, it checks if these eSpots are static or dynamic in nature. If the eSpots are static then metaDataGenerator decides to cache this page and sets the timeOut value based on the eSpot attributes. If the eSpot is dynamic then metaDataGenerator makes it non cacheable request.
Since business user have the ability to change the layout (add widget, remove widget, change widget properties ) using composer tool, the cache needs to be invalidated dynamically as and when business user changes the layout.
Communication between composer tooling and layout cache happens through dependency id's and invalidation id's. Whenever business user modifies the layout, pageLayout:<layoutId> dependency id is published by the composer tool.
The cache entry will have pageLayout:<layoutId> as one of it's invalidation id. So when dependency Id pageLayout:<layoutId> is published, the cache gets invalidated.
But how will someone add pageLayout:<layoutId> as invalidation Id to the cache entry ? Obviously it cannot be added statically in cachespec.xml, since layoutId is determined at runtime.
One option is to make use of MetaDataGenerator to identify the layoutId. But as we know, MetaDataGenerator gets executed for every request ( even if request is eventually served from cache ). So identifying the layoutId by executing pageDesign handler in metaDataGenerator for every request is very expensive operation and defeats the whole purpose of caching.
This is where <wcpgl:pageLayoutCache> JSTL tag comes into picture. This tag needs to be included on every layout JSP page. This tag makes use of the pageDesign object available in JSP and retrieves the layoutId from pageDesign object. It adds pageLayout:<layoutId> as one of the dependency id to the cache entry. Since layout details already fetched in the JSP, the tag doesn't make any additional service call. Also when the request is served from cache, the JSP never gets executed and hence there is no overhead with this approach.
So in summary, whenever layout JSP ( the top level JSP, which has an entry in struts-config-ext.xml + makes a call to pageDesign object to retrieve the layout information ) is cached, the following additional steps should be done:
1) Add <metaDataGenerator> tag to the cache entry in cachespec.xml - This tag decides whether to cache the request or not. If cached, adds timeOut value and emsName:<name> as one of the dependency id. This helps to invalidate the cache whenever layout association changes.
2) Add <wcfpgl:pageLayoutCache> into JSP - This tag adds pageLayout:<layoutId> as one of the dependency id, so that when layout design changes, the cache gets invalidated.
No comments:
Post a Comment