Welcome!

ColdFusion Authors: Elizabeth White, Joseph Galarneau, Maureen O'Gara, Todd Anglin, Fuat Kircaali

Related Topics: ColdFusion

ColdFusion: Article

Extending ColdFusion

Extending ColdFusion

Welcome to another edition of Extending ColdFusion, where we discuss the multitude of ways you can extend your ColdFusion programming with user-defined functions (UDFs), custom tags, CFCs, and other methods. In this edition, we are going to delve into a "gray" area of CF development – use of hidden/internal methods. These are methods that exist within ColdFusion but are not documented. Be warned – while all of the following code works just fine in MX 6.1, there is no guarantee that it will continue to work in future versions. That being said, there is some cool functionality if you are willing to take some minor risks!

One of the most requested features for ColdFusion is a simple way to track sessions. As you know, ColdFusion has very simple and easy-to-use session management. What it does not have is a way to grab a list of sessions for an application. This can be useful for many reasons, and as I said, has long been requested. The UDF we will look at will use one of the unsupported methods of the ColdFusion server to get this information:

<cfscript>
function getSessions(appName) {
var tracker =
createObject("java","coldfusion.runtime.SessionTracker");
return tracker.getSessionCollection(appName);
}
</cfscript>

This UDF, written by Samuel Neff (sam@rewindlife.com), is extremely simple. One line grabs an instance of the Java object, coldfusion.runtime.SessionTracker. The second line calls a method on this object, getSessionCollection(), that returns a structure of sessions based on the application name you pass in. The structure is keyed by a unique session identifier, but if you really want to identify a particular session you'll have to look at the data. Figure 1 shows an example of running the following call:

<cfdump var="#getSessions(application.applicationName)#">

 

What is application.applicationName?
This is one of the default values that will always exist in the application scope. As you can probably guess, it returns the name of the current application. So what are some uses of this code? On CFLib.org, I have a scheduled event that runs once an hour. It records the total number of sessions to the database. In my administrator, I can then display a report of how many sessions were active on an hourly basis. CFLib.org also supports an optional login system. Since this information is stored in the session scope, I cannot only record how many active sessions there are, but how many sessions are from people who are active members of the site. The following code shows the script called by the scheduled task:

<cfscript>
function getSessions(appName) {
var tracker =
createObject("java","coldfusion.runtime.SessionTracker");
return tracker.getSessionCollection(appName);
}
</cfscript>
<cfset nSessions = 0>
<cfset nLoggedIn = 0>
<cfset sessions = getSessions(application.applicationName)>
<cfset nSessions = structCount(sessions)>
<cfloop item="s" collection="#sessions#">
<cfif structKeyExists(sessions[s],"username")>
<cfset nLoggedIn = nLoggedIn + 1>
</cfif>
</cfloop>
<cfquery name="updStats" datasource="#application.dsn#">
insert into tblStats(numberSessions,numberLoggedIn)
values(#nSessions#,#nLoggedIn#)
</cfquery>

The first few lines are simply the UDF repeated again. Then we create two variables – one for the total number of sessions and one for the number of logged-in users. To get the total number of sessions, all we need is the number of keys of the struct, which is returned by structCount(). To get the number of logged-in sessions, we loop over the structure and check for the "username" key. If it exits, it's a session with a logged-in user. Lastly, we insert both values into the database. (The table contains a column with a timestamp that defaults to the current time.) Figure 2 shows a graph report of the last 12 hours of sessions on the site.

 

As you can probably tell, there are numerous possibilities available with this UDF, but please remember that this is an unsupported function. As I said in the beginning, this feature has been requested for many years. If you would like to see this "hack" added as a real feature of ColdFusion, I strongly urge you to voice your opinion at www.macromedia.com/go/wish. To see more hidden features of ColdFusion sessions and applications, see the blog entry at rewindlife.com: www.rewindlife.com/archives/000069.cfm

Now, what do you do if you don't want to use hidden functions? It is possible to track sessions, but it's just a little bit more difficult. One simple way is to include the following code in your Application.cfm file:

<cfparam name="application.sessions" default="#structNew()#">
<cfset application.sessions[session.urlToken] = now()>

All this code does is define an application structure called sessions and then sets a key equal to session.urlToken, a value that is unique per session, with the value of the current time. Why do we set the time? ColdFusion automatically "clears up" sessions that have expired. For our solution, we have to do it ourselves. So, if you wanted to count the number of sessions online, you could simply loop over each value, check if it's more than your session timeout, and if so, remove the key. If you wanted to store additional information, you could simply use a more advanced structure:

<cfparam name="application.sessions" default="#structNew()#">
<cfset application.sessions[session.urlToken] = structNew()>
<cfset application.sessions[session.urlToken].lastHit = now()>
<cfset application.sessions[session.urlToken].whatever = whatever>

In this example, I create a substructure for each session and save the time of the last hit, along with a variable called whatever.

In conclusion, I hope you find the methods described above useful for your projects. If you would like to suggest a particular UDF, custom tag, CFC, or some other extension for this series, please e-mail me at jedimaster@mindseye.com.

More Stories By Ray Camden

A longtime ColdFusion user, Raymond is a co-author of the "Mastering ColdFusion" series published by Sybex Inc, as well as the lead author for the ColdFusion MX Developer's Handbook. He also presents at numerous conferences and contributes to online webzines. He and Rob Brooks-Bilson created and run the Common Function Library Project (www.cflib.org), an open source repository of ColdFusion UDFs. Raymond has helped form three ColdFusion User Groups and is the manager of the Acadiana MMUG.

Comments (1) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
Simon Hill 11/17/03 05:52:02 AM EST

Tried this but as I have UUID's for cftoken, get error..
"88ED407E77E19C23," on line 1, column 67, is not a valid identifer name.
Whichever way I try to interact with the session structure returned from coldfusion.runtime.SessionTracker, I get syntax error. If i swithch to non-UID cftokens, all is fine.
Thanks
Simon