1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Session Variable Question

Discussion in 'Programming' started by unitedlocalbands, Dec 7, 2007.

  1. #1
    Is there a way to capture when the session variables timeout and cause a query to run that will update a field in a database.

    I want to be able to tell coldfusion to update the users status to offline when he or she forgets to log off and their session variable timeout instead.

    thanks
     
    unitedlocalbands, Dec 7, 2007 IP
  2. cfStarlight

    cfStarlight Peon

    Messages:
    398
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #2
    cfStarlight, Dec 7, 2007 IP
  3. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #3
    Thanks for the tip. I'm not sure if my host is running Colfusion mx7. I asked and they said that they were but I could never get cfflash or cforms to work. I use MX7 to develope on my pc but when I would upload to the server the forms would fail to load. Also when I first set up my application.cfc file It seemed that things wernt working either.

    I had to switch to .cfm from .cfc inorder for my application to work.

    I'm going to try and upload an application.cfc file again because maybe I was making a mistake before that has been fiixed sence then.

    Thanks for the link too! :)
     
    unitedlocalbands, Dec 7, 2007 IP
  4. cfStarlight

    cfStarlight Peon

    Messages:
    398
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #4
    Dump the server scope. It should tell you what version you're using <cfdump var="#server#">.

    Yeh, problems with cfform and shared hosting are not uncommon. Sometimes its a mapping problem. CF needs access to certain files for the forms to work. The most common problem is (siteroot)/CFIDE/* not being accessible from your site root.
     
    cfStarlight, Dec 7, 2007 IP
  5. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #5
    So it turns out that setting up the application.cfc file is a little more tricky than an application.cfm

    But needless to say... with the help of my trusty "COLDFUSIONMX7" book by Ben Forta and Raymond Camden... I did finaly figure out what I was doing wrong in the application.cfc file.

    To some it up quickly... EVERYTHING

    Well now this is what I got working as of right now:

    
    
    <cfcomponent output="false">
             <cfset this.name="userid">
             <cfset this.clientmanagement="yes"> 
             <cfset this.clientstorage="cookie">
             <cfset this.sessionmanagement="yes"> 
             <cfset this.sessiontimeout=#CreateTimeSpan(0,0,0,10)#>
    <cferror type="exception" mailto="me@me.me" template="exception.cfm">
    	
        <cffunction name="OnSessionStart" returntype="void">
        </cffunction>
        
        <cffunction name="OnRequestStart" output="true" returntype="boolean">
    
    <cfset REQUEST.sitename = "Bla">
    <cfset REQUEST.companyname = "Bla">
    <cfset REQUEST.dataSource = "Bla">
    <cfset dbdsn = "Bla"> 
    <cfset dbuser = "Bla">
    <cfset dbpw = "Bla">
    
                   <cfinclude template="siteheader.cfm">
    
    		<cfreturn true>
    	</cffunction>
        
        <cffunction name="OnSessionEnd" returntype="void">
    <cfquery datasource="#request.datasource#" name="last_login">
    UPDATE USER_LOGIN
    
    SET LAST_LOGIN_DATE = #UTCDATE#,
        ONLINE = '0' 
        
    WHERE USERID = '#CLIENT.USERID#'
    </cfquery>
    
    </cffunction>
    </cfcomponent>
    
    Code (markup):
    The OnSessionEnd method I dont think is running the query. Although I'm 100% sure the session is timming out. I know this because It does clear the session variables for sure.

    Am I doing something wrong?

    Happy Holidays! :)
     
    unitedlocalbands, Dec 7, 2007 IP
  6. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #6
    Here is the OnSessionEnd function I'm using. It does not do what it looks like it may do. It doesnt create any errors either.

    
    <cffunction name="OnSessionEnd" output="yes" returntype="any">
        
    <cfset curDate = CreateODBCDateTime(NOW())>
    <cfset utcDate = DateConvert("local2utc", curDate)>
    
    <cfquery datasource="#request.datasource#" name="last_login">
    UPDATE USER_LOGIN
    
    SET 
        LAST_LOGIN_DATE = #UTCDATE#,
        ONLINE = '0' 
        WHERE USERID = '#CLIENT.USERID#'
    </cfquery>
    
    <CFSET Valid = true>
    <CFSET Error = "">
    
    <cfif IsDefined("application.onlinenow")>
            <cfset application.onlinenow = application.onlinenow -1>
            </cfif>
    
    <cfset client.userid = "" >
    <cfset session.userid = "">
    <cfset structDelete(session, "user_online")>
    
    </cffunction>
    
    Code (markup):
    Thanks for the help, I would really like to get this to work.
     
    unitedlocalbands, Dec 8, 2007 IP
  7. cfStarlight

    cfStarlight Peon

    Messages:
    398
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #7
    Yes, OnSessionEnd has a few behaviors that aren't immediately obvious.

    1) You have to add two arguments to the functions: the session scope and appplication scope.

    
    <cffunction name="onSessionEnd">
    	<cfargument name="SessionScope" required="true">
    	<cfargument name="AppScope" required="true">
            ... rest of code 
    </cffunction>
    
    Code (markup):
    2) Inside OnSessionEnd the session scope is available as arguments.SessionScope not session.

    
    ...
    <cffunction name="onSessionEnd">
    	<cfargument name="SessionScope" required="true">
    	<cfargument name="AppScope" required="true">
            ...   
          <cfset doSomething = arguments.SessionScope.someVariableName>
          ...
    </cffunction>
    
    Code (markup):
    3) As per the documentation, OnSessionEnd is not associated with a request. It's called automatically by CF. So that means you can't use variables in the Request scope.

    4) IIRC the most confusing thing about this function is that it doesn't let you know when an error occurs. I don't even think the errors show up in the logs. I suspect CF is throwing an error because of the Request variable, but its not letting you know.

    The best thing to do is test the function by adding some debug code to the function. Like one of these

    - use <cflog> to append a message to a log (if on local computer. you probably won't have access to log files in shared host environment).
    - use cffile to append a message to a text file in that directory
    - use <cfmail> to send yourself a message "OnSessionEnd function completed at #now()#"

    Start with a simple message to check whether the function is running at all. If that works, add in the next line of code. If it doesn't work, you'll know whether the problem is. Add in each line until everything is working as it should.

    5) Btw, the OnRequestStart function has an argument named "targetPage"

    
        <cffunction name="OnRequestStart">
    		<cfargument type="String" name="targetPage" required="true"/>	
    		<cfset REQUEST.sitename = "Bla">
    		<cfset REQUEST.companyname = "Bla">
    		<cfset REQUEST.dataSource = "Bla">
    		<cfset dbdsn = "Bla"> 
    		<cfset dbuser = "Bla">
    		<cfset dbpw = "Bla">
    	</cffunction>
    
    Code (markup):
     
    cfStarlight, Dec 8, 2007 IP
  8. cfStarlight

    cfStarlight Peon

    Messages:
    398
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #8
    Sorry if this is information overload :) but a few other things.

    1. You should always "var" scope all local function variables. ie variables only used inside that function.
    
    <cffunction name="OnSessionEnd" output="yes" returntype="any">
        
    <cfset [COLOR="DarkGreen"]var [/COLOR]curDate = CreateODBCDateTime(NOW())>
    <cfset [COLOR="DarkGreen"]var [/COLOR]utcDate = DateConvert("local2utc", curDate)>
    <!--- scope the query name variable --->
    <cfset [COLOR="DarkGreen"]var [/COLOR]last_login = "" />
    ....
    
    Code (markup):
    2. What is the purpose of these variables? Btw, IIRC ERROR is a reserved word in CF so you should use a different name.

    3. You must do an exclusive cflock on the aplication scope when you decrement the counter. Otherwise you might have problems with race conditions.

    
    <cfif StructKeyExists(application, "onlinenow")>
       <cflock type="exclusive" scope="application" timeout="10">
    	<cfset application.onlinenow = application.onlinenow -1>
       </cflock>
    </cfif>
    
    Code (markup):
     
    cfStarlight, Dec 8, 2007 IP
  9. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #9
    Here is what I got now. I dont think I have the cfmail tag configured correctly. I'm not getting an email. I'm going to try and run this app on my pc.




    
        <cffunction name="OnSessionEnd" output="yes" returntype="any">
        <cfargument name="SessionScope" required="true">
    	<cfargument name="AppScope" required="true">
    
    <cfset var curDate = CreateODBCDateTime(NOW())>
    <cfset var utcDate = DateConvert("local2utc", curDate)>
    <cfset var last_login = "">
    
    <cfquery datasource="unitedlocalbands" name="last_login">
    UPDATE USER_LOGIN
    
    SET 
        LAST_LOGIN_DATE = #UTCDATE#,
        ONLINE = '0' 
        WHERE USERID = '#CLIENT.USERID#'
    </cfquery>
    
    <cfif StructKeyExists(application, "onlinenow")>
       <cflock type="exclusive" scope="application" timeout="10">
    	<cfset Arguments.ApplicationScope.onlinenow = Arguments.ApplicationScope.onlinenow -1>
       </cflock>
    </cfif>
    
    <cfset client.userid = "" >
    <cfset Arguments.SessionScope.userid = "">
    <cfset structDelete(Arguments.SessionScope, "user_online")>
    
    <cfmail to="jamescreston@sbcglobal.net" from="jamesc@unitedlocalbands.com" subject="Error">
    
    "OnSessionEnd function completed at <cfoutput>#now()#</cfoutput>" 
    
    </cfmail>
    
    </cffunction>
    
    Code (markup):
     
    unitedlocalbands, Dec 8, 2007 IP
  10. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #10
    Thanks so much for the help. I checked out the livedocs and they were a little helpful.

    I'm pretty confident that the part on the OnSessionEnd function that counts how many people are logged in, is working perfect. This is the code here:

    
    <cfif StructKeyExists(application, "onlinenow")>
       <cflock type="exclusive" scope="application" timeout="10">
    	<cfset Arguments.ApplicationScope.onlinenow = Arguments.ApplicationScope.onlinenow -1>
       </cflock>
    </cfif>
    
    Code (markup):
    But the qurey I dont think is working, But Im going to run a test tonight before I go to bed.

    I'm going to log onto the web site on two different computers and let the session time out for both.

    If everyhing is working the onlinenow var should reflect the correct number of people logged in.


    Thanks again
     
    unitedlocalbands, Dec 8, 2007 IP
  11. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #11
    So it turns out that neither are working. The onSessionEnd has to be working though because the session dose time out and the session variables to expire.

    I'm going to keep looking around though.

    Talk to you soon.:)
     
    unitedlocalbands, Dec 9, 2007 IP
  12. cfStarlight

    cfStarlight Peon

    Messages:
    398
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #12
    One potential problem is the reference to the application scope. I think it should be called arguments.AppScope everywhere.

    Yes, not being able to see the error makes debugging more difficult. Try putting the code inside a cftry/cfcatch. Then cfmail yourself a message either way: success or fail/error. Then you'll know what's causing the function code to not work. But make sure your cfcatch code doesn't contain an error itself or you won't get a message. Not tested, but something like this

    
        <cftry>
            <cfset var ErrorKey = "" />
            <cfset [COLOR="Red"]var[/COLOR] curDate = CreateODBCDateTime(NOW())>
             ... rest of code
             
             <cfmail ....>  OnSessionEnd completed </cfmail>
           <cfcatch>
               <cfmail ....>  
                   OnSessionEnd FAILED:<br>
    	       <cfloop collection="#cfcatch#" item="ErrorKey">
    		     #ErrorKey# #cfcatch[ErrorKey]#<br>
    	       </cfloop>
               </cfmail>
           </cfcatch>
         </cftry>
    
    Code (markup):
     
    cfStarlight, Dec 9, 2007 IP
  13. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #13
    I found this blog here that shed some light on the matter.

    http://mkruger.cfwebtools.com/index.cfm?mode=entry&entry=9F213187-C6E0-643C-6485ECCB04151E3E

    Your right about how you have to referance the application scope variables.

    This is the code I have working right now... It works too good unfortunatly. I'm working on fine tunning it now:

    
    <cffunction name="OnSessionEnd">
        
         <cfargument name="SessionScope" required="true">
            <cfargument name="ApScope" required="true"> 
       
       <cflock type="exclusive" name="Applock" timeout="10">
    	<cfset ApScope.onlinenow = ApScope.onlinenow - 1>
       </cflock>
       
       <cfmail from="me@me.me" to="me@me.me" subject="on session end arguments" type="html">
          <cfdump var="#arguments#">
       </cfmail>
    
    </cffunction>
    
    Code (markup):
    One thing in the blog it said that you cant use the "scope" attribute in the cflock tag. You had to use name.

    The problem I'm having now is that every time session timesout This function will run. Thats what we want right...

    Well actually what we need is for the function to run everytime a session timesout but we only want to update the application.onlinenow variable when a user forgets to log out. and not everytime the session times out. So I'm thinking of a creative conditional statment to make this work.
     
    unitedlocalbands, Dec 9, 2007 IP
  14. cfStarlight

    cfStarlight Peon

    Messages:
    398
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #14
    Oh duh! Yes, that's totally right. If we could use the application scope directly we wouldn't be passing it in as an argument anyway ;) That's what I get for trying to do too many things at once today.
     
    cfStarlight, Dec 9, 2007 IP
  15. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #15
    I still cant get the query to take place.

    Do I have to access the client variables the same way:

    Here is the function now.
    
    <cffunction name="OnSessionEnd">
         
         <cfargument name="SessionScope" required="true">
            <cfargument name="ApScope" required="true"> 
    
              <cfquery datasource="" name="useronline"> 
              SELECT USER_LOGIN.ONLINE
              FROM USER_LOGIN
              WHERE USER_LOGIN.USERID = '#CLIENT.USERID#'
              </cfquery>
              
             <cfmail from="me@sme.net" to="me@me.net" subject="on session end arguments" type="html">
          <cfdump var="#useronline.online#">
       </cfmail>
        
      
              
       <cflock type="exclusive" name="Applock" timeout="10">
    	<cfset ApScope.onlinenow = ApScope.onlinenow + 0>
       </cflock>
       
    
    </cffunction>
    
    Code (markup):
     
    unitedlocalbands, Dec 9, 2007 IP
  16. cfStarlight

    cfStarlight Peon

    Messages:
    398
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #16
    Do client variables actually exist in OnSessionEnd? I'm thinking they don't since OnSessionEnd isn't associated with a Request. But I rarely use client variables ..
     
    cfStarlight, Dec 9, 2007 IP
  17. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #17
    They do not exist in the onsessionend method... I found this out the hard way. Back to squar one for now.. I have to re think this whole thing.

    Thanks for your help,
     
    unitedlocalbands, Dec 9, 2007 IP
  18. cfStarlight

    cfStarlight Peon

    Messages:
    398
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #18
    Good luck with it. Sorry I couldn't be of more help. Its been a busy w/e!
     
    cfStarlight, Dec 9, 2007 IP
  19. unitedlocalbands

    unitedlocalbands Well-Known Member

    Messages:
    246
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    128
    #19
    How about this...

    If I built a timer that will start after a page loads and upon the timer running out then cf would clear the session variables.

    I woudl have to set the "sessiontimout"out to like 15 minutes and then I would build my timer to timeout like in ten minutes.

    something like this:
    
    <cffunction name="OnRequestEnd" output="true" returntype="string">
    
    <cfset var timeout = CreateTimeSpan(0,0,10,0>
    
    <cfif timeout eq 0>
    <cfset session.userid = "">
    </cfif>
    
    Code (markup):
    Thanks
     
    unitedlocalbands, Dec 10, 2007 IP
  20. cfStarlight

    cfStarlight Peon

    Messages:
    398
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #20
    But why do you need a timer? It seems like that's the point of onSessionEnd. If you set the session timeout to 10 minutes, all session variables will be cleared when the session times out. ie When 10+ minutes have elapsed with no user activity. Plus if you stored the user id as a session variable, you would have access to the value in OnSessionEnd.
     
    cfStarlight, Dec 10, 2007 IP