Extended Operations on ColdFusion Sessions

posted May 20th 2005 at 2203 EDT in All, ColdFusion

This article overviews a number of undocumented functions which can be performed on ColdFusion sessions to extend their usage.

Background

The original problem I was trying to tackle was finding a way to manually expire a session in order to get ColdFusion to reclaim that memory space.

The ColdFusion Documentation recomends invalidating a session using:


<cfscript>getPageContext().getSession().invalidate();</cfscript>

This does invalidate a session so future pages requests with that session ID throw errors when accessing the session scope, but it does not timeout that session so the memory is reclaimed. Data put in the session scope continues to persist untill the sessiontimeout attribute in the <cfapplication> tag.

Further, when a new request is made for a previously invalidated session the browser gets an ugly message instead of a new session. Using setMaxInactiveInterval() below solves that to!

There are a number of other java methods which can be performed on the ColdFusion session, so lets take a look.

getSessionCount()

Ever want to know how many sessions are currently active? You can get that data from coldfusion.runtime.SessionTracker.


<cfset tracker = createObject("java","coldfusion.runtime.SessionTracker")>
<cfoutput><p>There are #tracker.getSessionCount()# active sessions</p></cfoutput>

getSessionCollection()

If it isn't enough to know how many sessions there are, and you want to know what data is stored in the session scope on EVERY active session on the server... you can do that to.


<cfset tracker = createObject("java","coldfusion.runtime.SessionTracker")>
<cfset sessions = tracker.getSessionCollection(application.applicationName)>
<cfdump var="#sessions#">

setMaxInactiveInterval()

To change the timeout value of the current session from the value specified in the <cfapplication> tag, use the setMaxInactiveInterval() funcation. This function takes a value which is the number of seconds to allow before reclaiming that session. Interestingly this does not work when used against the getPageContext().getSession() object even though you would expect it to. A paramater of 1 will effectivly emulate the suggested invalidate() function by reclaiming the session after 1 second of inactivity. (note: there may be a slight delay between when that session is inactive and when ColdFusion checks it's inactivity to reclaim it. The session is still active during that time.) To set the current session to timeout after 5 minutes we would run:


<cfscript>session.setMaxInactiveInterval(280);</cfscript>

getTimeSinceLastAccess()

To find the number of seconds a session has been inactive use:


<cfoutput><p>Last request was #session.getTimeSinceLastAccess()# seconds ago</p></cfoutput>

If you want to see all this data for every session we need to go about this in a more round about way. If we simply looped through all the sessions above and checked the time since last access, that last access for each session would be updated (not good). To work around this as mentioned on rewindlife we need to use reflection.


<cfset tracker = createObject("java","coldfusion.runtime.SessionTracker")>
<cfset sessions = tracker.getSessionCollection(application.applicationName)>
<cfscript>
a = ArrayNew(1);
sessionClass = a.getClass.forName("coldfusion.runtime.SessionScope");
getTimeSinceLastAccessMethod = sessionClass.getMethod("getTimeSinceLastAcccess",a);
</cfscript>
<cfloop item="s" collection="#sessions#">
    <cfoutput>#s# - #getTimeSinceLastAccessMethod(sessions[s],a)#<br></cfoutput>
</cfloop>

25 Responses

  1. #1 barry.b
    5 years, 2 months ago

    one thing that Pete Freitag didn’t really address is the “undocumented nature” of things like:

    createObject(“java”,”coldfusion.runtime.SessionTracker”)

    that particularly is something that we could use right now but if MACR can pull the pin on that bit of hidden “kit” then the app breaks…which is why they remain undocumented!

    Trouble is, I’ve been trying to find a way to do the same thing as the SessionTracker but that’s “legit” – and I haven’t had any luck yet..

    oh well, back to the drawing board

    cheers
    barry.b

  2. #2 jehiah
    5 years, 2 months ago

    I should also mention that this is all for MX 6.1 Can anyone verify if these methods are accessable/work on 7?

  3. #3 OliS!
    5 years, 1 month ago

    Great Idea! But the last script doesn’t work for me. I get the following error:

    You have attempted to dereference a scalar variable of type class coldfusion.runtime.Array as a structure with members.

    The line

    sessionClass = a.getClass.forName(“coldfusion.runtime.SessionScope”);

    seems to responsible. I am using CFMX 6.1

  4. #4 OliS!
    5 years, 1 month ago

    Ah, i figured it out by myself. the line should read:

    a.getClass().forName(“coldfusion.runtime.SessionScope”);

  5. #5 OliS!
    5 years, 1 month ago

    Hi!
    Me again. Does anybody know, who to output a session variable without modifiying the timeSinceLastAccess?
    I like to have a page that displays all current sessions with sessionname, getTimeSinceLastAccess()
    Thanks oli

  6. #6 jehiah
    5 years, 1 month ago

    Does the workaround using relection work for you?

    I am assuming you are just doing session.getTimeSinceLastAccess() now?

  7. #7 OliS!
    5 years, 1 month ago

    Hi!
    I am using …
    sessionClass.getMethod(“getTimeSinceLastAcccess”,a); …
    So what i want to know is how to use reflection to get the content of session variables without modifying the lastAccess timestamp.

  8. #8 df
    4 years, 11 months ago

    Your example is fraught with spelling errors:

    getTimeSinceLasatAccessMethod

    getTimeSinceLastAcccess

  9. #9 Mal
    4 years, 11 months ago

    Do we need to lock the session scope when using the SessionTracker object?

  10. #10 jehiah
    4 years, 11 months ago

    Only for destructive operations. If you are just reading last access times you don’t need to lock the session.

  11. #11 Gus
    4 years, 6 months ago

    I had assumed that when using J2EE sessions that sessiontracker would only maintain active sessions but it includes those that have yet to timeout.

    Users closing the browser and ending the session does not update sessiontracker. So yeah just be aware that you have some stale info in your count.

  12. #12 David Boyer
    4 years, 2 months ago

    Just letting you know that these functions all appear to be working on MX7 (7.0.1 to be exact). Although your final section of code falls over with a “You have attempted to dereference a scalar variable of type class coldfusion.runtime.Array as a structure with members.” error. I did notice too that getSessionCount returns the number of sessions for the whole server but getSessionCollection is returning sessions only for the current application.

  13. #13 Alan Rother
    2 years, 8 months ago

    Just to keep this thread up to date. This still works in CF8!!!

  14. [...] I’ve put together the following code which is based on information others have posted to grab session information for all sessions on a single application or all applications. The trick about this code is that you’re accessing other sessions, not just the one you might be using. [...]

  15. #15 Fr33d0m
    2 years, 5 months ago

    Not sure how anyone can say this works for 7 or 8. If it returns an scalar dereference error on sessionClass = a.getClass.forName(“coldfusion.runtime.SessionScope”); then you simply cannot say it works!

  16. #16 Zuratharamon
    2 years, 3 months ago

    Freedom, did you read ANY of the comments?

    a.getClass().forName(”coldfusion.runtime.SessionScope”);

    After getClass put some () and it will solve your problem.

    I confirm that it works in CF7

  17. #17 Wubinator
    2 years, 1 month ago

    And confirmed that it works in CF8 (I’m running 8.01)

  18. #18 Richard
    2 years ago

    In ColdFusion 8, after adding the missing brackets, I’m now getting a different error:
    “Unable to invoke method getMethod on object class coldfusion.runtime.SessionScope.”

    Any ideas?

  19. #19 Gus
    1 year, 10 months ago

    I have an interesting problem that maybe the collective brains trust can either solve or at least put a spotlight on my ignorance !!
    I am trying to secure a login page on a server with a shared certificate.

    I have a site in it’s URL which is fine as http://www.yyy.com
    The server has a shared cert https://secured.zzz.com/ yyy where yyy is a virtual directory which is the same directory as the root for http://www.yyy.com

    I wish to have a user login through the secured site and when the session vars are set continue the session at http://www.yyy.com. I have tried using passing the session in the URL string but I cannot access my session vars. Is what I am doing actually possible ?

    CF 6.1MX
    IIS6 web server
    MS SQL server 2000

    Gus

  20. #20 Mike Causer
    1 year, 6 months ago

    CF8 working example:
    loc = {};
    loc.tracker = createObject(“java”,”coldfusion.runtime.SessionTracker”);
    loc.count = ‘There are #loc.tracker.getSessionCount()# active sessions’;
    loc.sessions = loc.tracker.getSessionCollection(application.applicationName);

    loc.array = [];
    loc.sessionClass = loc.array.getClass().forName(“coldfusion.runtime.SessionScope”);
    loc.getTimeSinceLastAccessMethod = loc.sessionClass.getMethod(“getTimeSinceLastAccess”,loc.array);

    loc.rtn = [];
    for ( loc.s in loc.sessions )
    {
    arrayAppend( loc.rtn, loc.s & ‘ – ‘ & loc.getTimeSinceLastAccessMethod.invoke( loc.sessions[loc.s], loc.array ) );
    }

  21. #21 David
    1 year, 3 months ago

    I would like to know how to get the content of session variables using this method but without modifying the lastAccess timestamp. Anyone know how? Is Mike Causer’s post supposed to answer this? I can’t tell. I ran his code but my session’s “Last Accessed” time changed back to zero when I did. I am using CF 8.1 Ent (Jrun install). Thanks.

  22. #22 Mike Causer
    12 months ago

    @David – You can use the above example to get another session’s last access time. I have not found a way of getting details from the current session without resetting its last access time / extending the session.

    To access a string “userid” stored in each session scope on the server, you can use the below example to get the value without updating the session. Only works on sessions other than the current.
    loc.st = createObject(“java”,”coldfusion.runtime.SessionTracker”);
    loc.sc = loc.st.getSessionCollection(“MyAppName”);
    loc.a = [];
    loc.ss = loc.a.getClass().forName(“coldfusion.runtime.SessionScope”);
    loc.a[1] = createObject(“java”,”java.lang.String”).getClass();
    loc.method = loc.ss.getMethod(“getValueWIthoutChange”,loc.a);
    // note the uppercase “I” in getValueWIthoutChange – it is case sensitive
    loc.a[1] = createObject(“java”,”java.lang.String”).init(“userid”);
    loc.rtn = “”;
    for ( loc.s in loc.sc ) {
    loc.rtn &= “

    sessid: ” & loc.s & “userid: ” & loc.method.invoke( loc.sessions.get(loc.s), loc.a ) & “

    “;
    }

  23. #23 Mike Causer
    12 months ago

    looks like the example stuffed up. here is part of it again:
    loc.rtn &= “{p}sessid: ” & loc.s & “{br}userid: ” & loc.method.invoke( loc.sessions.get(loc.s), loc.a ) & “{/p}”;

    replace { with <
    replace } with >

  24. #24 Danny Armstrong
    11 months, 1 week ago

    @Mike

    In post 20, did you run the script multiple times to see if the return from getTimeSinceLastAccess would be reset after previous invocations of that method? The method seems to report the time since last access AND then modifies the last access time to 0.

    This is the behavior I’m observing in my tests. They seem to corroborate the post here: http://rewindlife.com/2003/09/08/undocumented-application-scope-functions/#comment-271(the last post by Guillaume)

    Can the getValueWIthoutChange method be used to get the LastAccess time too?

  25. #25 Danny Armstrong
    11 months, 1 week ago

    I think my tests were not performing correctly because I was doing a dump on the resulting object, which included a dump of the sessions. And modifies the access time! Very tricky.
    Using the methods described here made it work because there were no dumps involved or anything that begged to be dumped: http://cfteeps.blogspot.com/2008/09/undocumented-goodness.html

    I think Guillaume’s post I referred to in #24 must be outdated.