Using the Cache
servlet bean can save a lot of time when you use it properly. When used incorrectly, it can slow rendering of a Java Sever Page and even cause the page to display incorrect data. It is important to understand how Cache
works in order to avoid mistakes that can slow your pages or make them wrong.
(If you are not familiar with Cache
, you may want to read more about it in Appendix B: ATG Servlet Beans of the ATG Page Developer’s Guide.
Let’s examine an example where Cache
actually slows down your web site. The following example uses Cache
on a page called hello.jsp
:
<dsp:droplet name="Cache"> <dsp:oparam name="empty"> Hello world! </dsp:oparam> </dsp:droplet>
Cache
stores the value “Hello world!” in its cache so that future retrievals can come from that cache. This is not a good place to use Cache
from an efficiency point of view. Without Cache
, the Java code generated to print a static string is very fast and simple. The use of Cache
in this example causes an unnecessary servlet invocation and the unnecessary storage of more bytes. The Cache
servlet bean is only useful when you are caching dynamic content.
Here is another example in which Cache
causes incorrect results. The dynamic pricing engine is among the most “costly” pieces of functionality used in the Pioneer Cycling Store JSP code because it calculates pricing on the fly and can run slowly. Determining a dynamic price for each SKU personalized for each user takes many more computation resources than finding and displaying static prices. It is dynamic, so one way to make it run faster is to cache it. Every SKU has a different price, so you can use the SKU ID as a key into the cache.
<dsp:droplet name="/atg/dynamo/droplet/Cache"> <dsp:param name="key" param="Sku.repositoryId "/> <dsp:oparam name="output"> <dsp:droplet name="/atg/commerce/pricing/PriceItem"> <dsp:param name="item" param="Sku"/> <dsp:param name="elementName" value="PricedSku"/> <dsp:oparam name="output"> <dsp:droplet name="/atg/dynamo/droplet/Compare"> <dsp:param name="obj1" param="PricedSku.priceInfo.ListPrice"/> <dsp:param name="obj2" param="PricedSku.priceInfo.amount"/> <%/*ListPrice is greater, so display it first in strikout mode: */%> <dsp:oparam name="greaterthan"> <span class="strikeout"> <dsp:valueof converter="currency" param="PricedSku.priceInfo.ListPrice"/> </span> </dsp:oparam> </dsp:droplet> <%/*Display their price: */%> <dsp:valueof converter="currency" param="PricedSku.priceInfo.amount"/> </dsp:oparam> </dsp:droplet> <%/*PriceItem droplet*/%> </dsp:oparam> </dsp:droplet>
In this code example, Cache
caches a string representing the formatted price of the SKU, for example, “$42”. It is much faster to let Cache
render the string “$42” than to let the PriceItem
servlet bean calculate a price, so caching this string seems like a good idea. However, PriceItem
calculates personalized prices, so if a user has a promotion for 20% off everything and he is the first to invoke the cached PriceItem
for SKU123, then his price is cached and even users who don’t have the 20% off promotion see that price.
A solution might be to key the cache a combination of the profile ID and the SKU ID. The problem remains that the string manipulation needed to construct a key out of those two pieces of data would cost time and that the hit ratio on such a cache would likely be so low as to render the cache useless. Worst of all, if the user is granted a promotion before the cache times out, the user sees the incorrect price.
Another situation to consider is caching content that contains links. In order to perform session tracking, the session ID must be carried by every HTTP request either in a cookie or in the URL link, and inserted by on-the-fly link rewriting. Cache
cannot cache content that needs to have link rewriting performed on it. If you choose to use Cache
to cache content that contains links and if a good portion of your user population does not accept session cookies, then invoking Cache
on content that contains link wastes time.
We have now explored in detail some situations where you should not use the Cache
servlet bean:
When the content is static.
When the cached content would be incorrect for the situation.
When it takes more time to construct the key than to render the content.
When the cache hit ration would be low.
When link rewriting is required.
You should use Cache
when the string you would use for a key is readily available and the content is always the same for each key. You should also use Cache
when the content either contains no links or the when the bulk of the user population is expected to accept session cookies.