Configure caching policies for portlets
Fragment caching for portlets requires defined a cache policy in a cachespec.xml file, either within the portlet WAR file or globally. If no caching policy is defined and applicable to a particular portlet, that porlet is not cached.
WebSphere Application Server caching policies provide a lot of flexibility for defining cache IDs and invalidation rules that match the specific requirements of individual portlets. The caching policies that we can define are not necessarily compliant with the caching behavior that is defined by the Java Portlet Specification. The following sections provide some recommendations on how we can exploit the features of cachespec.xml file, to define a caching policy that conforms to the specification.
Cache expiration. Portlets define cache expiration time in the <expiration-cache> element of the portlet.xml deployment descriptor. If this element is not present, or has a value of zero, the portlet is not cached. The cache expiration time for portlets is only defined in the deployment descriptor; any cache timeout values specified in a cachespec.xml file have no effect.
Caching scopes. Portlets are defined in the <caching-scope> element of the portlet.xml deployment descriptor, whether the portlet content should be shared across all users or whether it contains user-specific information and must be cached individually for each user. To maintain this setting in your caching policy definition, include the com.ibm.wsspi.portletcontainer.user_cache_scope attribute in the cache key, with the following cache key component:
<component id="com.ibm.wsspi.portletcontainer.user_cache_scope" type="attribute"/>This attribute has the following values:
- The value, public, in a portlet that defines public cache scope.
- The current logon user ID in a portlet that defines private cache scope.
- Null (anonymous) in a portlet that defines private cache scope if no user is logged on.
To cache portlet content for anonymous access, even in a portlet that defines private cache scope, add <required>false</required> to the cache key component. This implies that all anonymous browser access will retrieve the same cache content.
Portlet lifecycle methods. The Java Portlet Specification defines the four lifecycle phases: action, event, render and resource for running in a portlet. Only the render and resource phases produce content; the action and event phases invoke portlet activity without generating content and must not be cached. The lifecycle phase for a portlet call is available in the javax.portlet.lifecycle_phase request attribute. Check for the correct lifecycle by including the following cache key component:
<component id="javax.portlet.lifecycle_phase" type="attribute"> <value>RENDER_PHASE</value> </component>This cache key component only caches render requests to the portlet. Cache additional resource requests by adding the RESOURCE_PHASE. In many cases, the best approach is to define a separate <cache-id> element for resource requests. The resource ID is available in the com.ibm.wsspi.portletcontainer.resource_id request attribute for caching key generation in resource requests.Request parameters. Portlets can typically display multiple views. Render parameters distinguish which view displays. Each combination of parameters addresses a different view of the portlet. All views need to be cached separately; therefore, the full request parameter map should normally be included in the cache key. The com.ibm.wsspi.portletcontainer.all_parameters attribute provides a unique value for the content of the full request parameter map that can be used with the following cache key component:
<component id="com.ibm.wsspi.portletcontainer.all_parameters" type="attribute"> <required>false</required> </component>If we write a cache policy for a specific portlet, and you know exactly which views of the portlet are addressed by which request parameters, it is usually more efficient to use specific <parameter> elements in the cache key to cache only the most important views of the portlet.Other cache key components. Depending on your usage scenario, we will need to include other information in the cache key, if the returned content depends on it (for example, the portlet mode and window state, or the request locale in a multi-language portal). In a multi-device portal that supports different markup types, the returned content type should also be part of the cache key. The content type for a portlet is available in the com.ibm.wsspi.portletcontainer.response_contenttype request attribute.
Cache invalidation. The Java Portlet Specification states that action and event requests to a portlet must invalidate all currently cached content. The portlet caching definitions usually allow for caching multiple views of a portlet at the same time. To invalidate all of them, use the dependency ID mechanism of cachespec.xml.
Define a common dependency ID for all views that should be invalidated by an action. The common ID will usually only include the portlet window ID and the user scope, so that a portlet action does not affect private cache entries for other users:
<dependency-id>action <component id="" type="portletWindowId"/> <component id="com.ibm.wsspi.portletcontainer.user_cache_scope" type="attribute"/> </dependency-id>Define an invalidation rule that repeats the dependency ID and adds the current lifecycle method as a condition. It is essential to have the ignore-value attribute on the condition part. The lifecycle attribute must not be part of the returned invalidation ID, because that invalidation ID must match exactly with the dependency ID previously specified.
<invalidation>action <component id="" type="portletWindowId"/> <component id="com.ibm.wsspi.portletcontainer.user_cache_scope" type="attribute"/> <component id="javax.portlet.lifecycle_phase" type="attribute" ignore-value="true"> <value>ACTION_PHASE</value> <value>EVENT_PHASE</value> </component> </invalidation>Following the same pattern, specify more complex invalidation rules in caching policies for individual portlets, (for example, we can only invalidate a subset of the portlet views for specific actions that are determined by request parameters). The following example code describes a generic caching configuration that conforms to the behavior that is defined by the Java Portlet Specification:
Sample cachespec.xml file <?xml version="1.0" ?> <!DOCTYPE cache SYSTEM "cachespec.dtd"> <cache> <cache-entry> <class>portlet</class> <name>MyPortlet</name> <property name="consume-subfragments">true</property> <cache-id> <component id="" type="portletWindowId"/> <component id="com.ibm.wsspi.portletcontainer.user_cache_scope" type="attribute"/> <component id="" type="portletWindowState"> <!-- minimized portlets are not cached --> <not-value>minimized</not-value> </component> <component id="" type="portletMode"/> <component id="" type="locale"/> <component id="com.ibm.wsspi.portletcontainer.response_contenttype" type="attribute"/> <component id="com.ibm.wsspi.portletcontainer.all_parameters" type="attribute"> <required>false</required> </component> <component id="javax.portlet.lifecycle_phase" type="attribute"> <value>RENDER_PHASE</value> </component> </cache-id> <dependency-id>action <component id="" type="portletWindowId"/> <component id="com.ibm.wsspi.portletcontainer.user_cache_scope" type="attribute"/> </dependency-id> <invalidation>action <component id="" type="portletWindowId"/> <component id="com.ibm.wsspi.portletcontainer.user_cache_scope" type="attribute"/> <component id="javax.portlet.lifecycle_phase" type="attribute" ignore-value="true"> <value>ACTION_PHASE</value> <value>EVENT_PHASE </value> </component> </invalidation> </cache-entry> </cache>
Troubleshooting tips for the dynamic cache service