Caveat When Calling Components From onSessionEnd()

As most ColdFusion developers know, you cannot reference ‘application’ scoped variables directly in Application.cfc’s onSessionEnd() method. Instead you need to use the ApplicationScope parameter. Notes from the docs:

You must use the ApplicationScope parameter to access the Application scope. You cannot reference the Application scope directly; for example, use Arguments.ApplicationScope.myVariable, not Application.myVariable. Use a named lock when you reference variables in the Application scope, as shown in the example.

I ran into this today when working on some code a colleague wrote which was firing a method in an application scoped component, the code was as follows:

1
2
3
4
5
6
7
<cffunction name="onSessionEnd" output="false" returnType="void">
  <cfargument name="SessionScope" required="true" />
  <cfargument name="AppScope" required="true" />
  <cfscript>
      arguments.AppScope.myCFC(arg=arguments.SessionScope.arg);
  </cfscript>
</cffunction>

Obviously this method is being executed when the users session has expired. The use of arguments.AppScope means I can access the ‘myCFC’ component which is stored in application scope.

Now to the actual problem…inside the cfc was a method which was logging information in the database, but the datasource value was coming from application scope.

1
<cfquery datasource="#application.dsn#" name="qInsert">

Obviously arguments should be passed to components instead of being accessed directly, but that’s another story :)

I would have thought this would work fine, but no luck. It was a little bit of a pain to debug as you can’t see the results of onSessionEnd() being run.

The fix was simply to pass in the required variables as arguments to the method:

1
2
3
4
5
6
7
<cffunction name="onSessionEnd" output="false" returnType="void">
  <cfargument name="SessionScope" required="true" />
  <cfargument name="AppScope" required="true" />
  <cfscript>
      arguments.AppScope.myCFC(arg=arguments.SessionScope.arg,dsn=arguments.Appscope.dsn);
  </cfscript>
</cffunction>

Either way, be careful when doing this particularly if the method is being called from multiple application points and one of those could be onSessionEnd().

Comments