Flex and the Coldfusion Session - Reacting to Changes

Ben Forta was kind enough to give us a framework for linking Flex to the Coldfusion session scope while maintaining that we ought not to use it. I have availed myself to its use, particularly by expanding on the keepAlive method.

[Edit: Having re-read this, I feel obliged to say that Ben's reasons are sound and I didn't mean to seem dismissive of his admonishments. However my requirements, and desire to play with Flex, pretty much forced me into it and I think I have satisfied the potential security issues as described in the Addendum-de-dum-dum]

keepAlive is a handy little pulse you can tie to a TimerEvent.TIMER eventhandler in Flex. In Ben's scenario, keepAlive doesn't do anything; it's sole purpose in life is to ping the session and keep it going. However, I have created order completion frontends in Flex that are preceded by a series of Coldfusion pages. My final billing Flex app receives the session, and does all sort of wonderful things ... like collect the money that sustains my salary. However, my career is a constant exploration in the weird behaviors of semi-self-aware simians. That is, people do the oddest things. So, while my Flex app is shaking down a customer, they may open a new browser window and elect to clear their cart or log out. An earthquake could knock out their Internet connection or whatever. Bad things happen to my apps.

So what I've done is to load up my keepAlive pulse with a little extra info. First, since I am in a cart scenario, I make sure that my cart still exists - for the legacy app upon which I strive to improve, it is important that the cart exist after payment, at least for just a little while. I also make sure that they are still logged in. I also pay attention to dead response - that is, if my ResultObject.result is null, for any reason, I want to know about it. Actually, in this last case, I count how many times this occurs and, after a threshold limit, I kill the flex session.

So on the Coldfusion side it might look like the following:


<!--- Keep alive --->
<cffunction name="keepAlive" access="remote" returntype="struct">    
<cfscript>
var returnStruct = StructNew();        

returnStruct.LOGGEDIN = functionIsLoggedIn();
returnStruct.HASCART = functionHasCart();

return returnStruct;
</cfscript>
</cffunction>

And on the Flex side of it:



private const SECOND:uint = 1000;
private var delay:uint = 5 * SECOND; // five second interval
private var repeat:uint = 0; // continuous
private var myTimer:Timer;

private function tick(e:TimerEvent):void {
roSession.keepAlive();
}

private function addTimer(delay:uint,repeat:uint):void {
myTimer = new Timer(delay, repeat);
myTimer.addEventListener(TimerEvent.TIMER,tick);                        
}        
private function startTimer():void {
myTimer.start();
}
private function removeTimer():void {
myTimer.stop();
myTimer.removeEventListener(TimerEvent.TIMER,tick);
myTimer = null;
}


private var keepAliveNullCount:uint = 0;
private const INTERRUPTION_THRESHOLD:uint = 10;
private function doKeepAlive(e:ResultEvent):void {
if (e.result != null) {
keepAliveNullCount = 0;
if (e.result.LOGGEDIN == "false") {
removeTimer();
killCheckoutSession("session");
}    
else if (e.result.HASCART == "0") {
removeTimer();
killCheckoutSession("cart");
}
}
else {
keepAliveNullCount++;
if (keepAliveNullCount >
INTERRUPTION_THRESHOLD) {
// minor interruption is big enough to kill the session
removeTimer();
killCheckoutSession("connection");
}
}
}
        
        
private function killCheckoutSession(reason:String=""):void {
var killString:String = "";
switch (reason) {
case "session":
killString = "Your session has ended because you are no longer logged into the web site.";
break;
case "cart":
killString = "Your session has ended because your cart is empty.";
break;
case "connection":
killString = "Your session has ended because we have lost contact with the server.";
break;
default:
killString = "Your session has ended for unknown reasons.";
break;                
}

Alert.show(killString,"Session Terminated",Alert.OK,null,goAway);
}
        
private function goAway(eventObj:CloseEvent):void {
var request:URLRequest = new URLRequest("/");
navigateToURL(request,"_self");
}

Obviously you need to make sure to setup your RemoteObject, as well as include the appropriate Flex libraries.

The upside to all of this is that the Flex is now aware of the Coldfusion session and can react to changes.

[Addendum-de-dum-dum 11-26-2008] It occurred to me that I really ought to add that I don't let the Flex have any real authority over the Coldfusion session. Like all my front-ends, I really never trust it to be secure (check out Ted Patrick's really useful flash & flex blog for a good presentation on encrypting flex for reasons why I am rethinking this). Mostly I prefer to let the Flex act as a broker for the server side logic as that allows me to skip maintaining two sets of calculation implementations. However, if I must do calculations in the Flex, and this information is needed on the server, I will recalculate on the backside. The moral of the story addendum is that I don't trust code running on the client, at least when it comes to consequential figuring.

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
BlogCFC was created by Raymond Camden. This blog is running version 5.9.1.001. Contact Blog Owner