Along with cool tags and functions added in ColdFusion 8, there have also been some neat updates to the Admin API. If you don't know what the Admin API is - it is a set of CFCs that give you programmatic access to various administrator type functions. One example is being able to list and create datasources. Today I want to show one of the new features in the Admin API under ColdFusion 8 - being able to clear individual files from the trusted cache.
One of the caching settings you can use within ColdFusion is the trusted cache. By turning this on, ColdFusion will parse your file one time, and will never parse it again. If you change the file, even to fix something small like a typo, you have to login to the Admin and hit the "Clear Template Cache" button.
Well the Admin API lets us do this directly from code. This existed even back in ColdFusion 7. But the problem is - when you just fix one file, why do you have to clear the entire cache?
ColdFusion 8 updates the API so you can pass in a list of files. If you do, only those files are updated. This can be pretty darn useful. Here is a sample application I built that demonstrates this new API:
<cfoutput>
<form action="#cgi.script_name#" method="post">
Enter file name or directory: <input type="text" name="cachefile"> <input type="submit" value="Clear File/Folder from Template Cache">
</form>
</cfoutput>
<cfif structKeyExists(form, "cachefile") and len(trim(form.cachefile))>
<cfset form.cachefile = trim(form.cachefile)>
<!--- detect folder versus file --->
<cfset filelist = "">
<cfif directoryExists(form.cachefile)>
<cfdirectory directory="#form.cachefile#" name="files">
<cfloop query="files">
<cfset filelist = listAppend(filelist, form.cachefile & "/" & name)>
</cfloop>
<cfelseif fileExists(form.cachefile)>
<cfset filelist = form.cachefile>
<cfelse>
<cfoutput>
<p>
<b>You entered a file or folder (#form.cachefile#) that did not exist.</b>
</p>
</cfoutput>
<cfabort>
</cfif>
<cfoutput>
<p>
Going to clear the following file(s) from the template cache:<br />
<cfdump var="#listToArray(filelist)#">
</p>
</cfoutput>
<cfinvoke component="cfide.adminapi.administrator" method="login" adminPassword="admin">
<cfinvoke component="cfide.adminapi.runtime" method="clearTrustedCache" templateList="#fileList#">
</cfif>
It begins with a simple form asking you to name a file or a directory. One submitted, I check and see if you entered a folder. If you did, I do a cfdirectory to get the files in the folder. Once I have the files ready, I simply login to the Admin (note that I have hard coded the password here) and then run the clearTrustedCache function.
Pretty simple, right? There are a few updates I could do to this. I could make the cfdirectory tag recurse. I could also ask you for the ColdFusion admin password instead of hard coding it. I could even use Ben Forta's cool file browser.
If I were to package up this as something you could include in the ColdFusion admin (like SpoolMail), would folks use it?
Archived Comments
Mmmmm, I can see this mashed up with a directory watcher gateway watching your code for changes and re-loading when a file gets tweaked. This would really be awesome for multiple CF servers sharing a codebase on a SAN or other shared source. Then you could enable trusted cache to lower bandwidth to your shared source, and any updates will auto-refresh. Now I hope the upgrade price for CF8 Enterprise doesnt break the bank, as I have to somehow sell 2 copies to a customer and 1 copy to the company I work for =)
My only concern here would be the performance of having CF watch your entire box.
I'll chime in-- I'd be interested in using a wrapped-up version of that API (what a smart idea on Adobe's part to allow cache-refresh for individual files). IMHO, the interface for the tool would contain both a text entry area where you could quickly paste in the path for a single file and a file dialog box for selecting multiple files.
What I'm thinking of making is maybe a tool that combines a few things. I don't see this as necessarily being an app to itself, if thats makes sense.
@Ray, I agree that it wouldn't be an app to itself, but it would be nice if it could offer some sort of form interface so that you could just wrap it with an existing admin application. I'm happy to contribute code if you like.
What are you saying - my form wasn't pretty? ;) Seriously though - I'd accept any suggestions in that area.
I have not had the chance to play with this, but oh so nice it looks. Curious, does cfide.adminapi.administrator.login now reuire a username? With the addition of multiple users accessing cfadmin I'd think it should.
DK
Don't forget you can view the Admin API CFCs in your browser. If you do - you will see that username is an optional argument. The CF Admin _can_ use a username, but doesn't have to.
Wonder what happens if you do this in application.cfm? If you passed a url parameter (trusted=0) could you clear the current page before the page is executed?
You would rip a hole in the space time continuum and end the universe as we know it.
COOL!!!
... if it didn't affect the space time continuum it would (at least) cause a tremor in The Force ;-)
Wow, Charlie did his presentation on hidden gems for our user group and he very briefly mentioned this feature. A Google search of course returned your blog entry (which I read religiously so I'm not sure how I missed it the first time around). This is absolutely a to die for feature and I would love to see an admin add-on for it a la SpoolMail. I know you made this post quite some time ago but if you are still thinking about adding it, please do!
I suppose I could wrap it up sometime. I'm trying to _not_ release so many projects as it gives me too much to do. ;)
Hi Ray,
Can we pass a directory or does it have to be a list of files?
It has to be a list of files. Just use my Cache Cleaner admin extension. Makes it easy. You can enter a directory.
Is there also a way to clear the cached queries (CACHEDWITHIN) programatically through this api? I only find a solution that has been deprecated with MX upwards.
Thanks for an answer.
I looked at the runtime cfc (/CFIDE/adminapi/runtime.cfc) and did not see it. You can scan the other CFCs but I don't think this is in there.
Is there any way on cf8 to get a list of scheduled tasks, using the admin api?
Thank you.
I just scanned the CFCs (don't forget you can too - they are self-documenting) and I didn't see anything.
I was reading from this site, http://www.cfexecute.com/pa..., which talks about the admin api, and the servermanager which has getScheduledTasks. But that object or api method seems unavailable on cf8.
I'd say file an ER.
Excellent info Raymond!
I am not a developer, but I do have to administer a few CF servers.
I am being asked by the developers to clear the cache after pushes on a frequest basis, and I want to automate this. First, I normally just log into the admin console, and hit the "clear cache" button. I dont care about clearing the cache on a "file by file" or "directory" basis :-)
Can this be accomplished by writing (and calling) a .cfm file with the (second to last) last two lines of your script above?:
ex:
<cfinvoke component="cfide.adminapi.administrator" method="login" adminPassword="admin">
<cfinvoke component="cfide.adminapi.runtime" method="clearTrustedCache" templateList="#fileList#">
(MInus the "templateList="#fileList#"" option)?
I would like to write a command line script that does this on each of my 4 nodes - perhaps using wget or something.
Thanks you very much for this info!!!!
Yep, it should work just fine.
Ray - just posting anyone stumbling for answer if they have trouble. I had an app that I couldn't get cleared using the code (or any similar). Turns out it was something in application.cfc preventing the login from working. Adding a blank application.cfc in subfolder with the code to clear the cache fixed it. Just FYI....
Did the other app.cfc make use of cflogin? There is a bug with the Admin API where it conflicts with an existing cflogin being active.
Of course there is....yep. That was it.
Hi ray, I currently use a URL parameter in onRequestStart() to initiate a call to onApplicationStart() to reset Application parameters and clear the query cache:
<!--- Clear the query cache --->
<cfobjectcache action="clear" />
Do you see any issue with adding the following in onApplicationStart()?
<!--- Clear template cache --->
<cfinvoke
component="cfide.adminapi.administrator"
method="login"
adminPassword="mypasswordhere" />
<cfinvoke
component="cfide.adminapi.runtime"
method="clearTrustedCache" />
Not really, nope.