Using Session Timeout And CreateTimeSpan() - Subtle Caveat

Posted March 30, 2007 at 2:18 PM

Tags: ColdFusion

CreateTimeSpan() is a really easy way to create timeouts for both your Application and your user Sessions. It takes days, hours, minutes, and seconds and returns the numeric representation of that time span. I am sure most of you, if not all of you, are using this in your CFApplication tags or Application.cfc ColdFusion components.

CreateTimeSpan() is really cool, but it is a method call. A tiny one nonetheless, but a method call that has with it, processing overhead. Is this overhead needed? Not really. Unless you are in the habit of changing your timeouts, most likely all your CreateTimeSpan() calls return a constant value. Well, if they are returning a constant value, why bother using the method call. Readability? Sure. Maintainability? Of course.

But what if you were NEVER going to change the time span value. Could you just put in the value that CreateTimeSpan() would have returned. The answer is quite tricky in its subtlety. You can AND you can't. To demonstrate, I have set up a very simple HTML page:

 Launch code in new window » Download code as text file »

  • <html>
  • <head>
  • <title>Session Timeout Test</title>
  • </head>
  • <body>
  •  
  • <cfoutput>
  •  
  • <p>
  • ID: #SESSION.CFID#<br />
  • Token: #SESSION.CFTOKEN#
  • </p>
  •  
  • </cfoutput>
  •  
  • </body>
  • </html>

All this does is output the SESSION information. Then, I set up an Application.cfc that defines the Application and Session management in several different ways. Depending on which variable I pass in the URL (a,b,c,d), the SESSION timeout is set using a different methodology:

 Launch code in new window » Download code as text file »

  • <cfcomponent>
  •  
  • <cfset THIS.Name = "SessionTimeoutTest" />
  • <cfset THIS.ApplicationTimeout = CreateTimeSpan( 0, 1, 0, 0 ) />
  • <cfset THIS.SessionManagement = true />
  •  
  •  
  • <!---
  • Check to see which session timeout we are
  • going to utilize.
  • --->
  • <cfif StructKeyExists( URL, "a" )>
  •  
  • <!---
  • Here, we are going to try to use the result of
  • the CreateTimeSpan() without calling the method.
  • CreateTimeSpan() for 5 minutes results in the
  • number: 0.00347222222222. Use this instead of
  • the method call.
  • --->
  • <cfset THIS.SessionTimeout = 0.00347222222222 />
  •  
  • <cfelseif StructKeyExists( URL, "b" )>
  •  
  • <!---
  • Try to set an intermediary variable that stores
  • the result of the CreateTimeSpan() method, and
  • then applies that to the application setup.
  • --->
  • <cfset dtTimeSpan = CreateTimeSpan(
  • 0, <!--- Days. --->
  • 0, <!--- Hours. --->
  • 5, <!--- Minutes. --->
  • 0 <!--- Seconds. --->
  • ) />
  •  
  • <!--- Set the sessiontimeout. --->
  • <cfset THIS.SessionTimeout = dtTimeSpan />
  •  
  • <cfelseif StructKeyExists( URL, "c" )>
  •  
  • <!---
  • Try to set an intermediary variable that stores
  • the value we built in "a" and then applies that
  • to the application setup.
  • --->
  • <cfset dtTimeSpan = 0.00347222222222 />
  •  
  • <!--- Set the sessiontimeout. --->
  • <cfset THIS.SessionTimeout = dtTimeSpan />
  •  
  • <cfelseif StructKeyExists( URL, "d" )>
  •  
  • <!---
  • Try to set an intermediary variable that stores
  • the value we built in "a". However, this time,
  • store the value as a Java Double. and then applies
  • that to the application setup.
  • --->
  • <cfset dtTimeSpan = JavaCast(
  • "double",
  • 0.00347222222222
  • )/>
  •  
  • <!--- Set the sessiontimeout. --->
  • <cfset THIS.SessionTimeout = dtTimeSpan />
  •  
  • <cfelse>
  •  
  • <!---
  • For our default, we are just going to use
  • the CreateTimeSpan() directly.
  • --->
  • <cfset THIS.SessionTimeout = CreateTimeSpan(
  • 0, <!--- Days. --->
  • 0, <!--- Hours. --->
  • 5, <!--- Minutes. --->
  • 0 <!--- Seconds. --->
  • ) />
  •  
  • </cfif>
  •  
  •  
  • <!--- Set page settings. --->
  • <cfsetting
  • showdebugoutput="false"
  • />
  •  
  • </cfcomponent>

If I call "index.cfm" with no URL variable, we are setting the SESSION timeout using a direct CreateTimeSpan() call. This works just fine and outputs the SESSION information.

If I call "index.cfm?a", we are setting the SESSION timeout using the known result of our 5-minute CreateTimeSpan() call. CreateTimeSpan( 0, 0, 5, 0 ) returns the value 0.00347222222222. To test this for yourself see what (5 / 60 / 24) comes out to. When I try this methodology, it returns the ColdFusion error:

Element CFID is undefined in SESSION.

Clearly, the session is not working. If I call "index.cfm?b", we are setting an intermediary variable to a CreateTimeSpan() call and then setting the SESSION timeout equal to that variable. My theory here was that maybe indirect settings just would not work. This worked just fine, so it had nothing to do with where the CreateTimeSpan() was applied.

If I call "index.cfm?c", I set an intermediary variable to our known time span value, just to see if maybe directly setting the known value was breaking. This returns the same ColdFusion error as above.

I realized at this point, that it had nothing to do with directly or intermediary setting. It must have been something to do with the value returned by CreateTimeSpan() that was some how getting lost in translation to the known value. I decided that it was time to see what class of data we were even dealing with:

 Launch code in new window » Download code as text file »

  • #CreateTimeSpan( 0, 0, 5, 0 ).GetClass().GetName()#

... returns:

java.lang.Double

Ahhhhh! We are NOT dealing with just any old number. We are dealing with a Java Double. So, now, when I call "index.cfm?d", I set the intermediary value to the JavaCast-Double value of the known time span value. This works like a charm. This could be done without an intermediary variable as well.

That is very subtle. Very subtle indeed. I think the ColdFusion error is not helpful in this case. It's some sort of casting issue. When I put the known value of the time span directly in the code, ColdFusion sees this as String value. Then, it has to cast that to a numeric value for use with the SessionTimeout value. When casting from string, it must NOT cast to a double by default and then the value is not coming through.

This seems like a bug to me. But, then again, ColdFusion is typeless... how can I hold it accountable for not knowing which type of number to cast to.

Download Code Snippet ZIP File

Comments (5)  |  Post Comment  |  Ask Ben  |  Permalink  |  Other Searches  |  Print Page



Adobe ColdFusion 8.0.1 Update - Helping Programmers To Be Signifanctly Less Girlie - Download ColdFusion 8 Update 8.0.1 Now.

Reader Comments

Nice work Ben.
Please post the final code you use instead of createTimeSpan now.

Posted by Topper on Jul 30, 2007 at 1:45 PM


@Topper,

I actually still use the CreateTimeSpan(). It just seemed easier than trying to come up with a work-around. And, if I was gonna go with JavaCast(), I might as well just go with CreateTimeSpan().

Posted by Ben Nadel on Jul 30, 2007 at 2:24 PM


Makes sense. Thanks Ben.

Posted by Topper on Jul 30, 2007 at 6:36 PM


Found this little gem of information, i was tearing my hair out converting my application.cfm to application.cfc for the first time, getting session errors left and right.

In all my old application.cfm files, specifically the cfapplication tag, using sessiontimeout="0.02084" (30 minutes) works like a charm.

Posted by speshal on Aug 22, 2007 at 4:44 PM


Thanks

Posted by oyun on Dec 29, 2007 at 2:17 PM


Post Comment  |  Ask Ben


Home   |   Web Log   |   ColdFusion   |   Projects   |   Resume   |   Job Form   |   Search   |   Contact
Epicenter Consulting - Custom Software Solutions for Business Evolution HostMySite.com - The Leader In ColdFusion Hosting