« Programmatic Skinning with Flex 2 | Main | Exploring Flex Enterprise Services 2 »
February 16, 2006
Simple Flex 2 Messaging Example
As a Sr. Product Specialist for Flex, I spend the majority of my time either building out custom demonstrations, or presenting the technical aspects of Flex as various levels. You might have seen me present during the Flex online seminars as an example. That's a presentation fits into an hour and attempts to address the diversity of the crowd that often participates. As part of that demonstration I generally develop a simple application that consists of a DataGrid, a Button and a WebService. This is great for showing layout management, events, RPC calls and data binding. What it doesn't show however is any of the Flex Enterprise Services 2 goodness.
My challenge was how to show an "enterprise" feature like real-time messaging in the span of an hour, and cover the slide deck, the sample applications, and give enough time to code for it to make sense? As it turns out the new messaging features of Flex 2 are just that easy to use. For reference, a screen capture of the fully built demonstration application is below. The concept is simply to click on the Button, capture the click event, invoke the WebService and have the results fill the DataGrid via data binding.

I figured that an easy addition would be to put all the clients running the application on the same selected DataGrid row index. That is that if I was running the application in Browser A, and I selected a row in the DataGrid, that the DataGrid in Browser B (C, D, and whoever else) would highlight the same row of data. Granted the message that gets passed is simply an integer value, but often in collaborative applications the data we want to pass at any given point in time is fairly limited in complexity. And of course if you want more complexity, there's always the data services feature. The first step was to create a destination for the messages, which is done in the Flex XML configuration files, and looks as follows.
<destination id="demo">
<properties>
<network>
<subscriber-timeout>0</subscriber-timeout>
</network>
<server>
<max-cache-size>1000</max-cache-size>
<message-time-to-live>0</message-time-to-live>
<durable>false</durable>
</server>
</properties>
<channels>
<channel ref="my-rtmp"/>
</channels>
</destination>
With the message defined, it was time to establish a Producer and Consumer in the application. In this case, the application would do both - produce a message saying which row was currently highlighted, and consume those messages announcing what rows were highlight from other connected clients. This is literally two lines of additional code - entirely too easy. In this example I wasn't worried about acknowledging that I sent a message, only in handling an event that a new message had arrived. For this I handled the "message" event on the Consumer, where I pulled the index out of the message body and then set the "selectedIndex" property on the local DataGrid. All of that looks like this:
// In script block
// Notice the use of the new casting "as"
public function doMessage( event:MessageEvent ):void {
grdCatalog.selectedIndex = event.message.body as Number;
}
...
<!-- In MXML -->
<mx:Producer id="producer" destination="demo" />
<mx:Consumer id="consumer" destination="demo" message="doMessage( event )" />
Now that I could get messages that the selected index ... somewhere ... on some connected client ... could change, it was time to trigger the event that would announce that change. The DataGrid has a "change" event, which I use as a trigger to fire off the new message. Assembling this simple of a message involves declaring a message object, and setting some value (a Number representing the selectedIndex in this case) on the message body. With that complete, we send our message into the ether by calling the Producer's "send" method passing it the message as an argument. My event change event handler then looks something like the following snippet.
public function doSelection( event:Event ):void {
var mess:AsyncMessage = new AsyncMessage();
mess.body = grdCatalog.selectedIndex;
producer.send( mess );
}
At first I thought I was done, and I set out to run my application. Much to my dismay, when I did so, the events weren't getting transmitted. Blast it! What seems to be the problem here, miss? A little reading of the documentation informed me that instantiating the Consumer alone, wasn't good enough. Apparently I also needed to tell it to subscribe itself as a listener. This makes sense and is mirror to the behavior of the RPC classes. For example, you can declare a WebService class and even bind to the results, but you need to tell the WebService to actually do something somewhere along the line. On a WebService this is invoking one of the operations, and on the Consumer, it's calling the "subscribe" method.
I wanted to be connected as soon as the application started, so I created a "creationComplete" event handler and put the Consumer.subscribe() method in there. I figured that I might as well also move the invocation of the WebService that populates the DataGrid in there as well. This way there will be data available to select once the application starts.
public function doCreationComplete( event:Event ):void {
consumer.subscribe();
svcCatalog.send();
}
That's all there was too it! Even with my verbose style of coding (I just can't seem to shake the 80 column thing from COBOL), it took all of 40 lines of code. That includes loading a web service into a DataGrid and real-time collaboration across connected clients. Of course I get all the yummy goodness of the Flex Framework 2 as well, such as resizing and reordering DataGrid columns too. Wow! Certainly there must be more to it than this!? Whatever shall I tell my boss that I was doing for the half-day I was out skiing? Oh, well. (smile)
It was a fun little example for me to build, and the source is available as well. I did make one change for portability in that I swapped out the WebService for an HTTPService to an XML file. Other than that all the details remain the same. Enjoy!
Posted by khoyt at February 16, 2006 03:17 PM
Comments
I'd love to see more (hi res) video tutorials. there's so much to learn and to understand regarding Flex2 and AS3.
cheers,
w.
Posted by: Wax at February 17, 2006 11:49 PM
More FES examples will be great
e.g. basic ones like showing how to do a chat app which shows all the currently logged in users when u first log on to the app etc.
cheers
Posted by: pk_wasp at February 18, 2006 11:13 AM
Hi,
i was trying the above example
Error MSG: Server root is invalid. Could not locate flex-config.xml.
Pls help me out.
Posted by: srinath at February 28, 2006 05:36 AM
How can i get the value of a cell of the Grid without knowing the column name? I want to get for example, the cell in 2nd row 3rd column.
Posted by: MrD at October 5, 2006 03:08 PM