Thursday, 23 October 2014

When JSP coding turns Dyncache into a nightmare



The two code samples below looks very similar and they both work fine when tested in a local development environment without caching enabled. But once WebSphere Dynacache is enabled, the first code sample will start causing weird effects on front end. To be more specific, on first access to the page, the content that is generated by CategoryRecommendation.jsp will render correctly without problems, but subsequent access (e.g. page refresh) which is supposed to fetch content from cache, the content will suddenly disappear.

Whenever you see this issue, first thing to look for is your JSP flush which needs to be positioned exactly before and after c:import without anything in-between.

That is one of the reasons I personally prefer to use jsp:import as you can pass flush as an attribute to the tag and you don't have to worry about doing such a mistake.

Code sample 1

<%out.flush();%>
<c:import var="fscontent" url="/ArgSharedStore/Widgets/Tmpl/ESpot/CategoryRecommendation/CategoryRecommendation.jsp">
<c:param name="emsName" value="${spotName}" />
<c:param name="cacheWithParent" value="false" />
<c:param name="catalogId" value="${catalogId}" />
<c:param name="align" value="${align}" />
</c:import>
<c:out value="${fscontent}" escapeXml="false" />
<%out.flush();%>



Code sample 2

<%out.flush();%>
<c:import var="fscontent" url="/ArgSharedStore/Widgets/Tmpl/ESpot/CategoryRecommendation/CategoryRecommendation.jsp">
<c:param name="emsName" value="${spotName}" />
<c:param name="cacheWithParent" value="false" />
<c:param name="catalogId" value="${catalogId}" />
<c:param name="align" value="${align}" />
</c:import>
<%out.flush();%>

<c:out value="${fscontent}" escapeXml="false" />


Friday, 19 September 2014

Some insights into WebSphere Dynacache

Let's assume the following scenario:

  • You have two JSPs, a parent JSP called parent.jsp and a child which it dynamically includes a child JSP called child.jsp.
  • Child JSP requires one parameter to function properly and you need this parameter to be passed with user request to generate some dynamic content that doesn't depend on cache. Let's assume this parameter is called action1.
  • You want to cache the parent but you don't wish to cache the child/
  • The cachespec.xml is defined something as shown below.

<cache-entry><class>servlet</class><name>/StorefrontAssetStore/parent.jsp</name><property name="do-not-consume">true</property><property name="save-attributes">false</property><property name="consume-subfragments">true</property><cache-id><component id="someparam" type="parameter"><required>true</required></component></cache-id></cache-entry>
<cache-entry><class>servlet</class><name>/StorefrontAssetStore/child.jsp</name><property name="do-not-consume">true</property><property name="do-not-cache">true</property>
<property name="save-attributes">false</property><property name="consume-subfragments">true</property><cache-id><component id="action1" type="parameter"><required>true</required></component></cache-id></cache-entry>

Now, when you are developing the JSPs, you will most probably dynamically include the child from the parent as follows:

<jsp:include page="child.jsp" flush="true"><jsp:param name="action1" value="${param.action1}"/>
</jsp:include>

So question is, will this work as intended ? parent.jsp cached once and child.jsp is dynamically invoked with every request with a fresh value for action1 ?

Unfortunately, this will not happen and despite the child JSP is not cached, it will behave as if it is cached.

Why ?

Things will be more clear, if you opened WebSphere Cache monitor and checked how parent JSP is cached in first place, you will notice something as the below in its cache content:

[include: /StorefrontAssetStore/child.jsp?action1=somevalue]


Which means, whenever parent JSP is accessed from cache, it will dynamically call child JSP but within all calls, it is always passing one cached value which is <somevalue>

So how to get over this ?

Simply, your parent JSP needs to look something as below:


<jsp:include page="child.jsp" flush="true"/>

and within child JSP make sure you always access action1 using param.action1. This will ensure that child JSP is completely free from cache content and able to pickup parameters properly each time from the request stream and do something different each time.