Today's caching example moves us away from the template cache and into the object cache. I defined these two types of caches on day three of this series but let's revisit the definitions. The template cache in ColdFusion 9 refers to a specific area of cache where page fragments and full page cache items are stored. The object cache refers to anything cached except pages including strings, arrays, ColdFusion components, queries, XML, or the like.
Let's look at a simple example that illustrates the use of three new functions in ColdFusion 9: cachePut(), cacheGet(), and cacheGetMetadata().
metadata at the same time. --->
<cfset cachedData = cacheGet("wt-6-cache")>
<!--- If the data is not cached, create it and do a cache put. --->
<cfif isNull(cachedData)>
Cache doesn't exist, so create it.<br />
<cfset sleep(1000)>
<cfset cachedData = "This date/time IS cached: #Now()#<br />">
<cfoutput>#cachedData#</cfoutput>
<cfset cachePut("wt-6-cache", cachedData, CreateTimeSpan(0,0,0,10))>
</cfif>
<cfoutput>This date/time is not cached: #Now()#</cfoutput>
<h4>Cached data</h4>
<cfdump var="#cachedData#">
<h4>Cached metadata</h4>
<cfdump var="#cacheGetMetadata('wt-6-cache')#">
The concept illustrated here creates a result similar to the example from day three. The difference between the two is the cache type used. Instead of caching a page fragment with a displayed date/time, we simply cache the date/time string in object cache. The first bit of code in the code block attempts to retrieve an item from object cache with the key "wt-6-cache." If there isn't an item in object cache matching the key, the cacheGet() function returns null. The second bit of code uses the new isNull() function (bonus!) to check the result of the cacheGet() function. If the item isn't cached we simulate a slow page with the sleep() function, output a simple date/time string, and then call the cachePut() function. This function has two required parameters, cache ID/key and cache value, followed by two optional parameters cache timespan and idletime. The signature of the function looks like this: cachePut(id, value[, timeSpan[, idleTime]]).
Next, we use the <cfoutput> tag to display a date/time string that isn't cached. Then, we use the <cfdump> tag to display the contents of the cache. And finally, we use the new cacheGetMetadata() function inside a <cfdump> tag to display cache metadata for the cached value with key "wt-6-cache."
The first time you execute the page the output looks like this:

The cacheGet() function returns null since the item has never been cached. This also causes the isNull() function to evaluate to true which in turns causes the string "Cache doesn't exist, so create it." to display. Two date/times are displayed, the first one coming from the <cfoutput> just before the cachePut() function and the second which will display every time the page is loaded. At the bottom of the page is the metadata that comes from the cacheGetMetadata() function. Here's a list describing each piece of metadata.
Caching terminology:
- cache hitcount - number of times a cache hit has occurred for any item in the cache
- cache miscount - number of times a cache miss has occurred for any item not in cache or that was stale
- created time - the date/time the cached item was created
- hitcount - number of times the cached object has been requested and was used
- idletime - the cache idletime as set in the cachePut() function
- last hit - the date/time the cached item was last requested/used
- last updated - the date/time the cached item was last modified
- size - number of bytes the cached item occupies when serialized
- timespan - the cache timespan as set in the cachePut() function
If you run the template a second time before the timespan of 10 seconds expires you'll see output that looks like this.

Here we don't see the string "Cache doesn't exist, so create it.," and only two date/times appear. The first one isn't cached, and the second comes directly from the cache showing different times. Notice how the cache metadata has changed too. The cache_hitcount value increased by one showing us that all cache hits increment this data point. The regular hitcount value also increased by one showing us this value increases each time a cached item is retrieved. Note, that when the cache timespan (or idletime if defined) is reached the cached item will be removed from cache and the hitcount value reset to zero. Finally, we also see the lasthit value now has a date/time and the date/time matches the one at the top of the page.
If you allow this specific cached item to expire a few times and you hit the page again and again you'll eventually create metadata that looks like this.

Here you can see the cache_hitcount value continue to rise as we retrieve the item with cacheGet(). The cache_miscount value has also increased to show how may times the cache has expired and been requested again. If you haven't realized by now how much more metadata you have when using object cache versus template cache you should. You can use this additional metadata to analyze cache items and determine their validity as well as ensure your cache timespan and idletime are values that optimize cache hits and minimize cache misses.
The object cache is also much more flexible than template cache. You can store anything you want and you have control over the cache key name giving you the ability to be more creative and descriptive. However, remember that template and object cache on ColdFusion 9 occupy memory space (Java Virtual Machine or JVM) by default. If you have multiple applications or users on your server you want to be careful when creating names for your cache keys as you could create a collision with an existing cache item. If this were to happen you could read incorrect and unsuspected values from cache or worse yet, replace an item in cache with unrelated data.
Click here to download the code mentioned in this post.














I thought that ColdFusion was creating a different EHCache CacheManager for each application, based on your defaultCache settings (defined in ehcache.xml).
But I'm not sure...
So, by default you have two caches and when they are created at startup time they have the names appnameOBJECT and appnameTEMPLATE. So yes, two different applications can use the same key name for a specific cached item and they won't collide with one another. But, they are effectively stored in the same cache region. I'm simply recommending folks be careful with their names and be mindful of what keys are used where. Even if you can't collide across applications, you can within an application and that's still just as bad.
getCacheKey( id )
... and then use result of that to do the cachePut() / cacheGet() calls.
This kept the intent and the implementation seperate and made retrieving stuff from the cache in different places easier (at least for me).