Delivering Event Driven Notifications to Users with AJAX

Have you ever wanted to notify a group of users that an event has taken place using a cfwindow or some other type of alert? Well here's a way!

First off, let me state that I know that there are other ways of doing this - especially if you're working with Flex. If you're looking for a pure JavaScript solution then this will work. The concept is that we've got a database driven CF application and we want to notify specific users when an event has occurred. There are a few pieces to making this work.
-A database table or log file that we can query to determine whether or not anything new has happened (AppEventLog table).
-A simple cfc containing a function to handle the aforementioned query (applisten.cfc).
-Client side AJAX code to handle the checking and if necessary, notify the user (eventloop.cfm).
-A cfwindow page that is shown when an event has occurred (eventnotifer.cfm).

Here's the cfc code (applisten.cfc) that we'll be calling from the eventloop.cfm page...

view plain print about
1<cfcomponent>
2    <cffunction name="readEventLog" access="remote" returntype="boolean">
3        <cfquery name="qryAppEventLog" datasource="#REQUEST.ds1#">
4            SELECT        AppEventLogID
5            FROM            AppEventLog
6        </cfquery>
7        <cfset eventFired = (qryAppEventLog.recordCount GT 0)>
8        <cfreturn eventFired>
9    </cffunction>    
10</cfcomponent>

Next, we need to fire up our cfc to start checking the database's log table for new events (eventloop.cfm)...

view plain print about
1<cfajaximport tags="cfwindow">
2<cfajaxproxy cfc="#REQUEST.cfcDir#.applisten" jsclassname="proxyAppListen">
3
4<html xmlns="http://www.w3.org/1999/xhtml">
5<head>
6<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7<title>Untitled Document</title>
8
9<script type="text/javascript">        
10
11    checkAlertsErrorHandler = function(code,msg) {
12        alert('Error ' + code + ': ' + msg);
13    }
14        
15    setAlertInterval = function(){
16        alertInterval = setInterval('checkAlerts()', 10000);
17    }
18    
19    clearAlertInterval = function(){
20        clearInterval(alertInterval);
21    }
22
23    checkAlerts = function(){
24        proxyReadEventLog.readEventLog();
25        console.log('checkAlerts was called...');        
26    }
27    
28    checkAlertsCallback = function(newEvents){
29        if (newEvents && eventWinClosed){
30            day = new Date();
31            eventWinID = 'event' + day.getTime();
32    
33            eventWinClosed = false;
34            ColdFusion.Window.create(eventWinID,'Event Notification','eventnotifier.cfm?formName=' + eventWinID, windowOptions);
35            ColdFusion.Window.onHide(eventWinID, killEventWin);
36        }
37    }
38
39    closeEventWin = function(){
40        ColdFusion.Window.onHide(eventWinID, killEventWin);
41        ColdFusion.Window.hide(eventWinID);
42    }
43    
44    killEventWin = function(){
45        ColdFusion.Window.destroy(eventWinID, true);
46        eventWinClosed = true;
47    }
48
49    initHandler = function(){
50        windowOptions = new Object();
51        windowOptions.width = 200;
52        windowOptions.height = 100;
53        windowOptions.x = 50;
54        windowOptions.y = 50;
55        windowOptions.modal = false;
56        windowOptions.resizeable = false;
57        windowOptions.initshow = true;
58        windowOptions.draggable = true;
59        windowOptions.closable = true;
60        windowOptions.headerstyle = 'font-family: verdana; background-color: #0066FF;';
61    
62        eventWinClosed = true;
63        proxyReadEventLog = new proxyAppListen();        
64        proxyReadEventLog.setErrorHandler(checkAlertsErrorHandler);
65        proxyReadEventLog.setCallbackHandler(checkAlertsCallback);
66        proxyReadEventLog.readEventLog();
67        setAlertInterval();
68    }
69
70</script>
71
72</head>
73
74<body>
75    <h1>Event Loop Test 1 - cfwindow notifier...</h1>
76    <cfset AjaxOnLoad("initHandler")>
77</body>
78</html>

And finally, if the checkAlertsCallback function receives a true from our cfc then we show our cfwindow to let the user know that an event has occurred in the system...

view plain print about
1New Events have occurred...
2
3<a href="javascript:closeEventWin()">Close</a>

I'll obviously be going much deeper with this in a real world implementation but you get the general idea. I'm planning on targeting specific groups of users so as to show events that are context aware of who is logged in.

A quick note on performance: The last time I tested this prototype app I was using Firefox 3.something and I let it run for over an hour and it never consumed more than 60MB of memory!

Comments
Robert Rawlins's Gravatar Cool post, we use a very simlar method here with http://labs.d-xp.com/growl/ type notices to keep our users informed of what's going on, I love even driven programming for things like this.

I'm currently writing a blog article on different UI effects we use here to keep customers informed of what's going on.

Thanks for sharing!

Rob
# Posted By Robert Rawlins | 9/11/09 1:36 PM
Andy Sandefer's Gravatar @Robert
I just checked out your demo and I find your effects to be pretty cool - hello from across the pond!
# Posted By Andy Sandefer | 9/11/09 1:43 PM
Robert Rawlins's Gravatar greetings from england!

I'm sorry about my last comment, I think the way I phrased it was a little misleading now that I read it again. The effects in that link are not mine, they are someone else's, we simply use that plugin here within our application :-)

Rob
# Posted By Robert Rawlins | 9/11/09 1:47 PM
Henry Ho's Gravatar I wonder if you can use BlazeDS Ajax client library: http://livedocs.adobe.com/blazeds/1/blazeds_devgui...

Anyone tried?
# Posted By Henry Ho | 9/11/09 2:57 PM
Chris's Gravatar is there a demo of your code?

I'm in the camp of "not using built in AJAX CF controls" only because I feel that you're limiting yourself from code portability.

Assuming your code base moves from CF to soemthing else (god willing), your AJAX code needs to be rewritten in that future language.

I'm all about jQuery and ajax. It's platform independent (and way more flexible than what's bundled with CF).

Oh you can check out some of my AJAX stuff using CF/jQuery/jQueryUI on my site.

Just my 2 cents :)
# Posted By Chris | 9/11/09 4:03 PM
Andy Sandefer's Gravatar @Chris
This example calls for cfwindow and cfajaxproxy and it is intended to be used in a ColdFusion Server environment. Most all of the code that I write runs on ColdFusion Server as that is what I deploy for my clients. I'm in the camp that believes that if a prospect is unwilling to make a 1200 dollar investment in their IT infrastructure then they probably can't afford custom software development. You may be right about me "limiting" myself, but I don't think it has anything to do with code portability. I'm limiting myself from having to install and keep up with a pile of plug-ins and maintain a bunch of libraries - Adobe has done that for me and all of my ColdFusion clients and we will gladly continue to pay Adobe for what I believe is a well maintained application server and frankly the best rapid application development platform on the market.

I would agree with you that there are definitely a lot of great things that can be done with jQuery as well as many other AJAX frameworks but in this particular example I'm using ColdFusion 8 Standard with SQL Server 2005 on the back end.

I'm not against jQuery, but I'm definitely for picking the right tool for the job which in many cases means factoring in how many lines of code are required to create this solution and how hard it would be for another developer to manage the code if I were to be hit by a bus. I will get around to publishing various examples in jQuery at some point but for now you're probably not going to see a ton of $ signs in my code.

Thanks for reading and commenting and keep in touch.
# Posted By Andy Sandefer | 9/11/09 4:48 PM
Andy Sandefer's Gravatar @Henry
If you read the docs it states that Flash is required which wouldn't work for me as I was going for a pure AJAX solution in this situation. But thanks for the idea!

Requirements for using the Ajax client library
To use the Ajax client library, you must have the following:
* The Ajax client library, which is included in the following directory of the BlazeDS installation:
installation_dir\resources\fds-ajax-bridge
* A supported Java application server or servlet container
* Adobe Flex Software Development Kit (SDK) included with BlazeDS
* Adobe Flash Player 9
* Microsoft Internet Explorer, Mozilla Firefox, or Opera with JavaScript enabled
# Posted By Andy Sandefer | 9/11/09 4:55 PM
# Posted By ed hardy clothing | 5/21/10 3:45 AM
new era red bull hats's Gravatar We wholesale hats at competitive price,providing a huge range of hats with different brand name,such as coogi hats, polo hats,Jordan hats,famous hats,dc shoes hats,new era MLB hats, etc.You can buy cheap hats. Welcome to visist here. <a href="http://www.goahats.com/red-bull-hats-c-4.html">new era red bull hats</a> ?http://www.goahats.com/red-bull-hats-c-4.htm
# Posted By new era red bull hats | 6/20/10 8:43 AM
Wholesale NFL Jerseys's Gravatar Thanks for posting this. <a href="http://www.sportsjerseysshop.com">wholesal... nfl jerseys</a>
<a href="http://www.sportsjerseysshop.com">discount... nfl jerseys</a>
Very nice recap of some of the key points in my talk. I hope you and your readers find it useful! Thanks again
# Posted By Wholesale NFL Jerseys | 7/15/10 11:59 PM
cheap nfl jerseys's Gravatar Hey guys,
I hope this allowed, I have never used this website before so I wasn't really sure what this was going to do. <a href="http://www.nfljerseyse.com"; title="wholesale nfl jerseys">wholesale nfl jerseys</a> So this is just a test post. I really like this forum, it has some excellent discussions that take place.
# Posted By cheap nfl jerseys | 7/28/10 10:13 PM
ciphone's Gravatar Hello!everyone!iphone is so expensive.so I like <a href=" www.efox-shop.com/index.php/cPath/5_35
" rel="nofollow"> Ciphone </a>. d^_^bIt is very interesting.I want to introduce <a href="http://www.efox-shop.com/"; rel="nofollow"> efox-shop</a> to you.
# Posted By ciphone | 7/30/10 11:20 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.9.5.007. Contact Blog Owner