Friday, March 19, 2010    
Home My Books Blog ColdFusion About Me Back    

Calendar
<< Nov 2007 >>
S M T W T F S
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  

Search

Categories
 • Acrobat (3) [RSS]
 • Adobe (90) [RSS]
 • AdobeMAX06 (45) [RSS]
 • AdobeMAX07 (59) [RSS]
 • AdobeMAX08 (66) [RSS]
 • AdobeMAX09 (39) [RSS]
 • AdobeMAX10 (1) [RSS]
 • AIR (219) [RSS]
 • Appearances (191) [RSS]
 • Books (72) [RSS]
 • CFEclipse (15) [RSS]
 • ColdFusion (1381) [RSS]
 • Data Services (34) [RSS]
 • Fish Tank (5) [RSS]
 • Flash (197) [RSS]
 • Flex (498) [RSS]
 • Home Automation (5) [RSS]
 • Jobs (116) [RSS]
 • JRun (14) [RSS]
 • Labs (43) [RSS]
 • LiveCycle (34) [RSS]
 • MAX (232) [RSS]
 • Mobile (120) [RSS]
 • Regular Expressions (17) [RSS]
 • RIA (21) [RSS]
 • SQL (40) [RSS]
 • Stuff (536) [RSS]
 • Tips (CF Studio) (80) [RSS]
 • Tips (CF) (795) [RSS]
 • Tips (Dreamweaver) (91) [RSS]
 • Tips (Flex Builder) (2) [RSS]
 • Using CF (162) [RSS]

Other BLOGs
 • Charlie Arehart
 • Lee Brimelow
 • Ray Camden
 • Christophe Coenraets
 • Sean Corfield
 • Mihai Corlan
 • Cornel Creanga
 • Mark Doherty
 • John Dowdell
 • Danny Dura
 • Enrique Duvos
 • Steven Erat
 • Kevin Hoyt
 • Serge Jespers
 • Adam Lehman
 • Duane Nickull
 • Miti Pricope
 • Andrew Shorten
 • Ryan Stewart
 • James Ward
 • Greg Wilson
 • Full As A Goog

RSS Feeds
 • Feed
 • Subscribe

Join my mailing list and find out about new books and other topics of interest.

Thoughts, ideas, tips, musings, and pontifications (not necessarily in that order) by Ben Forta ...
NOTE: This is my personal blog, and the opinions and statements voiced here are my own.

Viewing By Day : November 15, 2007 / Main
November 15, 2007

Flex And ColdFusion Session Variables

A year or so ago I posted an entry explaining why, as a rule, managing session state on the server (as ColdFusion does) was not ideal in Flex applications. I still stand by that assertion. But, many have pointed out that it is sometimes necessary to access ColdFusion session data from within Flex applications. Indeed, I was asked about this several times in the past week alone. And so, time to update the topic.

ColdFusion stores session variables on the server. In order to know which subset of session data belongs to a specific client, ColdFusion creates an identifier that is sent to the client (usually as cookies, but it could also be a URL parameter). The identifier must be sent back to ColdFusion on each and every subsequent request so that ColdFusion may make the correct server-side session data available. Without the identifier, ColdFusion will assume that there is no active session, and will the create a new session and attempt to send a new identifier to the client.

Flex applications run within the Flash Player, not within ColdFusion. As such, Flex applications have no direct access to ColdFusion session data. But, if you were to create a Flex application with a ColdFusion back-end, that Flex application could indeed gain access to ColdFusion session data as needed. Here's how it works.

The preferred way for Flex to connect to ColdFusion is via Flash Remoting - using AMF to connect to a ColdFusion Component. AMF actually communicates back to ColdFusion via HTTP and the web browser. As such, if ColdFusion's session identifier exists in the browser, it will be sent back with Flash Remoting requests. Similarly, if the browser receives identifier cookies along with AMF results, those cookies will be saved. In other words, when you use to connect to a ColdFusion Component, ColdFusion is fully aware of session state management, and the CFC being invoked automatically has access to the correct session data.

But, how can Flex get to that data? The answer is it can't, but you can create a CFC that exposes session variables.

Caution: Before you go further I will point out the obvious. If you create a public facing CFC that exposes methods that allow session data to be directly manipulated, well, you've now allowed public access to session data. Of course, callers will only have access to their own session data, but still, proceed with caution, and make sure you fully understand what you are doing.

Ok, here is the session.cfc file:

<cfcomponent>

    <!--- Set a CF session variable --->
    <cffunction name="set" access="remote">
        <cfargument name="name" type="string" required="yes">
        <cfargument name="value" type="string" required="yes">

        <!--- Set SESSION var --->
        <cfset SESSION[ARGUMENTS.name]=Trim(ARGUMENTS.value)>

    </cffunction>


    <!--- Get a CF session variable --->
    <cffunction name="get" access="remote" returntype="any">
        <cfargument name="name" type="string" required="yes">

        <!--- Init local var --->
        <cfset var result="">

        <!--- Get SESSION var if it exists --->
        <cfif StructKeyExists(SESSION, ARGUMENTS.name)>
            <cfset result=SESSION[ARGUMENTS.name]>
        </cfif>

        <!--- Return it --->
        <cfreturn result>

    </cffunction>


    <!--- List session variable names --->
    <cffunction name="list" access="remote" returntype="array">

        <!--- Return it --->
        <cfreturn ListToArray(ListSort(StructKeyList(SESSION), "text"))>

    </cffunction>


    <!--- Keep alive --->
    <cffunction name="keepAlive" access="remote">
        <!--- Nothing to do here --->
    </cffunction>


</cfcomponent>

As you can see, the code is pretty simple. SESSION is actually a ColdFusion structure, and so direct session access is possible using CFML structure functions. The "list" method returns an array of session variables (their names). The "get" method gets the contents of a specific session variable. And the "set" method sets a session variable, creating or updating as needed (this example only creates simple variables). The final method, named "keepAlive" does nothing, and it can be called as needed to keep the session alive (ensuring that it does not time out).

To help test the app (and to populate it with data) you can use a simple test page like this:

<!--- Init vars --->
<cfparam name="FORM.varName" default="">
<cfparam name="FORM.varValue" default="">

<!--- Process form if submitted --->
<cfif Trim(FORM.varName) NEQ "" AND Trim(FORM.varValue) NEQ "">
    <cfinvoke component="session"
                method="set"
                name="#Trim(FORM.varName)#"
                value="#Trim(FORM.varValue)#">

</cfif>

<!--- Dump SESSION scope --->
<cfdump var="#SESSION#">

<!--- Form --->
<hr>
<cfform action="#CGI.SCRIPT_NAME#">
Variable:
<cfinput type="text" name="varName" required="yes">
Value:
<cfinput type="text" name="varValue" required="yes">
<br />
<cfinput type="submit" name="sbmt" value="Save SESSION variable">
</cfform>

How to use session.cfc from within Flex? Here is a simple example application:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="vertical" width="100%" height="100%"
    creationComplete="initApp()">


    <mx:Script>
        <![CDATA[
            import flash.events.TimerEvent;
            import mx.utils.ObjectUtil;

            // Timer thread handle

            private var timer:Timer;

            // Initialize app

            private function initApp():void
            {
                // "Keep alive" interval

                var pingSeconds:int=60;

                // Get session list

                session.list();

                // Create "keep alive" timer

                timer=new Timer(pingSeconds*1000);
                timer.addEventListener("timer", timerHandler);
                timer.start();
            }

            // Timer handler

            private function timerHandler(event:TimerEvent):void
            {
                // Ping CF session to keep alive

                session.keepAlive();
            }

            // Get a CF session variable

            private function sessionGet(varName:String):void
            {
                // Get it

                session.get(varName);
            }

            // Set a CF session variable

            private function sessionSet(varName:String, varValue:String):void
            {
                // Save it

                session.set(varName, varValue);
                // Update list

                session.list();
            }
        ]]>

    </mx:Script>

    <!-- Define CFC -->
    <mx:RemoteObject id="session"
                        destination="ColdFusion"
                        source="CFFlex.session"
                        showBusyCursor="true" />


    <!-- GET panel -->
    <mx:Panel width="100%" height="100%"
            title="ColdFusion SESSION Variables">

        <mx:HBox width="100%" height="100%">
            <!-- List fo session variables -->
            <mx:List id="sessionList"
                    dataProvider="{session.list.lastResult}"
                    click="session.get(sessionList.selectedItem)"
                    height="100%" width="200"/>

            <!-- Display value -->
            <mx:TextArea text="{ObjectUtil.toString(session.get.lastResult)}"
                    editable="false"
                    width="100%" height="100%" />

        </mx:HBox>
    </mx:Panel>

    <!-- SET panel -->
    <mx:Panel width="100%" height="150"
            title="Set ColdFusion SESSION Variable">

        <!-- Variable create form -->
        <mx:Form width="100%" height="100%">
            <mx:FormItem label="Variable:" width="100%">
                <mx:TextInput id="varName" width="100%"/>
            </mx:FormItem>
            <mx:FormItem label="Value:" width="100%">
                <mx:TextInput id="varValue" width="100%"/>
            </mx:FormItem>
            <mx:FormItem>
                <mx:Button label="Save"
                    click="sessionSet(varName.text, varValue.text)"/>

            </mx:FormItem>
        </mx:Form>
    </mx:Panel>

</mx:Application>

The application features two panels. The first displays a list of ColdFusion session variables (by calling the session.list() method), allowing them to be selected to display their contents (by calling the session.get() method). The second contains a form that can be used to create new session variables (by calling the session.list() method). To ensure that the ColdFusion session does not time out, a Flash timer is defined, and it pings the keepAlive() method (once a minute in this example).

Now, I would still caution you by saying that, as a rule, if data needs to persist it should persist on the client, within the Flex application. But, when you do need access to ColdFusion session data, this technique will do the trick.

Updated 11/16/2007 to add timer and keepAlive logic.


Scott Stroz On ColdFusion Exchange Integration

Scott Stroz has written a really useful article for the ColdFusion Developer Center entitled Using ColdFusion 8 with Microsoft Exchange Server.


The AIR Logo

As per Mike Chambers, this is the official AIR logo:

  © Copyright 1997-2009 Ben Forta, All Rights Reserved