ColdFusion 8 Per-Application Settings Get Partially Cached (And There's Nothing You Can Do About It)

Posted May 6, 2009 at 10:01 AM by Ben Nadel

Tags: ColdFusion

NOTE: The code in this post can be very misleading if you don't read the explanations that go with it!!

When I was playing around with some ColdFusion custom tags, I stumbled upon some interesting behavior in ColdFusion 8's per-application settings. From what I can see and re-create, the CustomTagPaths property is cached for the life of the application; but, the Mappings property, on the other hand, is not cached at all and needs to be defined in every page request that uses them. To demonstrate this, I have put together a short demo that uses the CustomTagPaths property to execute a custom tag and the Mappings property to create and utilize a ColdFusion component:

 
 
 
 
 
 
 
 
 
 

As you can see from the video, THIS.CustomTagPaths can be set once for the application and then never set again; THIS.Mappings, on the other hand, needs to be set on every page request. Now, I've seen people in the blogosphere and on the mailing complain that they are getting some intermittent errors with ColdFusion 8's per application settings and I wonder if it has something to do with this partial caching behavior?

To work in alignment with this caching strategy, I considered rearchitecting the way in which I define my per-application settings. In particular, I thought that I should probably only set the CustomTagPaths property once in the OnApplicationStart() event method and the Mappings property in the pseudo constructor such that it will be set on every page request:

  • <cfcomponent
  • output="false"
  • hint="I define application settings and event handlers.">
  •  
  • <!--- Define application settings. --->
  • <cfset THIS.Name = "TagPathDemo" />
  • <cfset THIS.ApplicationTimeout = CreateTimeSpan( 0, 0, 0, 15 ) />
  •  
  • <!---
  • Define custom mappings. These need to be set on EVERY
  • page request. Put in psuedo constructor so all events
  • can leverage them.
  • --->
  • <cfset THIS.Mappings[ "/com" ] = (
  • GetDirectoryFromPath( GetCurrentTemplatePath() ) &
  • "components\"
  • ) />
  •  
  •  
  • <cffunction
  • name="OnApplicationStart"
  • access="public"
  • returntype="boolean"
  • output="false"
  • hint="I fire when an application needs to be initialized.">
  •  
  • <!---
  • Define ColdFusion custom tag paths. Since these
  • values are cached, they only need to be set once
  • when the application is intialized.
  • --->
  • <cfset THIS.CustomTagPaths = (
  • GetDirectoryFromPath( GetCurrentTemplatePath() ) &
  • "tags\"
  • ) />
  •  
  • <!--- Return true so page will run. --->
  • <cfreturn true />
  • </cffunction>
  •  
  • </cfcomponent>

This makes sense based on the behavior, but unfortunately does NOT work. When I run the page with this Application.cfc configuration, I get the following ColdFusion error:

Cannot find CFML template for custom tag helloworld.

So, it seems that the CustomTagPaths property gets cached, but the behavior is not quite so straightforward. So what next? I tried moving it to the OnRequestStart() event method. Also no luck - same error. It appears that the per-application settings need to be set outside of any of the application event handlers.

At this point, we've run out of elegant solutions - if we don't define the CustomTagPaths in the pseudo constructor, they don't work; however, if we do define them, we set them unnecessarily; and finally, if we don't set them, we can't really check for their existence since they are not available in the THIS scope when not set explicitly.

The only thing I could think of was trying to execute a custom tag, catching any errors, and then defining the custom tag paths if necessary:

  • <cfcomponent
  • output="true"
  • hint="I define application settings and event handlers.">
  •  
  • <!--- Define application settings. --->
  • <cfset THIS.Name = "TagPathDemo" />
  • <cfset THIS.ApplicationTimeout = CreateTimeSpan( 0, 0, 0, 15 ) />
  •  
  • <!---
  • Define custom mappings. These need to be set on EVERY
  • page request. Put in psuedo constructor so all events
  • can leverage them.
  • --->
  • <cfset THIS.Mappings[ "/com" ] = (
  • GetDirectoryFromPath( GetCurrentTemplatePath() ) &
  • "components\"
  • ) />
  •  
  •  
  • <!---
  • Try to execute the tag check custom tag. If this fails
  • (throws an exception), then we need to initialize the
  • custom tag paths. If it DOES work, then the paths have
  • been initialized and cached.
  • --->
  • <cftry>
  • <!--- This tag doesn't do anything. --->
  • <cf_checktagpaths />
  •  
  • <!--- Tag failed - Define custom tag paths. --->
  • <cfcatch>
  •  
  • <cfset THIS.CustomTagPaths = (
  • GetDirectoryFromPath( GetCurrentTemplatePath() ) &
  • "tags\"
  • ) />
  •  
  • </cfcatch>
  • </cftry>
  •  
  • </cfcomponent>

As you can see, I am defining the CustomTagPaths property only if the custom tag "CheckTagPaths.cfm" failed to execute.

Not only is this very sloppy looking, it also does NOT work; the CheckTagPaths.cfm custom tag throws an exception on every request. From further experimentation, it seems that you cannot utilize the ColdFusion 8 per-application settings within the pseudo constructor itself - you have to wait until one of the application event handlers.

In the end, it appears that all of this exploration is for naught - the CustomTagPaths get cached for the life of the application, but there is no way for you to leverage that fact that I can find.

UPDATE: Just a quick update based on the comments that Ray Camden mentioned below. I had no idea that ColdFusion has cached tag references; however, after some quick testing, I have verified that it is not the custom tag itself that is being cached in my experimentation, but rather the directory:

 
 
 
 
 
 
 
 
 
 



Reader Comments

May 6, 2009 at 10:13 AM // reply »
319 Comments

Ben, I skimmed this. I did NOT read it closely. But are you forgetting that CF remembers the location of a custom tag? If you call cf_foo, and it finds it in path N, cf will never look for cf_foo elsewhere. This is less a App.cfc bug and just a custom tag behavior that has not changed since CF5.

Again, forgive me if this is not the issue.


May 6, 2009 at 10:16 AM // reply »
11,238 Comments

@Ray,

REALLY!! I did not know that! Is that really true? Now I have to go test :)


May 6, 2009 at 10:17 AM // reply »
319 Comments

Yep. Super old behavior. Maybe even back to when CTs were added (CF3 I think).

Of course, cfmodule doesn't have this problem.


May 6, 2009 at 10:18 AM // reply »
11,238 Comments

@Ray,

I just tested this and it is not the case - even when I put in another, not previously used tag, the mapping still exists.


May 6, 2009 at 10:20 AM // reply »
319 Comments

Ah ok. Well, if you ARE changing the CT path during dev, it is still important to remember. Once you run cf_foo and CF finds it, you are screwed.


May 6, 2009 at 10:23 AM // reply »
11,238 Comments

@Ray,

I had never seen that before. Thanks for letting me know.


May 6, 2009 at 10:32 AM // reply »
30 Comments

Have you actually seen errors with per-application settings under load? I ask, because I too have heard of issues, but haven't actually seen them.


May 6, 2009 at 10:35 AM // reply »
67 Comments

Sidenote: I like the screencasting that you've been doing lately. It's much more approachable than a wall of code -- you're still getting the wall, but having it spoken and shown visually just works better for me, I guess.


May 6, 2009 at 10:36 AM // reply »
15 Comments

Angela and I have been dealing with this for quite some time. We ended up defining the CustomTagPaths outside any contructors, but then defining it again in the onRequestStart() to get around some race conditions we were experiencing.

I think the CustomTagPaths is definitely something that needs to be worked on for CF9.


May 6, 2009 at 10:36 AM // reply »
30 Comments

In your second demo, I didn't see that you commented out the custom tag path before running the second custom tag (helloworld3).


May 6, 2009 at 10:38 AM // reply »
11,238 Comments

@Nathan,

Sorry about that, I just re-did the video. I realized that right after I posted :)


May 6, 2009 at 10:41 AM // reply »
11,238 Comments

@Rick,

Thanks man. I really like the video walk throughs. I am not sure where the right balance is between code / video because the screen size is so small. If I can find a nice way to record a larger video, but still have it fit inside my blog content, I might go that way as I think it would provide more value.

@Nathan,

I have not experienced this error myself; so it's hard to know what does or does not contribute to it exactly.


May 6, 2009 at 10:41 AM // reply »
319 Comments

@RickO: (Ben, forgive me for hijacking this a bit.) I've used Jing a few times, but never really got any good feedback on it. You think it is worthwhile using more often?


May 6, 2009 at 10:43 AM // reply »
30 Comments

Cool. Just wanted to make sure that wasn't the reason it was working...


May 6, 2009 at 10:44 AM // reply »
11,238 Comments

@Ray,

No problem :) I love Jing, but I want to find a better way to record larger dimension videos yet still embed easily.

@Nathan,

No worries.


May 6, 2009 at 10:46 AM // reply »
30 Comments

@Ben & Ray - I dig the screencasts.


May 6, 2009 at 2:17 PM // reply »
211 Comments

Off-topic (regarding Jing): Aren't you just limited by what your machine can handle? I have Jing Pro and I can record any size I want even a thin 200x1000 video strip? There are limitations, but size isn't one of them.


May 6, 2009 at 7:58 PM // reply »
47 Comments

The video does have the option to go full screen and it looks fine. You have to hover over the video and you'll see a tiny bar at the bottom, it's too small to see the full screen button, but it's there.

Instructions:

1) Right click on the video and Zoom In
2) Drag the video to the left
3) Click the full screen mode
4) Righ click and zoom out a couple of times
5) You may have to reposition the screen


May 6, 2009 at 8:01 PM // reply »
47 Comments

Sorry, I just tried a simpler method:

1) Right click and choose show all
2) Click the full screen button

That's it!


May 6, 2009 at 8:11 PM // reply »
132 Comments

@Ben

This bit us recently with the mappings and how part of our platform worked.

All of our applications live in the same CF application and each has a section of the application scope. I had it defining an auto mapping for the root of each sub-application (which is outside the webroot) at the start of every request.

this.mappings["/" & listLast(getRootPath(),"\/")] = getRootPath()

I started seeing random errors about not being able to find certain components, but I couldn't duplicate it... until I decided to cross application load test.

We had also setup explicit mappings in the Admin for most applications from back when we were on CF7 and this had been masking the fact that the implicit root mapping sometimes would vanish! So only new apps that didn't have CF Admin mappings would fail.

So the moral of the story is that *every* request shares the same this.mappings, but it also has to be initialized at the start of *every* request with the *exact same values*. Otherwise requests that are currently running can have their mappings up and vanish in the middle because of a different request!! :/


May 7, 2009 at 4:10 AM // reply »
1 Comments

@Daniel Short,

We also ran into huge problems with the per-app customtagpaths and what seemed like some race time trouble. I'd be interested in seeing the code you used to get around these issues.


May 7, 2009 at 8:08 AM // reply »
11,238 Comments

@Todd,

Yeah, that's true. I guess I'm just more worried about the embed code; I guess it's cause I never really thought about it. I could always record a large video and then just scale it down for the embed code :)

@Elliott,

What would be good would be to allow us to put the values in the OnApplicationStart() event handler. That way, we could keep them to a single setting.


May 10, 2009 at 6:41 AM // reply »
31 Comments

Just wanted to say that I loved the screen capture used in the post Ben. It's the first I've seen you use and actually came here to see how you were using Jing after we talked about it on Twitter.

It worked brilliantly in this example and engaged me a lot more than just reading the blog post.
I like how it really engages you to the viewer as well helping to get the content of the post across.

I don't think the screen size matters too much - at least not in this example. Where more width is needed the bigger screen cap with smaller embed code would do the trick nicely I'd think.
Nice to be able to play it embedded though where possible.

Interesting post by the way. Not something I was aware of and useful to know.


Jun 12, 2009 at 3:54 PM // reply »
26 Comments

A note here from our conversation on this - if you were to restart your server instance after you commented that out custom tag path I'd expect that template you executed to fail - and not find the CT path - (as the cache would no longer be available). Is that what you found - I'm assuming so?


Jun 12, 2009 at 4:28 PM // reply »
11,238 Comments

@Kevin,

I assume so, but have not tested that.


Jun 17, 2009 at 4:50 AM // reply »
1 Comments

Very interesting detail regarding this topic, is How Ben forget to say that he has written this post AFTER I've send him an email regarding problems with application specific customtags mappings, on an application that is build using HTML frames that loads different coldfusion pages in each frame.

I've offer obviously a PROBLEM not a solution, but is sad to see how people can ommit some details.
I'm not need to be named here is not the idea, I've not ego problems.

IMHO instead of starting post saying " .. While I was playing...",
a better approach can be " I've received an email regarding problems with ...., then I've decided to play a little bit to ...' .

Regards


Jun 17, 2009 at 5:52 AM // reply »
211 Comments

@Francisco: Uh... wait. What?! It's his blog, he can write it how he wants? o_O


Jun 17, 2009 at 8:08 AM // reply »
11,238 Comments

@Francisco,

Here is the email that you sent me:

> I've have started using Application.cfc on CFMX 8 because I want to
> be able to set different customTagPaths for every application hosted on my CF
> server. I have found a problem because my app uses frames (and I can not
> rewritte app). Seems initalization of this.customTagPaths is corrupted, because
> app can not find custom tags after login page (has no frames) when entering main
> screen (has 3 frames). Any hint?

To which, I tried to write a blog post. Unfortunately, I couldn't turn your idea into anything which is why I then told you (CC'ing gualtiero.sappa and alessandro.lia):

Francisco, My blog post was a bust. Sorry.

The blog post I tried to write for you involving frames is completely unrelated and was not something that I could solve. This blog post (the one above) has nothing to do with your email; there is no reference to frames, no reference to login pages. The only thing that your email and my blog post have in common is that they work with custom tag paths... which is a big part of my Custom Tags presentation I've given months ago and will give again at CFUNITED. It is in the research for this presentation that I first discovered partial caching of custom tags.

I am sorry that you feel that I have somehow skipped over you or not acknowledged you; I hope that you see that on my blog, I give credit for things as often as possible - I love giving people credit for stuff. I am sorry if you were confused as to where this blog topic came from.


Jun 17, 2009 at 9:08 AM // reply »
11,238 Comments

@All,

I would like to apologize for my last comment - I definitely came off as very defensive (followed by offensive). I felt attacked and I should have followed up with @Francisco via email rather than publicly.

While my blog post is not related to the question he originally asked me, I believe our misunderstanding is due to a strong language barrier that skewed communication. I am sorry that I let me emotional side take over my response.


Jun 17, 2009 at 9:18 AM // reply »
211 Comments

@Ben: I wouldn't worry about it or lose sleep over it. The whole thought of this is just silly. You certainly don't have to defend your every post or where your muse strikes from.


Rob
Sep 10, 2009 at 3:35 PM // reply »
4 Comments

I am having a similar issue. I have specified a per-application customtags path in my application. For the most part it is working just fine, however, when custom tags are being used within CFC methods or scheduled tasks, I'm gettting an exception saying that it cannot find the custom tag. I noticed a bug fix in the latest CF8 hot fix (http://kb2.adobe.com/cps/511/cpsid_51180.html) is supposed to fix this issue, but after applying it, the same behaviour is occurring.

Does anyone have a solution for this? I don't want to rely on custom tag paths in the administrator. I want my applications to be self-contained.

Thanks.


Sep 12, 2009 at 10:14 PM // reply »
11,238 Comments

@Rob,

I've got no good advice on this one, sorry.



Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 17, 2013 at 7:42 PM
HashKeyCopier - An AngularJS Utility Class For Merging Cached And Live Data
Ben - thanks so much for posting these Angular articles and findings, they've been a huge help towards learning one of the more 'complex' JavaScript frameworks out there (IMO). I have been using Angu ... read »
May 16, 2013 at 5:01 PM
UPDATE: Parsing CSV Data Files In ColdFusion With csvToArray()
Your code was the closest thing I've found to obtaining some direction for converting ISO fields to values that CF can translate properly. Thank you for posting! ... read »
May 15, 2013 at 10:37 PM
Very Simple Pusher And ColdFusion Powered Chat
hi id making plz easy ... read »
May 15, 2013 at 6:07 PM
Making SOAP Web Service Requests With ColdFusion And CFHTTP
Ben, you once again saved my bacon at work. Thank you, thank you, thank you! ... read »
May 15, 2013 at 4:15 PM
What If All User Interface (UI) Data Came In Reports?
@Josh, Thanks! @Ben, I definitely recommend the David West book "Object Thinking" I've been quoting from. It goes deeply into the philosophy and history of OO programming. His breadth ... read »
May 15, 2013 at 11:36 AM
Ask Ben: Print Part Of A Web Page With jQuery
I found this helpfull when you need to keep (refresh) the original parent page after closing the iframe child print dialog (Hoping you're not using a form at this time so it won't submit again): On ... read »
May 14, 2013 at 7:13 PM
What If All User Interface (UI) Data Came In Reports?
@Jonah, If there's any books you'd recommend on the subject of domain modelling, I'd love to hear it. I just downloaded the free PDF of "Domain Driven Design Quickly". Figured I'd give it ... read »
May 14, 2013 at 6:57 PM
The UX Of Prototyping: Low-Fidelity Is The New High-Fidelity
@Phillip, I'm not sure I follow what you mean? Are you saying that you looked at the list of widgets provided by the jQuery UI and let that be your style guide? ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools