RIA Prototype Client Using BlazeDS Messaging and JMS - Flex Client
In a previous posting I gave an overview of the dashboard client that I created to investigate BlazeDS messaging with Flex clients. This posting focuses specifically on the Flex client.
One of the purposes of an application dashboard is to provide the user a means of rapidly discerning the state of an application using data visualization. I couldn’t think of a better use of Flex and than visualizing data! I am partial to real-time strip chart plots since you can monitor the history of operational parameters over a period of time. I am also partial to bar type meter that show the current value of a parameter and maybe even a high water mark. I envisioned a final dashboard application with many such strip charts and bar meters. The first objective of the prototype was to scope out an efficient way of displaying data for one set of metrics.
Charting Components
I wanted to try out some of the stock Flex charting components since I had never had the opportunity to work with them before. The LineChart component looked like a perfect component to use to draw my data in real time. Unfortunately, the LineChart does not allow you to present data in the same way that say the Windows performance monitor does as shown below.
You basically have the choice of moving the whole chart as the performance monitor does or moving the data plot as you can with the bar chart component. Once I got over my preconceived notions of how a strip chart should work I found the LineChart to be perfectly adequate. The following show the LineChart component in the dashboard demo.
Although the stock LineChart component appears adequate for my purposes, I’m still a bit tempted to try to construct a strip chart component. After checking out the Degrafa web site, it looks like degrafa may be a good tool set to use in constructing a moving strip chart. I suppose I can also make my LineChart appear a bit more polished through CSS. Unfortunately, making UIs look pretty has not been in my job description up until this point so I have a bit to learn.
Efficiency memory management
One concern that I had with the LineChart was how can you effectively change the underlying data structure without causing the invalidation of a large number of objects each time a new data point is received (and hence sloppy memory management). After pondering this issue, and after a post or two on the flexcoders newsgroup, I discovered the virtues of the IViewCursor interface which is implemented by the ArrayCollection class. This interface provides methods similar to the file pointer used in random access file I/O APIs. You can seek anywhere within your data structure and then perform operations like insert or remove. This was exactly the behavior I was looking for: a way of deleting the oldest data point on one end of the data structure and adding the latest data point to at the other end of the data structure. The following code snippet shows how this operation was implemented in code.
// Update chart data provider, remove the oldest and add // the newest datapoint if we are at the max array size. Otherwise, // add to the collection if(metrics.source.length > ARRAY_SIZE ){ cursor.seek(CursorBookmark.LAST); cursor.remove(); cursor.seek(CursorBookmark.FIRST,1); cursor.insert(data); } else { metrics.addItem(data); }
I used the Flex Builder profiler to monitor object creation during a long run of the client application and saw a very minimal effect in the Flash player memory footprint due to this technique. I hereby declare victory and move on!
Value Object
The next thing to consider is how to move data from the back-end to the front-end. The classic design pattern here is to use a value object to encapsulate your data. I use value objects so much that they are like breathing to me. The following listing shows the simple value object that contains three dummy metric values and the associated timestamp.
package info.jimboone { [Bindable] [RemoteClass(alias='info.jimboone.MetricsVO')] /** * Simple object to encapsulate metric values * * @author Jim Boone * */ public class MetricsVO { public var timestamp:Date = new Date(); public var instantValue:int = 0; public var metric1:int = 0; public var metric2:int = 0; public var metric3:int = 0; public function toString():String{ return timestamp + " Metric1: " + metric1 + " metric2: " + metric2 + " metric3: " + metric3; } } }
Channel Configuration
I must admit that I am not completely happy with the way that endpoint configurations are handled between the Flex client and the server, especially with a J2EE application server but I will save this as the topic for another posting.
For simplicity, I effectively hard-coded the destination endpoints to localhost since this is where my server running. The following code snippet shows how the endpoints and channels were configured all within ActionScript on the client. Of course this configuration needs to line up with entries on the server side configuration in server-config.xml in order for the front-end to talk to the back-end.
private var pollingChannel:AMFChannel; private var longPollingChannel:AMFChannel; private static const BASE_URL:String = "http://localhost:8080/DashboardServer/messagebroker"; private static const AMF_ENDPOINT:String = BASE_URL + "/amf"; private static const POLLING_ENDPOINT:String = BASE_URL + "/amfpolling"; private static const LONG_POLLING_ENDPOINT:String = BASE_URL + "/amflongpolling";; private function initChannels():void{ this.pollingChannel = new AMFChannel("polling-channel", POLLING_ENDPOINT); this.longPollingChannel = new AMFChannel("long-polling-channel",LONG_POLLING_ENDPOINT); var pollingFreq:Number = pollingFreqCbo.text as Number; pollingChannel.pollingEnabled = true; pollingChannel.pollingInterval = pollingFreq; longPollingChannel.pollingEnabled = true; longPollingChannel.pollingInterval = pollingFreq; this.pollingChannelSet = new ChannelSet(); this.longPollingChannelSet = new ChannelSet(); this.pollingChannelSet.addChannel(this.pollingChannel); this.longPollingChannelSet.addChannel(this.longPollingChannel); remotingService = new RemoteObject(); remotingService.destination="DataGenerator"; remotingService.addEventListener(MessageAckEvent.ACKNOWLEDGE, onMessageAcknowledge); remotingService.addEventListener(FaultEvent.FAULT, onRemotingFaultHandler); remotingService.channelSet = this.pollingChannelSet; msgConsumer = new Consumer(); msgConsumer.addEventListener(MessageEvent.MESSAGE, onMessageHandler); msgConsumer.addEventListener(MessageAckEvent.ACKNOWLEDGE,onMessageAcknowledge); msgConsumer.addEventListener(MessageFaultEvent.FAULT, onMessageFaultHandler); }
Dashboard Flex Client Source Code
There really isn’t anything earth shattering or terribly unique in a Flex dashboard client. The more interesting observations will occur when I start putting the dashboard through its paces to investigate how BlazeDS performs. The complete source code for the Flex client can be viewed and downloaded here.
No comments yet. Be the first.
Leave a reply

