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

Since I have never setup an appplication.cfc nd have usually used application.cfm I know I am behind the curve.. however just to make sure, and I am sure this is a stoopid question, I can just rename the application.cfm files to application.cfc and make the appropriate code changes for it to work correctly?
# Posted By Jay McConathy | 3/21/07 8:05 AM
Ray,

Your app.cfc reference has
<cfset this.scriptProtect = false>

Shouldn't it be the following?
<cfset this.scriptProtect = "all">
# Posted By Phillip Senn | 3/21/07 8:12 AM
PS: No. I prefer to write my own security. Plus I find scriptProtect tends to interfere at times, like on a blog if you try to post code as the author, it will block it. It _is_ a nice feature, I just don't use it myself.
# Posted By Raymond Camden | 3/21/07 8:22 AM
great website and good idea! However, you spelt my hometown wrong...its spelt worcester park. Not that it matters but thought you should know
# Posted By gemma | 3/21/07 8:27 AM
@Jay - I wouldn't just rename it. A CFC is quite different from an CFM file. You need to reorganize stuff. I'm pretty darn sure I did a blog entry on this.

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?
# Posted By Raymond Camden | 3/21/07 8:42 AM
Ray, why is it necessary to use only one kind of lock, named or scoped, across the whole Application.cfc?
# Posted By Tom Mollerus | 3/21/07 8:51 AM
Tom:

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.
# Posted By Raymond Camden | 3/21/07 9:10 AM
I have a very simple newbie one ..

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">
# Posted By Jay McConathy | 3/21/07 9:34 AM
I have not seen a blog entry on it which is why I am asking..
# Posted By Jay McConathy | 3/21/07 9:35 AM
Do you have to var scope the lock name like you would a query name?
# Posted By Paul | 3/21/07 2:03 PM
As far as I know, no.
# Posted By Raymond Camden | 3/21/07 3:21 PM
mmm Ray & Jay there's this entry in the coldfusion cookbook ;-p

http://www.coldfusioncookbook.com/entry/124/How-do...?
# Posted By Jean-Michel Rottiers | 3/22/07 5:02 AM
Ray,

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?
# Posted By Tom Mollerus | 3/22/07 8:54 AM
It doesn't render it less effective. It renders it UNeffective. :)
# Posted By Raymond Camden | 3/22/07 11:00 AM
Great post Ray and thank you for confirming my suspicion on this. I'm trying to clean up another developer's Application.cfc logic and I came across this very scenario which threw up a red flag.

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 :)
# Posted By Matthew Zimmer | 4/10/08 10:12 AM
Good catch there Matt. I'll edit the post.
# Posted By Raymond Camden | 4/10/08 10:15 AM