I stumbled across four useful functions that exist in the Application scope.
getMaxInactiveInterval = #application.getMaxInactiveInterval()#
getElapsedTime = #application.getElapsedTime()#
getTimeSinceLastAccess = #application.getTimeSinceLastAccess()#
expired = #application.expired()#
UPDATE. These four functions also work on the Session scope.
They’re undocumented so they may not exist or be accessible in a future version, but there’s no security risk with them so they’re not very likely to change.
getMaxInactiveInterval() returns the timeout set for the current application. If you want the server default timeout you can grab it from the runtime service.
The following is most of the information available to you from the runtime service.
factoryClass = CreateObject("java", "coldfusion.server.ServiceFactory");
rt = factoryClass.runtimeService;
getApplicationMaxTimeout = '#rt.getApplicationMaxTimeout()#' getApplicationTimeout = '#rt.getApplicationTimeout()#' getAppServer = '#rt.getAppServer()#' getComMapperDir = '#rt.getComMapperDir()#' getDefaultCharset = '#rt.getDefaultCharset()#' getDefaultMailCharset = '#rt.getDefaultMailCharset()#' getMaxQueued = '#rt.getMaxQueued()#' getMinRequests = '#rt.getMinRequests()#' getNumberSimultaneousRequests = '#rt.getNumberSimultaneousRequests()#' getRegistryDir = '#rt.getRegistryDir()#' getRequestTimeoutLimit = '#rt.getRequestTimeoutLimit()#' getRootDir = '#rt.getRootDir()#' getSaveClassFiles = '#rt.getSaveClassFiles()#' getSessionMaxTimeout = '#rt.getSessionMaxTimeout()#' getSessionTimeout = '#rt.getSessionTimeout()#' getSlowRequestLimit = '#rt.getSlowRequestLimit()#' getTemplateCacheSize = '#rt.getTemplateCacheSize()#' getWhitespace = '#rt.getWhitespace()#' isApplicationEnabled = '#rt.isApplicationEnabled()#' isCachePaths = '#rt.isCachePaths()#' isPureJavaKit = '#rt.isPureJavaKit()#' isSessionEnabled = '#rt.isSessionEnabled()#' isTrustedCache = '#rt.isTrustedCache()#' logSlowRequests = '#rt.logSlowRequests()#' timeoutRequests = '#rt.timeoutRequests()#' useJ2eeSession = '#rt.useJ2eeSession()#'
This isn’t a complete listing of everything available but it’s everything I thought would be interesting.
UPDATE Ray brought up a very good point. Whenever you call any of the undocumented scope methods on an Application or Session reference it updates the last access timestamp and therefore returns undesirable results for getTimeSinceLastAccess() and other time related functions.
To call the function and not have it update the last access time you have to use reflection, as in this example.
a = arrayNew(1);
sessionClass = a.getClass().forName("coldfusion.runtime.SessionScope");
timeMethod = sessionClass.getMethod("getTimeSinceLastAccess", a);
#loopSession#:
#timeMethod.invoke(sessions[loopSession], a)#
Tests using reflect product appropriate results, as follows.
sessionInfoTester_300_60747953: 10 sessionInfoTester_500_52154508: 3374 sessionInfoTester_600_25316452: 570079 sessionInfoTester_501_37754600: 569959
it looks like these are redsky only, just tried on my host (still mx) & got bad method errors.
It seems like getTimeSinceLastAccess() always returns 0 for _all_ sessions.
Ray, you’re right as always. Calls to the undocumented functions reset the last access time and thus make direct calls to the time methods useless. Calls via reflection do not set the last access time and thus produce proper results. I updated the entry above and added a new code example.
What exactly does the expired() function do/return?
Expired returns true or false if the session has expired. This is only valid if you access a session other than the one your code is running in.
Remember, these are undocumented functions that are not meant for us to use directly. They are made for CF’s own intenal use. Presumably, CF calls expired() on a schedule in order to remove expired sessions.
What about page expire. Is there a way to force it? I try to do it for a long time. Nobody knows how to do it inside CFML. I searching for the code on online forums (Macromedia), but nothing. Please,HELP!!
What do you mean by page expiring – you mean forcing the browser to get the latest version? You can do that with simple meta tags. Its NOT a CFML thing, but a browser thing.
I mean to write code in CFML that would disable BACK button (secure applications). Thanks for your time.
gorandri,
Please post generic CF questions in http://webforums.macromedia.com/colfusion
Thanks,
Sam
Note: there’s a difference between the GetMaxInactiveInterval() for application (which returns milliseconds) and session (which returns seconds).
I’m not relying on these functions too heavily, because I’d expect them to change somewhat, or at least be reworked when released into the wild…
Tyler – if we design a nice CFC to wrap this stuff up, it may be a bit easier to handle changes. As long as we can continue to get the internal stuff, we can change the inner methods and keep the external methods using the same name. Maybe I’ll work on this sometime this week.
I was trying to find out the no of sessions currectly active and i used this code in my .cfm page….i loaded java and refered to the class path..but i am getting
Unhandled System exception ! java.security.AccessControlException: access denied (java.lang.RuntimePermission createClassLoader). Java exception occurred in attempt to construct object.
error…how do i solve it….
my Code:
function getSessions(appName) {
var tracker = createObject(“java”,”coldfusion.runtime.SessionTracker”);
return tracker.getSessionCollection(appName);
}
Total Users Logged on is #nLoggedIn#
Vijay, the AccessControlException problem was a bug in CFMX that was fixed in CFMX 6.1. Upgrade to 6.1 and it should fix the problem.
Sam,
When I use structkeyexists to access the structure returned by tracker.getSessionCollection(application.applicationName), it seems update the last access timestamp for every elements in the structure.
But I dont know how to use reflection to solve this problem since structkeyexists is a cf fuction.
Please give me a hint!
Thanks!
How can I access session variables to avoid updating last access timestamp?
Uwe,
Please read the end of the blog entry after the Update notice. You need to use reflection to call some methods so as not to affect the outcome. Example code is above.
Sam
Hi Sam,
I already use reflection to call the methods as shown above. But I still do not know how to access the variables of another session without updating their last access timestamp. So what I am lookig for is some kind of “field reflection”.
Ah, now I see what you mean. Reflection won’t work on the CF variables because they aren’t really Java variables attached to the session object.
CF Session’s extend Java’s Hashtable so you should be able to use reflection to call the get() method and pass in the sesion key, which is always all uppercase when sent to get().
Sorry I don’t have time to test this out now and provide a complete example, but hopefully this will get you further along.
Best regards,
Sam
The reflection doesn’t work on the SessionScope object using the get() method ( I tried…), the last access timestamp is always updated !
If you are a bit curious and look at the java decompiled code of the SessionScope.class, you will see that all the methods allowing to set or get your session variables ( even the clone() or toString() methods) udpate the LastAccess attribute of the SessionScope object.
Sorry, no solution this way…
Regards,
Guillaume
I need to find a way to check the presence of an already logged in user.
I may keep his status as logged in, but if the browser or the line crashes there is no way to restore its logged-in flag.
Is there any way to monitor, at least, its session to see if it is still active ? I see that there is a function that is called “expired()” but I can’t understand how to use it.
Thanks in advance for your help.