A reader asks,
When you've used OnApplicationStart to store application variables how do you refresh it?
Simple - I use a URL variable. Inside my onRequestStart, I'll have something like this:
<cfif structKeyExists(url, "refreshmebabyonemoretime")>
<cfset onApplicationStart()>
</cfif>
A few notes. The name of the URL variable is completely arbitrary. You probably want something people can't guess, but it is up to you to decide how anal/secure you want to be.
Also - remember that when ColdFusion runs onApplicationStart by itself, it does so in a single threaded manner. When you run it, it isn't single threaded. But if you are just setting a bunch of application variables, it probably will not matter to you.
p.s. So hey, did you notice I used structKeyExists instead of isDefined? I'm slowly coming around to it. ;)
Archived Comments
Excuse my ignorance on the topic, but what is the benefit of using StructKeyExists instead of isDefined? Faster or just better form?
isDefined() can lead to unexpected results becuase it will look through a number of scopes trying to find the specified variable. So isDefined() may return true when you expect it to return false, and vice-versa, when a variable with the same name exists in another scope.
Yea, ever since I got grief about using isDefined in my guess a number game, all my code is strictly structKeyExists now! =)
what's the difference of using the StructKeyExists and a line like this?
<cfif IsDefined("url.refreshmebabyonemoretime")>
I could understand that having something similar to
<cfif IsDefined("refreshmebabyonemoretime")>
would potentially give you unexpected results.
but the first option works for me.
any pros or cons?
> isDefined() can lead to unexpected results becuase it
> will look through a number of scopes trying to find the
> specified variable. So isDefined() may return true when
> you expect it to return false, and vice-versa, when a
> variable with the same name exists in another scope.
That make sense if you don't specify a scope, but why is IsDefined("url.SomeVar") different from StructKeyExists(url, "SomeVar")? Is there a performance benefit of one versus the other?
IMHO IsDefined("url.SomeVar") is preferable because it doesn't couple the logic to a specific CF storage mechanism. In other words, if the folks at Macromedia lose their minds and decide that CF 8 will no longer use a struct to model the URL scope, code using IsDefined will continue to work. (Yes, I know this example is reaching, but for me its enough to stick with IsDefined() unless someone can show me a compelling reason otherwise)
Just wondering,
Seth
The other benefit is performance. StructKeyExists() performs faster (at least in CFMX) than does isDefined(). I don't think performance gains of this kind are worth much extra effort, but then using StructKeyExists() doesn't take much extra effort.
if it performs better in that it views a null value as not defined, then im sold. until then its
isDefined("") and len()
for me.
tw
I would just use structKeyExists(url, "blah") AND url.blah neq '' for that, does the same thing.
StructKeyExists will find elements that isDefined will not. A specific example is an array of structures.
e.g.
StructKeyExists(sessionOnlineArray[i], 'init') inside a loop will return true or false, but isDefined will break and throw a CF error.
So altough I mostly use isDefined, StructKeyExists has more versatility; furthermore, if it has performance advantages, there should be no questions about it.
guess its time to explore it.
talk about paradigm shift. damn, i think i dream about isDefined() and len() in my cfif statements :)
Are people saying that url.blah neq '' is better than len(url.blah), or am I reading things wrongly?
One person said that. I prefer Len().
Len() is faster.
I could have sworn there was more than one person earlier.
Oh well.
Anyhow, just to see if there was a significant performance difference I did a quick test - looped through each ten thousand times. The mean average result of the first five runs was 269ms and 281.2ms (for Len and EQ '' respectively), and the all fifteen runs it was 117.7ms for Len() and 125ms for EQ '', with both having a median of 47ms.
So, using Len() is prettier and might save a whole ten milliseconds! :)
I am kind of a newbie when it comes to differently scoped variables in ColdFusion. I am quickly getting up to speed. I have seen this construct utilized in many examples, but none have shown how to load said variable into the structKey. How is that done? I've tried loading the variable in the pages address as part of a query string with no luck. I am sure there is something very basic that I am missing here.
I'm not quite sure what you mean Andrew. "load said variable into structKey"? Do you mean set a variable in a struct? If so it is rather simple, cfset foo.moo = "value", or cfset foo["moo"] = "value". You should be able to read up on structs in the cf docs.
I was referring to the URL struct specifically. I do understand how to access a struct programatically, but specifically the URL struct is most often used in the context of your example. Ben Forta uses a similar example in his chapter on Advanced ColdFusion Components in CFMX7 Application Development. I started thinking about the problem some more and realized how the URL struct works - each parameter of the query string makes up the entire URL struct. With that in mind I tested with a link formed somewhat like this: http://www.foo.org/test.cfm.... Worked like a charm. Thanks for the good article and giving me a place to use as a sounding board.
Ah - yes - that's just a feature built into CF. It will auto-break the query string apart into a struct. I remember the old days of parsing query strings in PerlCGI. :)
Have you ever seen this method fail to restart the application? I have tried Ray's method above and tried another thread-safe version I say Barney suggest to someone on a list somewhere (don't recall at the moment), and I can't seem to make it work. Just for testing I outputted text before and after the call to onApplicationStart() which is being displayed. I even outputted some text inside the onApplicationStart method, which also displayed, but when I dump the application scope afterwards, I still have data that from before the refresh. Any ideas?
~Dave
What do you mean it doesn't work? If you add a cflog statement to onApplicationStart, do you see a log event if you call it with my method?
Ray,
This is my onApplicationStart:
<cffunction name="OnApplicationStart">
<cflog file="inetap-mii" text="The application was started at #now()#." type="information" />
</cffunction>
When I use the method you list, I can clearly see it make an entry into inetap-mii.log. However...
Before I ran this, created a structure in the application scope. After running the reload and seeing the log entry made, I can <cfdump var=#application# /> and still see the structure that I had previously added to the application scope (and I confirmed this wasn't client side caching). My understanding is that the Application scope would be fresh at this point as if I was running the application for the first time. Am I just misunderstanding what onApplicationStart can do for me? Thanks.
~Dave
If should refresh - however - why not just restart CF? If you are making changes to the application .cfc file, it may be best.
Well at this point it has just become a matter of principle! :) Restarting works. I was just trying to figure out why this wasn't doing the trick. Thanks.
Heh, I hear ya. I just tend to go to a restart if CF is being "wierd." And it sounds like it may be for you.