Rob Brooks-Bilson
Tech, Photography, Stuff
Tech, Photography, Stuff
August 9, 2010
I submitted a bug for this but the system seems to have swallowed it up without giving me the bug number (probably because I submitted as cf 9.0.1).
I've found what I consider to be a serious bug an issue with ColdFusion's
ehache implementation and query objects that may bite you if you're not aware of how it works. If I take a query object and stick it in cache, then perform an operation on the original query
object such as adding a column or performing certain query of query
operations, ColdFusion is treating the query object that's in cache as
if it were a copy by reference to the original query object. That is,
if I make a change to the original query object, ColdFusion is also
applying the change to the version that's in cache.
As far as I'm concerned, cache represents a boundary that ColdFusion
should not implicitly cross. With most caching systems I've worked with in the past (such as memcached), the cache always acted as a dumb key/value store. Unless I perform an explicit cachePut(), I wouldn't expect that CF would update values in the cache. Here's
two code snippets that reproduces the case. The first uses the
cfartgallery data source:
The second example shows how this can be done with a query of a query, based on a different bug Ray found previously (see http://www.coldfusionjedi.com/index.cfm/2009/8/28/Another-example-of-the-QofQ-Bug). In this sample, note that the date gets reformatted by the query of a query and both the original query and the cached version get updated:
The work around for this problem is to use the duplicate() function to make a clone of the query object before doing the cachePut(). Although this works, there are other potential consequences from having two copies of the query around, so be careful.
Update: It looks like this is actually expected behavior in Ehcache. Unfortunately, it's not documented in the ColdFusion documentation anywhere, but Ehcache actually has two configurable parameters (as of v. 2.10) called copyOnRead and copyOnWrite that determine whether values returned from the cache are by reference or copies of the original values. By default, items are returned by reference. Unfortunately we can't take advantage of these parameters right now as CF 9.0.1 implements Ehcache 2.0.
I can live with this, but it's not what I expected as I've always viewed Ehcache as a "dumb" key-value store and certainly didn't expect this behavior. Even if ColdFusion was running v 2.10 of Ehcache, it's still not something we could easily configure. Since ColdFusion currently doesn't have a cacheNew() function for creating new user-defined cache regions, the only way to turn this functionality off would be to hard-code your cache configuration in your ehcache.xml file for each user-defined region where you want to disable copyOnRead and copyOnWrite.
August 5, 2010
ColdFusion 9.0.1 added a new function called cacheGetSession() that returns the underlying cache object for Ehcache. What's really cool about this is that it allows you to get at just about all of the features available in Ehcache that aren't directly exposed to ColdFusion through built-in functions.
I was recently working on some example code for an upcoming caching presentation when I ran into a situation where I wanted to get a list of all caches that had been created on the server, including custom caches I had created myself. One simple line of code is all it took:
What you should note here is that even though I'm telling cacheGetSession() to get the cache object for the default object cache, getCacheManager() exposes a method called getCacheNames() which returns an array of cache names for the instance of cache manager. In the case of ColdFusion's Ehcache implementation, ColdFusion instantiates cacheManager as a singleton such that all caches are managed by the single cache manager. When you call getCacheNames(), it will return you a list of all caches currently implemented on the instance of ColdFusion.
While this may not be an issue for many people, if you are on a shared server it may be a concern. The only way to disable this is to disable the cacheGetSession() function using sandbox security.
July 27, 2010
If you've been following my series on caching in ColdFusion 9, you know that ColdFusion 9.0 includes the powerful caching platform Ehcache from Terracotta. What you may not know, though, is that in ColdFusion 9.0.1 Adobe upgraded the Ehcache engine from version 1.6 to 2.0. This brings several new caching capabilities to ColdFusion and makes them dead simple to implement. If you're interested in learning more, Mike Allen from Terracotta and I are presenting a webinar on August 12, 2010 at 11am Pacific time. Here's the official announcement:
Join me and Mike Allen, the head of product management at Terracotta in a discussion about simple and effective ways to scale and boost the performance of ColdFusion applications using Ehcache.
In this webcast, you'll learn:
Please register for this webcast even if you are unable to attend and you will get an email with a link to the recording.
January 28, 2010
Now that ColdFusion 9 has been out for a few months, I've compiled a list of issues around caching that I'd like to see addressed in ColdFusion 9.0.1 or Updater 1. These are all issues that haven't already been discussed elsewhere or filed by others as bugs/enhancement requests.
To get the ball rolling, I'm listing each of the issues here along with the bug/enhancement number for the corresponding issue I filed in Adobe's ColdFusion Bug Database.
I have some additional things I'd like to see such as cache cluster configuration withing the CF Admin and an upgrade to Ehcache EX so that we can do true distributed caching within ColdFusion, but I'll address those items in a later post. For now, here's my list. I'm interested to hear how others are doing with the new caching in ColdFusion 9.
This error only happens if you have RMI enabled in ehcache.xml and you aren't connected to a network. I don't expect this would ever be a problem in a production environment, but it could pop up on development machines – especially if people develop disconnected. At a minimum, I'd like to potentially see a more meaningful error message (even though you can narrow it down to RMI via the stack trace).
You can change this to any path you want in ehcache.xml and it applies globally.
The ColdFusion documentation for the cacheSetProperties() tag currently shows that diskstore is a valid option:
http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7c18.html
My testing, however, has shown that is not working in the shipping build of ColdFusion 9. Try the following example (you'll need to create a directory off your root, c:/temp):
Before:
After:
If you run this code and check the c:/temp directory you should find it empty. Check your jave temp directory (c:/windows/temp on wintel) and you'll see that the files are still written there showing that the default value in ehcache.xml is being used and not the value being set in the cacheSetProperties() function.
The obvious action is to remove this attribute from the documentation until it can be implemented in a later version of ColdFusion. I would like to see it implemented, though, as I think it's useful to be able to set the diskstore location programmatically.
What this actually returns to you is a structure with two sets of information:
Cache_hitcount and cache_misscount apply to the overall cache. In other words, how many hits and misses the entire cache have received. The rest of the keys returned in the structure apply to the item passed in to the cacheGetMetadata() function.
I see a couple of potential issues with how this has been implemented. What I think we really need is two separate functions here. The existing cacheGetMetadata() should return just the metadata that is specific to the item passed to the function, not metadata on the entire cache. I would expect a separate function to retrieve metadata for the cache itself. To avoid confusion, I'd call the new function something like cacheGetStats(). In my mind it would return the cache_hitcount and cache_misscount that are currently returned by the cacheGetMetadata() function. It would also return a whole lot more that's available from ehcache but not exposed to ColdFusion – things like the total number of items currently in the cache, total size in bytes of all of the items in the cache, etc.
This creates a cache region at runtime called customCache. Getting, putting and flushing the cache are all supported from the cfcache tag. However, it's not currently possible to use any of the caching functions to operate on the custom cache region because there is no way to specify which cache region you want to use – the functions always apply to the default object or template cache.
I'd like to propose adding an optional attribute to all cache functions to allow a developer to pass in a custom cache region (key) for the function to operate against where applicable.
Using a function instead, you use cacheRemove():
Consider the following example:
If you execute this, you'll get some output as well as a dump of all of the cached items in the template cache (getalltemplatecacheids is an undocumented function). At this point, there are two items in the cache:

Now say you weren't happy that the two lines of output on your page were all run together and you wanted to put a line break between each one. You might modify your code and add in a simple paragraph tag or line break like so:
Go ahead and run the code once you've inserted the <p> tag. What you'll now see is that you have three items in the cache:
What's happening is that ColdFusion is using the position of the code in your page as part of the ID for the cached item. When you inserted the <p> tag, the position of the fragment you cached also changed by moving down a few lines, and ColdFusion assumed you had added a new page fragment that you wanted to cache.
This may or may not be a big deal to people as CF will still pull the correct cached item every time. The gotcha is that if you have a lot of caching going on, and you're making a lot of changes in a development environment, it's possible to fill your cache up with a lot of junk pretty quickly.
I'm not making any statements on how this feature was implemented - I just want to make people aware of how the template cache works under the covers since it's not documented and if people are paying attention when they are developing they might see some things with the template cache that don't make sense if they don't know how it works.
diskSpoolBufferSizeMB: This is the size to allocate the DiskStore for a spool buffer. Writes are made to this area and then asynchronously written to disk. The default size is 30MB. Each spool buffer is used only by its cache. If you get OutOfMemory errors consider lowering this value. To improve DiskStore performance consider increasing it. Trace level logging in the DiskStore will show if put back ups are occurring.
clearOnFlush: It determines whether the MemoryStore should be cleared when flush() is called on the cache. By default, the MemoryStore is cleared. Useful is you want to back up a cache to the file system without clearing the MemoryStore.
diskExpiryThreadIntervalSeconds: The number of seconds between runs of the disk expiry thread. The default value is 120 seconds.
I'm not sure why these were left out but it would be nice if they were also included in the configurable properties using ColdFusion functions.
January 14, 2010
You'll have to bear with me here because this is a long one. A few months ago we ran into a problem after upgrading some of our servers to ColdFusion 8.0.1 CHF3 from CHF1. We had an application that integrates with a web service running on a remote .Net/IIS server that started throwing a "Connection Failure" message for code that worked fine pre-upgrade. It turns out that in CF 8.0.1, CHF 2/3 there was a "bug" that was fixed for cfhttp:
72744 Fix for CFHTTP making disable deflate as true by default in the header when CF sends an HTTP request, since compression is not handled by CFHTTP client.
Problem for us is that this fix actually broke code we had previously running. Here are the test cases:
Here we have a CF 8.0.1 server running CHF 3:

Execute this code, where we tell CF to pass in two headers:
Wireshark shows CF appending deflate;q=0 to the * which we told CF to pass. This is what was added in CHF 2/3.

IIS 6 gets this and decides to return the data compressed as you can see in the Content-Encoding:

This time, take out the accept-encoding header:
When you run this, notice that ColdFusion appends all sorts of stuff for the Accept-Encoding header:

The result coming back to CF is again compressed by IIS 6:

Let's try this now with CF 8.0.1 with no CHF (works the same with CHF 1):

Run the code passing in both headers:
Wireshark shows ColdFusion passing in only the accept-encoding value we specified. For the TE trailer, we pass in deflate;q=0 which is supposed to tell IIS not to return deflated (compressed data):

What you see next is what we expect to see. IIS is returning the correct data uncompressed:

Now go ahead and take out the accept-encoding like we did last time:
Notice how CF just passes along deflate, gzip, x-gzip, etc?

IIS gets this and returns the content deflated, which CFHTTP can't handle and we get our error:

One last time. Now for CF 9:

Run the code passing in both headers:
What we see in wireshark is the same thing we just saw for CF 8.0.1 up to CHF1:

Data comes back uncompressed as we expect:

Remove the accept-encoding header:
Same values passed as for CF 8.0.1:

And we get compressed data back (and the error again), as expected:

So, what this long exercise shows me is two things:
I filed a bug report on this and verified the problem with Adobe (there's a bug number but for some reason it isn't showing up in the bug base). They've stated they'll be releasing a fix for it in CHF4 for CF 8.0.1. Just a reminder that this issue does not affect ColdFusion 9.
Thanks go to my coworker Adam Crump for helping to troubleshoot and diagnose the issue.
January 6, 2010

I just received word today that I'll be speaking at cf.Objective() 2010. This is the one ColdFusion conference I've wanted to attend for years now but have never been able to.
If you've been following my blog lately, I've been working on a multi-part series on caching in ColdFusion 9. I also spoke about this topic at Adobe MAX 2009. Caching is something I've been very interested in for the past few years now.
The presentation I'm planning for cf.Objective() is a little different than the one I gave at MAX. There will be some overlap, but the focus of the cf.Objective talk will be on caching for scalability as opposed to a general presentation on caching fundamentals.
I hope to see you there!
November 23, 2009
Welcome to Part 9 of my series on Caching Enhancements in ColdFusion 9. Today we're going to cover something called dependent template caching. Strange name, I know. If you remember back from Part 7, we said that by default, when you cache a web page or page fragment with the cfcache tag, that page/fragment goes into the cache and is retrieved for any subsequent visits to that page. The same content is returned for everyone. We also covered a method for caching pages based on unique URL parameters such that different versions of the same page (say a product display page) would be cached and retrieved from the cache based on URL parameters. But what about page/page fragments that vary based on other variables that aren't passed in via URL? This is where dependent template caching comes in.
Dependent template caching allows you to specify a variable or list of variables to "watch" for changes. If the value of one of these variables changes from the first page or fragment that was cached, ColdFusion will create a new variant for the page/fragment and store that in the cache as well. This is all handled by using the new dependsOn attribute of the cfcache tag in ColdFusion 9. If you are reading this and wondering where this might be useful, you aren't alone. When I first read about this feature in the ColdFusion docs, I misunderstood the intent of the attribute and how it's supposed to work. Here's what the Coldfusion 9 docs have to say about dependsOn:
A comma separated list of variables. If any of the variable values change, ColdFusion updates the cache. This attribute can take an expression that returns a list of variables.
I think the key to the misunderstanding people have about this feature is in the part that says "If any of the variable values change, ColdFusion updates the cache." To me, updating the cache means replacing an old/expired/changed value with a new one. It's a one for one swap of items in the cache. Out with the old and in with the new. But this isn't what happens when you use dependsOn. What the docs should say is that when a variable value changes, ColdFusion creates a new entry in the cache for the changed item so that both the original page/fragment as well as the new page/fragment are now in the cache. Here's a quick example to illustrate how this works:
If you run this code, you should see something that looks like this:

What this code does is create a page fragment and cache it within a loop. The cfcache tag is set to watch a variable called y for changes. The value of y is initially set to true. There's also some conditional code in the loop which waits for the third and fifth iterations of the loop to fire. We'll get to that in just a moment. For now, let's step through each iteration of the loop and discuss what's happening. During the first iteration of the loop, the fragment is added to the cache. During the 2nd iteration of the loop, the fragment is pulled from the cache and displayed. During the third iteration of the loop, the value of x is 3 and our cfif statement fires, updating the value of y to false. Because y is the value we set to watch in the dependsOn attribute of our cfcache tag and it has now changed from true to false, this signals ColdFusion to go ahead and cache the version of the loop output we're now on for iteration 3 of the loop. This is where we end up with a 2nd fragment in the cache, not an update to the existing fragment in the cache. The fourth iteration of the loop also displays the second cached fragment since the value of y is still false. For the fifth and final iteration of the loop, our conditional code within the loop fires again. This time it sets y back to false, a value which we already have a fragment stored in the cache. ColdFusion knows to go grab the fragment for false from the cache and displays it.
There's one other thing to note in here. I didn't think to include this in any of the previous posts on the template cache so I've decided to add it here. If you look at the end of the cfcache tag in our example, you'll notice a parameter you probably haven't seen before: stripWhiteSpace. This is an optional parameter that only works if you are using the template cache to cache page fragments. Setting it to true (it's false by default) tells Coldfusion to strip any unnecessary whitespace from the fragment before storing it in the cache.
While this is a good example of the mechanics of dependent caching, it's not really a practical example. For that, let's consider a real world example where you would want to make use of dependent caching. Say you have an application that requires authentication. The main landing page for the application is personalized based on who is logged in. In this case, you can't cache a single version of the main page as you wouldn't want it to say "Hello Tom" when Mary logs in. Sure you could solve this by passing the username along in the URL, but you probably don't want to do that – who wants to deal with all of the extra validation code to make sure someone doesn't go and change that URL variable to someone else's username. No, in this case, you would probably be using session variables in your application to maintain persistence, and session variables are a perfect use case for dependent caching. Here, we could set dependsOn to watch something that uniquely identifies a user and when that changes (a different user is logged in), the personalized version of the page for them could be added to the cache. Let's take a look at some simple code that implements this idea. The first thing we'll need is an Application.cfc file to setup session management and handle security basics for us:
This code gives our application a name and turns on session management. If also has an onRequestStart() method that looks for a URL variable called logout, and if it finds one it fires off the onSessionStart() method, effectively logging the user out be changing the value of session.loggedIn to false.
The onRequest() method handles the check to see if a user is authenticated for a requested page. If session.loggedIn is true, the page they were requesting is included. Otherwise, we assume that the user is not logged in and include the login form instead.
The onSessionStart() method fires at the beginning of a user's session and sets their logged in status to false by default.
Remember that this is just a simple example and for that reason does not contain all of the code you would use to implement something like this in real life (validation checks, error handling, etc.).
The next file we need is our login.cfm page:
This page is just a simple login form. It firsts checks to see if it was called via a form submit, and if so sets the value of session.loggedIn to true. It also sets another session variable to hold the user's username. After the variables are set, the user is redirected to the main landing page for the application (index.cfm) Again, if this were a real application we would have an actual login check here but for the purposes of this example we're just assuming that any username/password combo is valid.
If the user arrived at the page directly from the onRequest() method of our Application.cfm page, we know that they have not yet logged in so we display a login form for them. When they submit this, the page submits to itself and the code we previously discussed fires, logging the user in and redirecting them to the main application page. Here's the code for the main index.cfm page:
There's not a whole lot going on here. All we do is set a cfcache tag at the top of the page telling ColdFusion that we want to cache the contents of the entire page. A timespan of 5 minutes is set just to keep the example from staying in the cache forever. Notice we also set dependsOn=session.username". This is where the magic happens. What we've done is told ColdFusion is that every time a different user tries to call this page, it should first check the cache to see if there's already a page stored for this user and if so, grab and use that version. If not, it should generate a new version of the page and cache that value for later use.
If you want to see this in action, go ahead and open the index.cfm page in your browser. You should be redirected to the login form. You can enter anything you like for the username and password. Once you submit the login form, you should be redirected to a personalized version of the index.cfm page. Note the value of the timestamp.
Now go ahead and click on the logout link. This will clear your session and cause the login form to display again. Try logging in using a different username this time. After submitting, you'll again be redirected to a personalized version of index.cfm.
Logout again and repeat the process again but this time use the username you entered the first time. When you submit and are taken to the index.cfm page you should notice that the value of the timestamp is the same as the first time you logged in as this user. This is because ColdFusion saw that session.userName changed and found a page in the cache that corresponded to the username you logged in with (the username becomes part of the key for the page in the template cache). If you want to see that there are two distinct pages in the cache, just create a new ColdFusion page in the same directory as the rest of your application and add dump the template cache using this code:
You'll end up with something like this:

As you can see, each individual user has their own copy of the index.cfm page in the cache thanks to dependsOn.
I hope these examples were straightforward and useful enough to demonstrate the usage and power of dependent caching in ColdFusion 9. This is the last post on the template cache I have planned for the series. In Part 10, we'll start to take a look at the object cache in ColdFusion 9 before moving on to more advanced topics.
November 21, 2009
When using the template cache in ColdFusion 9, you have two main options for getting pages and page fragments out of the cache – time based expiry and flushing. This blog post covers both. You should not that all of the examples here cache full pages. In most cases, the techniques discussed can be applied equally to page fragments.
If you run this code and then run it again, you'll see that the timestamp for the page is cached. Now wait for 30 seconds or so and reload again. You should see that the time has updated.
The timespan parameter lets you specify a period of time after which the cached item should be flushed regardless of whether it's ever been accessed or not. This basically lets you say "keep this page in the cache for 30 seconds". Here's an example:
This code sets a timespan of 30 seconds. If you run the code then run it again, you'll see that the timestamp gets cached. Go ahead and keep hitting the reload button on your browser every few seconds. After 30 seconds have gone by, the timestamp will update as the old content is flushed from the cache.
There are a couple of things to note here. First, when you call this code, it flushes all templates in the template cache for your application, not just the page you call it from. Let me repeat that. Using the cfcache tag with action="flush" causes the template cache to flush all of the content for the current application. You need to be very careful using this as it's possible that on a high traffic site with a large template cache you could bring your server down when hundreds or thousands of requests hit at the same time for uncached data, causing your system to queue up requests while it's busy rebuilding the cache. In most cases what you'll want to do is to flush a single page or perhaps a group of related pages from the template cache.
So, how do you go about flushing a single page or a group of related pages from the template cache? There's another parameter of the cfcache tag you can use called expireURL just for this purpose. Let's consider an example of how we would use this:
Go ahead and run this example in your browser. You should have something on your screen that looks like this:
Reloading the page should return the same timestamp over and over as the template is cached after the first call. Now try adding the URL parameter ?productID=72 to the URL string in your browser and reload the page a few times to get the new version of the page into the cache. Try changing the value of productID a few more times, each time reloading the page so that we get a handful of pages in the template cache. Now try dumping the contents of the template cache by running this code in a separate ColdFusion file:
You should see a bunch of different entries – one for each unique productID you provided in the URL. Now go ahead and call the code we've been working with for this example, only this time append ?productID=72&flush to the URL. Go ahead and reload the page with those URL parameters a couple times. Notice the timestamp updating each time you reload? That's because passing in the URL parameter flush calls the ColdFusion page to call the cfcache tag with expireURL="*.cfm?productID=#URL.productID#". The expireURL parameter lets you specify a wild carded URL pattern such that only pages that match the pattern get flushed. This allows you to get as generic or as specific as you want in determining exactly what pages to flush. In this case we're telling ColdFusion to go ahead and flush any cached .cfm pages that have the URL parameter ?productID equal to the value that we pass in on the URL.
If you dump the contents of the template cache you'll notice that there's still an entry for the item(s) we just flushed. That's because the code in the example we've been running repopulates the cache immediately after the flush. If you didn't want the cache repopulated immediately after flushing the content, you could just as easily locate the code to flush the cache elsewhere and just remove the item.
If you want to remove a group of related pages from the cache, say all of the pages that have a productID, you could modify the code to wildcard the productID parameter like so:
This should result in the removal of all pages from the cache that have a productID URL parameter. Note that if you run this right now in ColdFusion 9.0 it will not work. There is a bug in ColdFusion 9.0 with the wildcard feature. If you put the flush code in a separate template and run it multiple times, what you'll see is that one page at a time is flushed from the cache instead of all of the pages that match the URL pattern at once. Credit goes to Aaron West for catching this bug.
That about wraps up everything I have to say about expiring and flushing pages and page fragments from the template cache. In Part 9 we'll talk about one last feature of the template cache – Dependent Caching.
November 20, 2009
In Part 5 of this series, we introduced the template cache with a quick example that showed how to cache page fragments. As we mentioned then, the template cache can be used to cache page fragments as well as entire web pages. This post is broken up into three sections that explore the three typical use cases of the template cache: Caching entire wen pages, caching entire web pages with url parameters and caching page fragments.
With an open cfcache tag at the beginning of the page, this code tells ColdFusion to go ahead and write the entire page to the template cache. If you haven't modified your cache configuration from the default ColdFusion install, this item will live in the cache for 24 hours (86400 seconds) unless you restart your JVM by restarting your ColdFusion server or you manually flush the cache first, which you can do by using the cfcache tag with action="flush" which we'll talk about in the next part of this series.
As I mentioned in Part 5 of this series, the ColdFusion template cache acts as a black box. You don't really get to see how it magically does gets and puts of your content or how it generates keys for the data going into the cache. What I didn't mention before is that there's an undocumented function in ColdFusion 9.0 called getAllTemplateCacheIDs() that will show you all of the keys for items that ColdFusion puts in the template cache. There isn't really a lot you can do with this information since neither the cfcache tag nor any of the cache functions allow you to specify a key for items in the template cache. However, the function is useful for showing how ColdFusion handles general ColdFusion pages, pages with URL parameters and page fragments differently within the cache.
When ColdFusion takes a regular old ColdFusion page and caches it in the template cache, it generates a unique key for it based on the URL and a UUID appended to it. Here's an example of a file called cache_entire_page.cfm:
If you run this page, ColdFusion puts it in the template cache as you would expect. To see the key that ColdFusion automatically generates for it, create a new ColdFusion page with this code in it:
If you run that newly created page, you should see a dump of all the keys in the template cache for your application. It should look something like this:

Now try calling this page with no URL parameter passed to it. Right after you've done that, append ?productID=55 to the URL and call it again. Once you've done this, run the sump of all the keys in the template cache and you should have output that looks like this:

What you should notice right away is that there are now two new keys being returned for the page you just called twice. The first key looks just like the key from our last example. It contains just the template name and a UUID. The other key, however, contains something new. In addition to the URL for the template and the appended UUID, it also contains the query string as part of the key name. As you can see, by using the useQueryString parameter of the cfcache tag, we've instructed ColdFusion to treat pages with URL parameters as unique when it places them in the template cache.
If you execute this, you'll get some output as well as a dump of all of the cached items in the template cache. At this point, there are two items in the cache:

Now say you weren't happy that the two lines of output on your page were all run together and you wanted to put a line break between each one. You might modify your code and add in a simple paragraph tag or line break like so:
Go ahead and run the code once you've inserted the
tag. What you'll now see is that you have three items in the cache:

What's happening is that ColdFusion is using the position of the code in your page as part of the ID for the cached item. When you inserted the
tag, the position of the fragment you cached also changed by moving down a few lines, and ColdFusion assumed you had added a new page fragment that you wanted to cache.
This may or may not be a big deal to people as CF will still pull the correct cached item every time. The gotcha is that if you have a lot of caching going on, and you're making a lot of changes in a development environment, it's possible to fill your cache up with a lot of junk pretty quickly – just something to be aware of with the template cache when working with page fragments.
Now that we've covered the basics of the template cache, keep an eye out for my next post where I'll cover the ins and outs of updating items in the template cache including techniques for time based expiry, cache flushing, and dependent caching.
November 17, 2009
In Part 5 of this series, we mentioned that Ehcache could be configured at runtime via ColdFusion code as well as by using an XML configuration file called ehcache.xml.
On a Java EE install of ColdFusion 9, you can find the ehcache.xml file located here:
/JRun4/servers/servername/cfusion-ear/cfusion-war/WEB-INF/cfusion/lib
There are two main sections of the file you need to be concerned with for basic configuration. The first section you should take a look at is the DiskStore configuration:
This tag tells Ehcache where it should write cache files if you have the cache configured to overflow to disk or to persist to disk. We'll get into the specifics of those options, but for now it's important to know that by default Ehcache will use your Java temp directory to store cache files if it is configured to do so. On Windows, the Java temp directory is located in c:/windows/temp. You can change the value here to any drive/directory on your system if you wish to use a location other than the Java temp directory.
The next section to take a look at comes at the end of the ehcache.xml file. Skip on down to the very end where you should see a block of XML that looks like this:
This block of XML tells ColdFusion how to configure all of the Object and Template caches that are automatically created for your application. When a cache is automatically created, the name for the cache is also automatically created using the convention appnameOBJECT for object caches and appnameTEMPLATE for template caches. Each cache has a number configurable parameters:
If you make changes to any of these parameters, ColdFusion will apply them to any new caches that it automatically creates. If you have disk persistence or overflow to disk turned on, two files will be written to your file system per cache, an index file and a data file. For an object cache you would get appnameOBJECT.index and appnameOBJECT.data.
If you want to see what properties have been set for your application's cache, you can do so using the cacheGetProperties() function. The function takes a single optional parameter that specifies the type of cache to return the properties for. Options are Template or Object. If you don't specify the cache type to return properties for, ColdFusion returns them for both cache types. Here's an example that dumps the properties for both the default Object and Template caches:
This will result in output that looks like this:

As you can see from the screen shot, the structure keys correlate to parameters form the ehcache.xml file with two notable exceptions. Both diskSpoolBufferSizeMB and diskExpiryThreadIntervalSeconds are not reported on as properties that can be changed programmatically at runtime.
If you wish to change any of these properties programmatically, you can do so using the cacheSetProperties() function. This function takes a single argument – a structure containing all of the properties that should be configured. You can configure any of the following parameters:
Remember, this only applies to caches automatically created by ColdFusion. If a cache doesn't yet exist and you call cacheSetProperties(), ColdFusion will automatically create the cache for you based on whether you are setting properties for an Object cache, a Template cache, or both.
The following code shows how to build the structure of parameters necessary to configure a cache and set the cache properties using the cacheSetProperties() function:
It's also possible to create more caches than just the default template and object caches that ColdFusion creates automatically for you. This can be achieved by defining them in your ehcache.xml file or at runtime using the cfcache tag. To configure a new cache region in your ehcache.xml file, you would do so like this (place this before or after the defaultCache block in your ehcache.xml file):
As you can see, the only difference between this code and the code for the default cache is that you give the cache region a name using the name parameter.
You should know that neither cacheGetProperties() nor cacheSetProperties() can be used to configure the properties for a custom cache in ColdFusion 9.0. Hopefully this is a feature that will be added in a future version of ColdFusion.
If you want to read from or write to a custom cache, you can only do so using the cfcache tag. Here's an example:
This code is almost identical to the code we wrote in Part 5 where we introduced the object cache (don't worry about the extra metadata we're pulling using cfcache. We'll cover that later). The only real difference is that here we specify a name for our cache in both cfcache tags by defining it in the key attribute. Key allows us to specify a custom name for our cache. If a cache by that name hasn't been configured in your ehcache.xnl file, ColdFusion will automatically create it using the parameters set in the default cache settings. Remember, you can only work with custom caches using the cfcache tag. None of the cache functions in ColdFusion 9.0 allow you to specify the cache name you want to apply the function to. Go ahead and run the code a few times to verify it's pulling from the custom cache.
There's a lot more advanced stuff that can be configured in the ehcache.xml file such as cache clustering. These topics deserve their own posts, which we'll get to soon. For now, thanks for sticking with the series and I hope you've learned a little more about the ins and outs of cache configuration in ColdFusion 9.