<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Ad hoc Geek &#187; widgets</title>
	<atom:link href="http://www.adhocgeek.com/tag/widgets/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.adhocgeek.com</link>
	<description>Approaching geekery in an ad hoc and improvisational manner.</description>
	<lastBuildDate>Fri, 30 Sep 2011 09:43:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Flex widget communication PoC</title>
		<link>http://www.adhocgeek.com/2009/05/widget-comms-poc/</link>
		<comments>http://www.adhocgeek.com/2009/05/widget-comms-poc/#comments</comments>
		<pubDate>Fri, 29 May 2009 15:11:26 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Geek]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[messaging]]></category>
		<category><![CDATA[widgets]]></category>

		<guid isPermaLink="false">http://www.adhocgeek.com/?p=14</guid>
		<description><![CDATA[Problem : How do you get several distinct Flex widgets on a page to communicate? By distinct here I mean that each widget is a separate embedded SWF file, i.e. they don&#8217;t share the same Application. There are actually several ways to do this, and an appropriate choice really depends on the kind of data [...]]]></description>
			<content:encoded><![CDATA[<p>Problem : How do you get several distinct <a href="http://www.adobe.com/products/flex/">Flex</a> widgets on a page to communicate?</p>
<p>By distinct here I mean that each widget is a separate embedded SWF file, i.e. they don&#8217;t share the same Application.</p>
<p>There are actually several ways to do this, and an appropriate choice really depends on the kind of data you want to share and when. What I needed was real-time communication; say I have one widget that searches for a particular resource (in my case they&#8217;re bonds), when the user selects a resource, that widget should propagate the selection to all the others on the page. It was also a requirement that the number and identity of the widgets on the page be an unknown &#8211; i.e. I can&#8217;t assume that there will always be exactly three widgets called Fred, Bob and Jane.</p>
<p>Not being a Flex expert, my first thought was to use a <a href="http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/net/SharedObject.html">SharedObject</a>. This seemed like a good idea since apparently they &#8220;offer real-time data sharing between multiple client SWF files&#8221;, which is exactly what I want. However, this is only possible if you&#8217;re using Flash Media Server. I don&#8217;t really need that round-trip to the server each time and I don&#8217;t need to communicate between multiple clients, just among SWF files on the same page at a single client. I also don&#8217;t have Flash Media Server. I did toy around briefly with a polling solution using local SharedObjects though. The server SWF would contain something like this :</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> syncSharedObject<span style="color: #66cc66;">&#40;</span>sharedText:<span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">var</span> so:<span style="color: #0066CC;">SharedObject</span> = <span style="color: #0066CC;">SharedObject</span>.<span style="color: #0066CC;">getLocal</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;test&quot;</span>, <span style="color: #ff0000;">&quot;/&quot;</span>, <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">&#41;</span>;
    so.<span style="color: #0066CC;">data</span>.<span style="color: #006600;">sharedText</span>= sharedText;
    so.<span style="color: #0066CC;">flush</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>And the client SWF would contain code to poll the SharedObject periodically to check for updates (I&#8217;m not going to show the boilerplate code that sets up the Timer instance):</p>

<div class="wp_syntax"><div class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> syncSharedText<span style="color: #66cc66;">&#40;</span>event:TimerEvent<span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">var</span> so:<span style="color: #0066CC;">SharedObject</span> = <span style="color: #0066CC;">SharedObject</span>.<span style="color: #0066CC;">getLocal</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;test&quot;</span>, <span style="color: #ff0000;">&quot;/&quot;</span>, <span style="color: #000000; font-weight: bold;">false</span><span style="color: #66cc66;">&#41;</span>;
    sharedText = so.<span style="color: #0066CC;">data</span>.<span style="color: #006600;">sharedText</span>;
<span style="color: #66cc66;">&#125;</span></pre></div></div>

<p>Simple! But also fairly braindead. This is a pull architecture &#8211; the clients aren&#8217;t notified when the data has changed, so they have to keep looking at it (say every half second), which creates some annoying overhead &#8211; each widget interested in &#8220;sharedText&#8221; would have to poll the SharedObject and that could be a lot of widgets looking at one piece of data. Of course, this gets worse if we need to pass around lots of different pieces of data!</p>
<p>So, back to the drawing board and a little more reading, after which I discovered <a href="http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/net/LocalConnection.html">LocalConnection</a>. This seems to do pretty much everything I need, but it&#8217;s definitely more complex to get up and running with. What I want is one widget to act as a server and notify all the other widgets about changes to relevant data, however I can&#8217;t designate a specific widget as the server because I don&#8217;t know if it will always be present. A simple solution would be to let the first widget to load grab the publisher/server functionality and all subsequently loaded widgets would then be subscribers/clients (I decided to call the class MessageManager, and, since it will need to raise events, it extends EventDispatcher) :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
</pre></td><td class="code"><pre class="actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">//constructor (I'm not going to write out all the class definition code)</span>
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> MessageManager<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">target</span>:IEventDispatcher=<span style="color: #000000; font-weight: bold;">null</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #808080; font-style: italic;">//Generate a locally unique ID.</span>
    <span style="color: #0066CC;">this</span>.<span style="color: #006600;">subscriberID</span>= UIDUtil.<span style="color: #006600;">createUID</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #0066CC;">try</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #808080; font-style: italic;">//First we try to connect as the server.</span>
        conn = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0066CC;">LocalConnection</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
        conn.<span style="color: #0066CC;">connect</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Server&quot;</span><span style="color: #66cc66;">&#41;</span>;
        conn.<span style="color: #006600;">client</span> = <span style="color: #0066CC;">this</span>;
        isServer = <span style="color: #000000; font-weight: bold;">true</span>;
&nbsp;
        <span style="color: #808080; font-style: italic;">//initialise the subscriber cache.</span>
        subscribers = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0066CC;">Object</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
    <span style="color: #0066CC;">catch</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">e</span>:<span style="color: #0066CC;">Error</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #808080; font-style: italic;">//The server probably already exists; register ourselves with it.</span>
        isServer = <span style="color: #000000; font-weight: bold;">false</span>;
        conn = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0066CC;">LocalConnection</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
        conn.<span style="color: #0066CC;">connect</span><span style="color: #66cc66;">&#40;</span>subscriberID<span style="color: #66cc66;">&#41;</span>;
        conn.<span style="color: #006600;">client</span> = <span style="color: #0066CC;">this</span>;
        conn.<span style="color: #0066CC;">send</span><span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;Server&quot;</span>, <span style="color: #ff0000;">&quot;registerSubscriber&quot;</span>, <span style="color: #0066CC;">this</span>.<span style="color: #006600;">subscriberID</span><span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
    <span style="color: #0066CC;">super</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">target</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;
<span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> registerSubscriber<span style="color: #66cc66;">&#40;</span>subscriberID:<span style="color: #0066CC;">String</span><span style="color: #66cc66;">&#41;</span>:<span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">!</span>subscribers<span style="color: #66cc66;">&#91;</span>subscriberID<span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#41;</span>
         subscribers<span style="color: #66cc66;">&#91;</span>subscriberID<span style="color: #66cc66;">&#93;</span> = <span style="color: #000000; font-weight: bold;">true</span>;
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>There are a fair few assumptions in this code (there&#8217;s no real error handling, for a start), but it works well enough for a PoC. It may seem a little confusing to use the same class for both publisher and subscriber interfaces, and it would be entirely feasible to separate them out, but I didn&#8217;t consider that necessary for such a small scale test.</p>
<p>With the publisher and subscribers loaded and registered, I now need to be able to send a message. I created a MessageManagerEvent class which extends Event with an additional data property, this contains the &#8220;message&#8221; to be passed around (a fairly common pattern &#8211; the <a href="http://www.adobe.com/devnet/flex/samples/flex_store/">Flex store</a> sample application uses something similar but calls it ObjectDataEvent). For a widget to then update all other widgets, it just needs to create a MessageManagerEvent and call the MessageManager.sendMessage method. sendMessage determines whether the current instance of MessageManager is the server or a subscriber and either sends a single message to notify the server or iterates over the subscribers collection notifying each one in turn. I created a simple application to demonstrate this in action and included two of them below (you should be able to view source on either) :</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="MessageManagerTest01" width="200" height="75" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/flash/MessageManagerTest/MessageManagerTest.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#869ca7" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/flash/MessageManagerTest/MessageManagerTest.swf" quality="high" bgcolor="#869ca7" width="200" height="75" name="MessageManagerTest01" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<p>Just enter some text into either box and you should see it copied across to the other application.</p>
<p><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="MessageManagerTest02" width="200" height="75" codebase="http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab"><param name="movie" value="/flash/MessageManagerTest/MessageManagerTest.swf" /><param name="quality" value="high" /><param name="bgcolor" value="#869ca7" /><param name="allowScriptAccess" value="sameDomain" /><embed src="/flash/MessageManagerTest/MessageManagerTest.swf" quality="high" bgcolor="#869ca7" width="200" height="75" name="MessageManagerTest02" align="middle" play="true" loop="false" quality="high" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.adobe.com/go/getflashplayer"></embed></object></p>
<p>If you refresh the page a few times, you may notice the &#8220;SERVER&#8221; and &#8220;SUBSCRIBER&#8221; labels flip back and forth between the widgets, depending on which one loads first. If you open a new copy of this entire page, the new instances should both be saying &#8220;SUBSCRIBER&#8221; (assuming you keep this page open). Even more interesting is that if you open a copy of this page in <em>another browser entirely</em>, you may find that those say &#8220;SUBSCRIBER&#8221; as well, and that text is propagated to them from the original browser instance! (I&#8217;ve noticed this works between FireFox and IE so far, YMMV, of course).</p>
<p>A few points to note :</p>
<ul>
<li>You can use more complex objects as messages, but each widget must have a reference to that type compiled in, otherwise it won&#8217;t deserialise correctly.</li>
<li>Any type used as a message must have a default constructor, or at least a constructor with default parameters.</li>
<li>This is far from being a usable implementation, since it doesn&#8217;t account for the possibility of the server or any subscriber dying. Ideally there would be a mechanism for a subscriber to take over the server role if the server is removed, though this would probably require use of a SharedObject to persist the subscriber list.</li>
</ul>
<p><b>Update</b></p>
<p>What I&#8217;ve done here was for my benefit really &#8211; a learning exercise. What Blitz Agency has done <a href="http://labs.blitzagency.com/?p=650">here</a> is something on another level altogether. Under the hood it&#8217;s all still LocalConnection based though.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.adhocgeek.com/2009/05/widget-comms-poc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

