Quick Application.cfc Review
A user sent in a request for me to look over some code he would like to use for his Application.cfc file. (As an aside, don't forget my online Application.cfc template you can use.) The template looked nice but had one main issue that I noticed. Since the user got the template from someone else, I won't post the whole thing as it isn't my code, but I will demonstrate the problem I saw.
First is the onSessionStart:
<cffunction name="onSessionStart" output="false">
<cfscript>
session.started = now();
</cfscript>
<cflock
scope="application" timeout="5" type="Exclusive">
<cfset
application.sessions = application.sessions + 1>
</cflock>
</cffunction>
Notice that he is keeping count of the sessions, a topic I covered last week. Most importantly though - notice his lock. He is using a scope based lock to ensure his update of the application variable is single threaded. Now lets move on to the onSessionEnd method:
<cffunction name="onSessionEnd" output="false">
<cfargument name = "sessionScope" required=true/>
<cfargument name =
"applicationScope" required=true/>
<cfset var sessionLength =
TimeFormat(Now() - sessionScope.started, "H:mm:ss")>
<cflock
name="AppLock" timeout="5" type="Exclusive">
<cfset
arguments.applicationScope.sessions = arguments.applicationScope.sessions - 1>
</cflock>
</cffunction>
(Forgive the bad formatting - this came in via email.) Notice the problem? Try to figure it out before reading on.
He correctly uses a lock again to update the session count. But he can't use a scope lock since the application scope isn't available directly in onSessionEnd. That's why he has to use the application scope passed in via arguments.
So the problem then is that in one case he has a scope based lock and in another case he has a named based lock. He needs to use one or the other. Since he can't use a scope lock in onSessionEnd he should use the named based lock only.
p.s. A few other small things that I'll point out that are minor but bug me: I don't like using cfscript as he did here, just for one line of code. He also forgot the arguments prefix for sessionScope in onSessionEnd. I tend to be anal about using the arguments prefix in my methods.
Comments
Your app.cfc reference has
<cfset this.scriptProtect = false>
Shouldn't it be the following?
<cfset this.scriptProtect = "all">
Hmm, I can't find it.
I can maybe write a new one on it. Do you have a good, and not too complex App.cfm you could share?
2 issues.
1) It is important to use the same type of lock, or it is useless.
2) onSessionEnd can't use the scope lock, it can only use the named lock.
here it is..
<CFSETTING ENABLECFOUTPUTONLY="Yes">
<CFAPPLICATION NAME="QAX"
CLIENTMANAGEMENT="Yes"
SESSIONMANAGEMENT="Yes"
SETCLIENTCOOKIES="Yes"
SESSIONTIMEOUT="#CreateTimeSpan(0, 8, 0, 0)#"
APPLICATIONTIMEOUT="#CreateTimeSpan(0, 8, 0, 0)#"
CLIENTSTORAGE="Registry">
<CFERROR type="request" template="app_error.cfm" mailto="jay_mcconathy@txeb.uscourts.gov">
<!--- Do I need to create my app var? --->
<cfset needInit = false>
<cflock scope="application" type="readOnly" timeout="30">
<cfif not structKeyExists(application,"sessions")>
<cfset needInit = true>
</cfif>
</cflock>
<!--- Yes, I do need to make it. --->
<cfif needInit>
<cflock scope="application" type="exclusive" timeout="30">
<cfif not structKeyExists(application,"sessions")>
<cfset application.sessions = structNew()>
</cfif>
</cflock>
</cfif>
<!--- Store my last hit. --->
<cfset application.sessions[session.urltoken] = now()>
<CFSETTING ENABLECFOUTPUTONLY="No">
http://www.coldfusioncookbook.com/entry/124/How-do...?
I think I've realized why I was confused, and I'm wondering if you can confirm: the problem wasn't that the user was merely using two different kinds of locks in Application.cfc; the problem was that the user had two different kinds of locks protecting the same scope, which would render them less effective, right?
One thing, though:
As I read the sentence "But he can't use a named lock since the application scope isn't available directly in onSessionEnd" I was a bit confused. Since nobody has commented on it yet I suppose most understood what Ray was trying to say, though, I feel like posting a comment to help out the noobies (not to correct Ray as the paragraph immediately following this sentence already does that for us), the sentence should read:
"But he can't use a [scope based lock] since the application scope isn't available directly in onSessionEnd"
When in doubt, check Ray's blog!
^ Write that down :)

