<?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>Reignite</title>
	<atom:link href="http://www.reignite.com.au/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.reignite.com.au</link>
	<description>Potential Delivered</description>
	<lastBuildDate>Fri, 08 Feb 2013 02:41:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>AMFR.js Example</title>
		<link>http://www.reignite.com.au/amfr-js-example/</link>
		<comments>http://www.reignite.com.au/amfr-js-example/#comments</comments>
		<pubDate>Fri, 08 Feb 2013 02:41:02 +0000</pubDate>
		<dc:creator>surrey</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.reignite.com.au/?p=1052</guid>
		<description><![CDATA[AMFR.js AMF.js is the javascript client for R-AMF server.  It uses a custom version of AMF, version 99.  The custom version was created in an effort to reduce the number of bytes sent over the wire.  On a per client &#8230; <a href="http://www.reignite.com.au/amfr-js-example/" class="link-more">more</a>]]></description>
			<content:encoded><![CDATA[<h1>AMFR.js</h1>
<p>AMF.js is the javascript client for R-AMF server.  It uses a custom version of AMF, version 99.  The custom version was created in an effort to reduce the number of bytes sent over the wire.  On a per client basis the reduction is not great but considering our customers at Reignite are expecting to have in some cases many thousands of clients making calls to the server and our customers pay for bandwidth usage every byte counts.</p>
<p>So here is the basic usage:</p>
<pre><code>&lt;script type="text/javascript" src="<a href="http://occ.reignite.com.au/AMFR.js" target="_blank">AMFR.js</a>"&gt;&lt;/script&gt;
var con = new AMFR();
con.endpoint = "http://www.example.com/amfr";
var msg = con.createMessage("securityService", "authenticate",["siteAdmin","password"]);
con.call(msg, function(data){alert("on result")},function(data){alert("on status")});
</code></pre>
<p>You import AMFR.js and that is all.  Then when you want to use it you create a new AMFR(), set the endpoint, use it to create a message and then send the message.</p>
<p>You can reuse the same AMFR over and over.  Just create new messages and send them.</p>
<p>Create message takes the following:<br />
destination, operation, [params]<br />
The destination is the name of the service specified in your server side configuration.  It is the same as the destination name used in Flex RemoteObjects.  The operation is the method to call on that service, just like the operation in Flex RemoteObjects.  The params are an array of javascript objects.  So if you want a date to appear as a date in Java you need to pass a javascript Date object not a string representation.  If you want an object to deserialize as a correctly typed object in Java you need to add a special field to your Javascript object.  EG:<br />
{&#8220;AMFR_class&#8221;:&#8221;com.example.security.User&#8221;,<br />
&#8220;id&#8221;:4,<br />
&#8220;username&#8221;:&#8221;frank&#8221;, etc&#8230; }<br />
The server would attempt to instantiate an object of type com.example.security.User and set its fields with id, username and whatever else you sent through.</p>
<p>The inverse of this is true too.  When a server method returns a Java object to the Javascript client it is a plain old Javascript object, or map or dictionary or whatever term you like, with the special AMF_class property attached.  So you could load a User from the back end, update some fields then store it back.</p>
<p>Dig into the AFMR.js code and see what it does for yourself.  It is not minimised or obfuscated in any way and I&#8217;ve tried to use plain english names for things.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reignite.com.au/amfr-js-example/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Configuring R-AMF For Use with AMFR.js and AMF3</title>
		<link>http://www.reignite.com.au/configuring-r-amf-for-use-with-amfr-js-and-amf3/</link>
		<comments>http://www.reignite.com.au/configuring-r-amf-for-use-with-amfr-js-and-amf3/#comments</comments>
		<pubDate>Fri, 08 Feb 2013 02:23:51 +0000</pubDate>
		<dc:creator>surrey</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.reignite.com.au/?p=1047</guid>
		<description><![CDATA[R-AMF R-AMF is the name I&#8217;ve given the no frills implementation of Adobe&#8217;s AMF server I wrote in an effort to improve efficiency and fix a few bugs that bothered me.  It stemmed from the requirement to move to HTML &#8230; <a href="http://www.reignite.com.au/configuring-r-amf-for-use-with-amfr-js-and-amf3/" class="link-more">more</a>]]></description>
			<content:encoded><![CDATA[<h1>R-AMF</h1>
<p>R-AMF is the name I&#8217;ve given the no frills implementation of Adobe&#8217;s AMF server I wrote in an effort to improve efficiency and fix a few bugs that bothered me.  It stemmed from the requirement to move to HTML 5 / Javascript while retaining backward compatibility with our old Flex based clients.  I&#8217;ll go into how to configure the server side an example of using the AMFR.js Javascript client for AMF99 or AMFR if you like.</p>
<h1>Overview</h1>
<p>AMF is a binary protocol for communicating over the web.  That means we need a client and a server side to encode and decode the messages.  The client can be either Flex, in which case AMF3 is usually used or it can be my Javascript client which uses AMF99.</p>
<p>The server side is written in Java.  Essentially it is a servlet that a client POSTs to.  The servlet reads the body data, which is encoded in AMF of version 0, 3 or 99.  The body, once decoded will contain a service call that is routed according to configuration to the appropriate endpoint.  The configuration of the server begin in the web.xml.  This specifies the servlet used and the type of configuration used for the routing and remoting systems.  R-AMF server does not support streaming or real time messaging, only synchronous service calls.  This is because I intend to use web sockets for real time messaging as they become available.</p>
<h1>Web.xml</h1>
<p>The first part is a filter.  The SEncodeFilter is required to convert a Java binary stream into a character stream that can be read by Javascript.  The filter operates based on an HTML header.  So if you are using AMFR.js as your client you would set the header to true but if you are using a Flex AMF3 client you would either not set the header or you would set it to false.  Flex can handle binary streams but Javascript using the XMLHttpObject can only handle character streams.  I used to use a Base64 encode filter but found it was less efficient that required.  SEncode is an encoding scheme I came up with that is more compact.</p>
<pre><code>
&lt;filter&gt;
    &lt;filter-name&gt;encodeFilter&lt;/filter-name&gt;
        &lt;filter-class&gt;com.reignite.messaging.server.SEncodeFilter&lt;/filter-class&gt;
    &lt;/filter&gt;
&lt;filter-mapping&gt;
    &lt;filter-name&gt;encodeFilter&lt;/filter-name&gt;
    &lt;url-pattern&gt;/amfr&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;</code></pre>
<p>The above would be added to your web.xml.  I&#8217;m assuming you are somewhat familiar with Java server configuration eg: Tomcat, Jetty, etc&#8230; so I won&#8217;t go into great detail about this.  But you can see there is a filter that intercepts everything going to /amf.  The filter looks for the header:<br />
s-enc<br />
If you set s-enc to &#8220;true&#8221; as in the string without the quotes.  Then the filter works its magic on the body of the request to convert it to and from a UTF-8 character stream.</p>
<p>The next bit is the servlet configuration.</p>
<pre><code>&lt;servlet&gt;
	&lt;servlet-name&gt;MessageBrokerServlet&lt;/servlet-name&gt;
	&lt;display-name&gt;MessageBrokerServlet&lt;/display-name&gt;
	&lt;servlet-class&gt;com.reignite.messaging.server.MessagingServlet&lt;/servlet-class&gt;
	&lt;init-param&gt;
		&lt;param-name&gt;initializer&lt;/param-name&gt;
		&lt;param-value&gt;com.reignite.messaging.server.SpringWebInitializer&lt;/param-value&gt;
	&lt;/init-param&gt;
        &lt;init-param&gt;
		&lt;param-name&gt;RAMFServerBeanName&lt;/param-name&gt;
		&lt;param-value&gt;ramfServer&lt;/param-value&gt;
	&lt;/init-param&gt;
	&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
	&lt;servlet-name&gt;MessageBrokerServlet&lt;/servlet-name&gt;
	&lt;url-pattern&gt;/amfr&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
</code></pre>
<p>So I called the servlet MessageBrokerServlet out of habit but the servlet class is MessagingServlet.  This is the base class that will listen on /amfr and process AMF messages.  You&#8217;ll note the servlet listens to the same url as the filter.  I personally extended the MessagingServlet to become the SecureMessagingServlet which allowed me to store some request data in a ThreadLocal for use in my application, but you don&#8217;t need to extend the servlet if you don&#8217;t want to.</p>
<p>The other important thing to note here is the init-param I pass in to the servlet.  This is the initializer and is what the servlet will use to set up the routing.  I&#8217;ve got it configured with a SpringWebInitializer but you could extend com.reignite.messaging.server.WebInitializer to get configuration details from somewhere else if you like or you could implement the Initializer interface and not use the web servlet context at all.  I only created the SpringWebInitializer because I use Spring. The other init-param is for the SpringWebInitializer so it can find the RAMFServer in your Spring applicationContext.xml. I don&#8217;t use annotations for dependency injection as they are an incorrect use of annotations and should not be used for that purpose.  I also do not use autowiring as that is an incorrect use of dependency injection and should not be used due to maintenance issues and project hand over issues.</p>
<p>Once your MessagingServlet has been configured to find your RAMFServer instance you&#8217;ve finished configuring the servlet.  Now you have to configure the server.  In the source code I put up on google code there is a basic context file.  You should look at that for clues as to what to do.</p>
<h1>Spring configuration</h1>
<pre><code>&lt;bean id="ramfServer"  class="com.reignite.messaging.server.RAMFServer"&gt;
	&lt;property name="endpointLocator" ref="endpointLocator" /&gt;
	&lt;property name="codecLocator" ref="codecLocator" /&gt;
	&lt;property name="errorVersion" value="99" /&gt;
&lt;/bean&gt;
 &lt;bean id="endpointLocator"class="com.reignite.messaging.server.WebEndpointLocator"&gt;
	&lt;property name="endpointMap"&gt;
		&lt;util:map&gt;
			&lt;entry key="/amfr" value-ref="endpoint" /&gt;
		&lt;/util:map&gt;
	&lt;/property&gt;
&lt;/bean&gt;
 &lt;bean id="codecLocator" class="com.reignite.codec.CodecLocatorImpl"&gt;
	&lt;property name="serializeWorkers"&gt;
		&lt;util:map&gt;
			&lt;entry key="99" value="com.reignite.codec.amf.AMFRSerializeWorker" /&gt;
		&lt;/util:map&gt;
	&lt;/property&gt;
	&lt;property name="deserializeWorkers"&gt;
		&lt;util:map&gt;
			&lt;entry key="99" value="com.reignite.codec.amf.AMFRDeserializeWorker" /&gt;
		&lt;/util:map&gt;
	&lt;/property&gt;
	&lt;property name="aliasRegistry"&gt;
		&lt;bean class="au.com.reignite.amfr.SelfRegisteringMessagingAliasRegistry"&gt;
		    &lt;property name="sessionFactory" ref="sessionFactory" /&gt;
		&lt;/bean&gt;
	&lt;/property&gt;
	&lt;property name="proxyRegistry"&gt;
		&lt;bean class="com.reignite.messaging.MessagingProxyRegistry"&gt;
			&lt;property name="typeEditor" ref="delegatingTypeEditor" /&gt;
		&lt;/bean&gt;
	&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="delegatingTypeEditor"class="com.reignite.messaging.proxy.DelegatingTypeEditor" /&gt;
&lt;bean id="endpoint"class="com.reignite.messaging.server.AMFEndpoint"&gt;
	&lt;constructor-arg ref="ramfServer" /&gt;
	&lt;property name="destinationMap"&gt;
		&lt;util:map&gt;
			&lt;entry key="securityService" value-ref="securityDestination" /&gt;
		&lt;/util:map&gt;
	&lt;/property&gt;
&lt;/bean&gt;
&lt;bean id="securityDestination"class="com.reignite.messaging.server.SpringInitializedDestination"&gt;
	&lt;property name="name" value="securityService" /&gt;
	&lt;property name="target" ref="securityService" /&gt;
	&lt;property name="typeEditor" ref="delegatingTypeEditor" /&gt;
&lt;/bean&gt;
</code></pre>
<p>You can see there is a RAMFserver at the top.  It has an endpoint locator, codec locator and an error version.  The endpoint locator is listed later on as is the codec locator.  The error version just says what version of AMF any errors are encoded to.  If you are using Flex clients to talk to the RAMFserver then set error version to 3 other wise to 99.</p>
<p>The endpoint locator maps a url to an endpoint.  An endpoint is a collection of services.  In this way you could use this server to collect together several different sets of services by mapping different endpoints.  In practice though you&#8217;ll probably only have one endpoint to locate.</p>
<p>The codec locator maps AMF versions to serialisers and deserialisers.  The above config only maps version 99, but if you look in the source code you&#8217;ll find AMF3SerializeWorker and deserialize worker too.  So you can support both Flex and js clients if you want.</p>
<p>The delegating type editor is the thing that converts types from the client to types in the server.  EG: Javascript doesn&#8217;t have ArrayList but Java does.  So Javascript sends an array and the TypeEditor sees you are trying to put an array where an ArrayList is wanted so it converts it.</p>
<p>The Endpoint is a map from destination name to Spring configured service.  As an example I have a securityDestination.</p>
<p>I encourage you to look through the code of all of these because there are all sorts of different configuration details you can use.  Also you should note that numbers that come through as undefined or NaN are converted to java null.</p>
<p>I hope this has helped.  You will still need to do some trial and error and look through the source code and read my comments in it.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reignite.com.au/configuring-r-amf-for-use-with-amfr-js-and-amf3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon AWS Micro Instance Mysql Locking up</title>
		<link>http://www.reignite.com.au/amazon-aws-micro-instance-mysql-locking-up/</link>
		<comments>http://www.reignite.com.au/amazon-aws-micro-instance-mysql-locking-up/#comments</comments>
		<pubDate>Fri, 26 Oct 2012 04:07:33 +0000</pubDate>
		<dc:creator>surrey</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.reignite.com.au/?p=1042</guid>
		<description><![CDATA[Just a quick blog entry here to help out those starting with Amazon AWS (cloud).  One of the easiest and cheapest ways to get started is with an Amazon AMI linux micro instance.  This is a small and fast instance &#8230; <a href="http://www.reignite.com.au/amazon-aws-micro-instance-mysql-locking-up/" class="link-more">more</a>]]></description>
			<content:encoded><![CDATA[<p>Just a quick blog entry here to help out those starting with Amazon AWS (cloud).  One of the easiest and cheapest ways to get started is with an Amazon AMI linux micro instance.  This is a small and fast instance of Linux that will run most basic web sites.  However it does not start with a swap file.  This means mysql will quickly run out of memory and die.</p>
<p>You&#8217;ll see error messages like:</p>
<p>Fatal error: cannot allocate memory for the buffer pool</p>
<p>mysqld dead but subsys locked</p>
<p>And so on.  Her is a quick way to create a swap file (makes your system perform better anyway)</p>
<ol>
<li>dd if=/dev/zero of=/swapfile bs=1M count=1024</li>
<li>mkswap /swapfile</li>
<li>swapon /swapfile</li>
<li>Open /etc/fstab and add this line <span style="text-decoration: underline;">/swapfile swap swap defaults 0 0</span></li>
</ol>
<p><span style="line-height: 24px;"><br />
Thanks to: <a href="http://www.prowebdev.us/2012/05/amazon-ec2-linux-micro-swap-space.html">http://www.prowebdev.us/2012/05/amazon-ec2-linux-micro-swap-space.html</a></span></p>
<p><span style="line-height: 24px;">For that info.</span></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reignite.com.au/amazon-aws-micro-instance-mysql-locking-up/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Binary communication using AJAX and AMF</title>
		<link>http://www.reignite.com.au/binary-communication-using-ajax-and-amf/</link>
		<comments>http://www.reignite.com.au/binary-communication-using-ajax-and-amf/#comments</comments>
		<pubDate>Tue, 16 Oct 2012 07:48:26 +0000</pubDate>
		<dc:creator>surrey</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.reignite.com.au/?p=1040</guid>
		<description><![CDATA[So we have moved on from Flex for the most part and taken up GWT and pure javascript to write our rich clients or fat clients or HTML 5 clients.  One thing we&#8217;ve wanted to do is retain our underlying &#8230; <a href="http://www.reignite.com.au/binary-communication-using-ajax-and-amf/" class="link-more">more</a>]]></description>
			<content:encoded><![CDATA[<p>So we have moved on from Flex for the most part and taken up GWT and pure javascript to write our rich clients or fat clients or HTML 5 clients.  One thing we&#8217;ve wanted to do is retain our underlying architecture for services and that meant using AMF directly from javascript.</p>
<h1>AMF</h1>
<p>As a quick refresher AMF is an open source communication protocol developed by Adobe and implemented in Java in BlazeDS.  It is a highly compact binary protocol that accommodates object remoting and remote procedure calls.  The difference between a binary protocol and a non-binary is that a binary protocol just stores the numeric value of a data item instead of spelling it out using characters.  Thus the number 32,342 is represented by 4 bytes as an integer whereas in XML or JSON it is represented by 5 bytes (one for each character).  This becomes particularly useful with very long numbers like date / time expressions.  The other difference is that AMF uses references for repeated data meaning if you send a list of objects all the same type, the type information is sent only once and a byte reference is used for each additional occurrence.  In all, AMF is up to 10 times more efficient than XML and probably around 5 times more efficient than JSON.</p>
<h1>AMF in GWT</h1>
<p>Previously I created an AMF client in GWT and compiled that to Javascript which our UI guys used.  This resulted in heavy code that was easy to maintain by me, as a Java developer, but hard to maintain and understand for Javascript developers.</p>
<h1>Greater Efficiency</h1>
<p>Reignite has moved into the mobile application space in a big way.  We&#8217;ve taken our enterprise development mindset and applied it to the mobile space to create robust, scalable and maintainable apps.  But one of the big challenges with mobile apps is bandwidth and memory efficiency.  That is, end users may have relatively small data allowances for their devices and they need all their apps to use it.  So we would like to keep as small a footprint as possible.  We are also aware that wireless speeds are a bit up and down so we need our service calls to be fast.  To that end I threw out BlazeDS and turfed the GWT implementation of AMF to replace it with my own version.  RAMF or AMF version 99 does away with all the legacy Flash interaction and cuts out several unneeded features.  As a result each service call is from 2 bytes to about 100 bytes smaller.  It doesn&#8217;t sound like much, but it adds up on the server side when you have to pay for bandwidth for possibly tens or hundreds of thousands of users.</p>
<h1>AJAX and Character Encoding</h1>
<p>As anyone who has done AJAX calls before knows, the HTML 4 XMLHttp Object can only pass character data to and receive character data back from a server.  So how do you deal with a binary protocol that sends bytes instead?  (HTML 5 has web sockets that allow byte data transmission)  The most common way is Base64 encoding.  But this means taking a step backward in the bandwidth stakes.  This is because Base64 uses 4 bytes to encode 3.  Thus Base64 is 33% fatter than pure binary.  But is Base64 the only way to go?  Nope.  I searched long and hard until I found Y-Enc.  Inspired by Y-Enc I created my own encoding that escapes only negative byte values (positive byte values can be equated to UTF-8 characters).  Since most bytes in an AMF stream are positive I could get away with it.  The results are about 20% smaller message sizes than Base64.  This is really helpful in large requests.  In doing the encode / decode it was important to ensure all data was being sent and received in UTF-8 otherwise it all went south very quickly.</p>
<h1>The Upshot</h1>
<p>The upshot of all of this is Reignite now has a pure Javascript implementation of AMF without the weight of any legacy Flash code.  The server side is implemented in Java and uses Spring to configure it meaning fewer configuration files and greater flexibility.  The server implementation can execute remote procedure calls not only from this new AMF but is backward compatible (to support our old clients) and can be configured to support REST, SOAP and in the future web sockets.</p>
<h1>Number One Tip</h1>
<p>Javascript uses 64 bit numbers but does bitwise operations on only 32 bit numbers.  This means I had to grab an implementation of Long from Google code to allow me to parse 64 bit numbers that came over the wire (such as date / time values and some UTF characters).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reignite.com.au/binary-communication-using-ajax-and-amf/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>What now for Reignite and Flex?</title>
		<link>http://www.reignite.com.au/what-now-for-reignite-and-flex/</link>
		<comments>http://www.reignite.com.au/what-now-for-reignite-and-flex/#comments</comments>
		<pubDate>Wed, 16 Nov 2011 04:46:34 +0000</pubDate>
		<dc:creator>russell</dc:creator>
				<category><![CDATA[Blaze]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.reignite.com.au/?p=962</guid>
		<description><![CDATA[You have probably seen the two big announcements from Adobe recently. 1. they are abandoning the Flash Plugin on Mobile Devices 2. they are contributing Flex to the Apache Foundation Basically Adobe is moving away from Flash and towards HTML5. &#8230; <a href="http://www.reignite.com.au/what-now-for-reignite-and-flex/" class="link-more">more</a>]]></description>
			<content:encoded><![CDATA[<p>You have probably seen the two big announcements from Adobe recently. </p>
<p>1.	they are abandoning the Flash Plugin on Mobile Devices </p>
<p>2.	they are contributing Flex to the Apache Foundation </p>
<p>Basically Adobe is moving away from Flash and towards HTML5.</p>
<p>As Reignite is one of the premier builders of Flex Applications in Australia you would be correct in thinking that this will have some impact on our business and our clients. However the writing has been on the wall for quite a while now and fortunately we saw this coming! </p>
<p>When Steve Jobs effectively banned the Flash Plugin on iOS it sent alarm bells ringing at Reignite. This was nearly 2 years ago now and at that time we were about to launch into Smart Phone App development. We had originally thought that we would simply leverage our then 5+ years of experience with Flex writing online applications to now use Flex to write mobile applications. Apple made sure this was not going to happen. After a quick assessment of a plethora of mobile “write-once-deploy-many” frameworks we realised that nothing was as mature as Flex. It became pretty clear that in the absence of Flex on the mobile that the only real alternative to write quality applications would be to write mobile apps in their native languages. Accordingly we added Objective C and Android skills to the team and we have since built many successful mobile applications. </p>
<p>With more and more people browsing the web via phones and tablets it also soon became apparent that even online applications built in Flex were now under threat. Accordingly we added GWT skills to the team.</p>
<p>So by keeping an eye on our industry and interpreting the trends and moods of developers, technology organisations and the wider Internet community Reignite has predicted the changes coming, put plans in place well ahead of time and now we are well positioned to help all our clients evolve into a HTML5 future.</p>
<p>Reignite will still be one of Australia’s premier developers of online applications however the tools we use to do this have changed. So now we don’t just build online applications that live in the browser but we build multi-screen applications that can run on just about any device including smart phones, tablets, desktops, browsers, smart TVs and so on. Also our partnership with Adobe will not change either, Flex may “catch a second wave” with its contribution to Apache, Adobe’s acquisition of PhoneGap was a very positive move, Adobe makes regular contributions to jQuery and Adobe’s development and graphics tools are still industry leading. All of this means Adobe is still a very relevant company in this space.</p>
<p><strong>I am an existing Reignite Client with a Flex application what do I do?</strong></p>
<p>There is no need to be alarmed, Adobe’s decisions will not have any immediate impact on any of our clients. All your applications will work exactly as they did yesterday and will continue to run for years to come. What we will need to do is look at the future of your applications and assess the correct time (if any) to migrate them over to HTML5. Our friends at Whotune.com wont mind me telling you that we started migrating their Flex application one feature at a time from Flex to GWT several months ago. The site as it exists today is a hybrid HTML5 and Flex application. </p>
<p><strong>Will you continue to write Flex Code and provide Flex Skills to our team?</strong></p>
<p>Yes! All of our developers are already multi-skilled in several languages, mostly Java and Flex. Having a Java and Flex background is the perfect foundation to become a HTML5 developer and as such all of our existing developers will be adding HTML5 to their skill sets. This will enable them to continue to write Flex Applications and provide Flex skills and provide Flex mentoring where needed. </p>
<p>It is unlikely from now on that Reignite will build entirely new green-field projects in Flex, however it is worth pointing out that there are still many areas where Flex is still far superior to HTML5 which is relatively immature.</p>
<p><strong>Does this have any impact on the server side of my application?</strong></p>
<p>No! Reignite has developed all of its applications using a best practice n-tiered architecture. This means that the interface tier implemented in Flex can simply be replaced by a new technology like HTML5 without impacting on the server at all. As part of our migration to various HTML5 based interface development technologies including GWT and PhoneGap we have developed the mechanisms to communicate from the new technology to our existing server side applications. On nearly all of our projects this communication is performed via AMF an open source protocol from Adobe. Reignite has written AMF clients for GWT and JavaScript to allow our new interfaces to connect and communicate with our existing back end services. Good architecture definitely pays you back handsomely in the long term!</p>
<p>If you have any further questions then please do not hesitate to contact me directly or add a comment to this blog.</p>
<p><strong>Russell Francis</strong><br />
Managing Director</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reignite.com.au/what-now-for-reignite-and-flex/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>An AMF client implemented in GWT</title>
		<link>http://www.reignite.com.au/an-amf-client-implemented-in-gwt/</link>
		<comments>http://www.reignite.com.au/an-amf-client-implemented-in-gwt/#comments</comments>
		<pubDate>Fri, 30 Sep 2011 08:55:41 +0000</pubDate>
		<dc:creator>surrey</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[AMF]]></category>
		<category><![CDATA[double binary]]></category>
		<category><![CDATA[GWT]]></category>

		<guid isPermaLink="false">http://www.reignite.com.au/?p=954</guid>
		<description><![CDATA[One of the biggest problems faced by any application is when you want to change front end technologies.  In our case we wanted to introduce a Google Web Toolkit generated interface into an existing Flex application.  While there are many &#8230; <a href="http://www.reignite.com.au/an-amf-client-implemented-in-gwt/" class="link-more">more</a>]]></description>
			<content:encoded><![CDATA[<p>One of the biggest problems faced by any application is when you want to change front end technologies.  In our case we wanted to introduce a Google Web Toolkit generated interface into an existing Flex application.  While there are many hurdles to jump, the one I&#8217;ll go into a little bit is making GWT talk to our existing infrastructure over AMF (BlazeDS).</p>
<h2><span id="more-954"></span>What is GWT?</h2>
<p>GWT is Google Web Toolkit.  It is a base level development kit that cross compiles Java into a Javascript web application.  It allows developers familiar with the Eclipse suite of Java productivity tools to quickly develop and easily support ajax applications.</p>
<h2>What I did</h2>
<p>I created a new user interface for an existing application that had substantial investment in services provided by BlazeDS, Adobes Java implementation of an AMF server.  So rather than recreate all my services using GWT remote procedure calls, I created an AMF client that would compile to Javascript.  It turns out it is fairly complex work to do, but fun.</p>
<h2>Major hurdles</h2>
<p>The major hurdles in converting a Java AMF client to Javascript are:</p>
<ol>
<li>No dynamic class loading.  This means that while I can instantiate classes on the fly and I can use the instanceof operator, I can&#8217;t instantiate objects from class variables, only class literals.  To get over this one, I created a code generator that reads in all your remote objects and creates object proxies for them.  These object proxies are then registered in a big map that maps the remote class name to the local proxy.  This way, when I want to instantiate an object, I get the proxy and use it as a factory to do the work without reflection.</li>
<li>No java.io package.  Ouch.  This hurt because it meant I had to create my own implementations of InputStream and OutputStream (amongst a few other related classes).  That all seemed to go fairly well, but there&#8217;s more to that below.</li>
<li>Ajax calls can only pass strings over HTTP.  AMF is a binary protocol, which makes it more efficient than text based ones.  It uses object references and bitwise encoding to make your packets small and your objects easy to recreate.  It also means you need to base 64 encode your AMF payload.  I then had to put a filter on my server to detect base 64 and decode it.  This adds some overhead to each request, but not much.</li>
</ol>
<h2>Today&#8217;s big issue</h2>
<p>Having over come the above issues I thought it was all smooth sailing, until I found my Date objects weren&#8217;t serialising and deserialising correctly.  For some unknowable reason, Blaze encodes dates as doubles, even though it is encoding the millisecond time which is a long.  That means the time is cast to a double and then encoded using IEEE 754 encoding.  Now to save you some time if you ever have the same need.</p>
<h2>Decoding a Double from a Long</h2>
<p>A double is encoded in three parts, the sign, exponent and mantissa (cool word, look it up).  Essentially you need to break the 64bit integer (long) into chunks and each chunk is then multiplied together.  The left most bit, the one in bit position 63 (0 index) is 0 for positive numbers and 1 for negative numbers</p>
<pre>int sign =  ((bits &gt;&gt; 63) == 0) ? 1 : -1;</pre>
<p>Then the exponent is bits 52 &#8211; 62.</p>
<pre>int exponent = (int) ((bits &gt;&gt; 52) &amp; 0x7ffL);</pre>
<p>But the exponent is what as known as &#8220;biased&#8221; and is stored with an offset so the actual exponent is exponent &#8211; 1075</p>
<p>Finally the mantissa</p>
<pre>long mantissa = (exponent == 0) ? (bits &amp; 0xfffffffffffffL) &lt;&lt; 1 : (bits &amp; 0xfffffffffffffL) | 0x10000000000000L;</pre>
<p>The actual double value is gained thusly:</p>
<pre>double result = sign * mantissa * Math.pow(2, exponent - 1075);</pre>
<h2>Encoding a double to a long</h2>
<p>This is the tricky one and my solution is probably inefficient, but it works and produces the same output as Double.longBitsToDouble() (which you can&#8217;t use in GWT because it calls native methods)</p>
<pre>double v = the double you want to encode;
long bits = (long) v;
long total = 0;
if (v == 0.0) {
	total = 0;
} else {
	Double test = Double.valueOf(v);
	 if (test.isNaN()) {
		total = 0x7ff8000000000000L;
	} else if (v == Double.POSITIVE_INFINITY) {
		total = 0x7ff0000000000000L;
	} else if (v == Double.NEGATIVE_INFINITY) {
		total = 0xfff0000000000000L;
	} else {
		 if (bits &lt; 0) {
			total = 0x8000000000000000l;
			bits = Math.abs(bits);
                        v = Math.abs(v);
		}
		int lastExponent = 0;
		 while (bits &gt;&gt; lastExponent &gt; 0) {
			lastExponent++;
		}
		long exp = (lastExponent + 1022) * (long) Math.pow(2, 52) + 1;
		double man = v / (Math.pow(2, lastExponent - 1)) - 1;
		int count = 52;
		StringBuilder out = new StringBuilder();
		while (man &gt; 0 &amp;&amp; count &gt; 0) {
			man = man * 2;
			if (man &gt; 1) {
				man--;
				out.append("1");
			} else {
				out.append("0");
			}
			count--;
		}
		long manLong = out.length() == 0 ? 0 : Long.valueOf(out.toString(), 2);
		total += exp + manLong;
	}
}
writeLong(total);</pre>
<p>As you can see I ran out of mathematical inspiration and reverted to binary as a string.  For those who are knowledgeable enough and patient enough I&#8217;m sure you can replace the binary string, but the above does work.</p>
<p>There is so much more to do with writing an AMF client in GWT and more I can say about GWT, but that will have to wait until  next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reignite.com.au/an-amf-client-implemented-in-gwt/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>HTML 5 Vs Flex</title>
		<link>http://www.reignite.com.au/html-5-vs-flex/</link>
		<comments>http://www.reignite.com.au/html-5-vs-flex/#comments</comments>
		<pubDate>Tue, 19 Apr 2011 05:17:21 +0000</pubDate>
		<dc:creator>surrey</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.reignite.com.au/?p=939</guid>
		<description><![CDATA[There are endless discussion flying around the &#8216;net regarding the match up between HTML 5 and Flash.  I thought I&#8217;d take a moment to give my view on the whole affair. Definitions First up, let&#8217;s get our terms defined so &#8230; <a href="http://www.reignite.com.au/html-5-vs-flex/" class="link-more">more</a>]]></description>
			<content:encoded><![CDATA[<p>There are endless discussion flying around the &#8216;net regarding the match up between HTML 5 and Flash.  I thought I&#8217;d take a moment to give my view on the whole affair.</p>
<h1><span id="more-939"></span>Definitions</h1>
<p>First up, let&#8217;s get our terms defined so we know what&#8217;s what.</p>
<h2>Flex:</h2>
<p>For those who believe all Flash is created equal, you&#8217;ll need to change your way of thinking.  There are three different things when talking Flash: Flash Runtime, Flash Creative Suite and Flex.  The Flash Runtime is the thing that runs in your browser and allows Flash files (.swf) to run.  It can be compared to the Java Virtual Machine.  Flash Creative Suite is a program you can use to create Flash files.  It is a bit of Photoshop and a bit of programming that lets you write code and create animations, interactions and images.  Then there is Flex.  Flex is an object oriented, enterprise application development framework that uses Actionscript.  It is a way to create rich featured applications that run on the Flash Runtime.  If you want a spinning logo or page banner, you&#8217;d use Flash.  If you wanted a multi-user n-tier enterprise wide, data driven application, you&#8217;d use Flex.</p>
<h2>HTML 5:</h2>
<p>HTML 5 is a standard that specifies a set of markup tags for laying out documents that can be viewed in a web browser.  In general, when someone talks about creating a site in HTML 5 (or any version of HTML) they are usually also talking about the use of cascading style sheets and Javascript as well.</p>
<h1>Should you use HTML 5 Rather than Flex?</h1>
<p>I suppose you want a yes or no answer?  My answer is, like always, use the tool that makes the most sense at the time.  You wouldn&#8217;t use a hammer to drive a screw and you wouldn&#8217;t try to polish your car with sandpaper, would you?  So why would you say HTML 5 is better than Flex, or vice versa?  I wouldn&#8217;t.  Recently, a client asked what we thought of converting their application from Flex to HTML 5.  I said it would be an expensive and fruitless endeavour.  The reason was not because it couldn&#8217;t be done, but rather, for the complexity of application the client had, it would not work out.</p>
<h2>Enterprise Values:</h2>
<p>When developing an application, as opposed to a web site, there are certain extra factors you need to keep in mind:</p>
<ul>
<li>Maintainability: Once put into production, the application needs to be able to be updated and modified easily and cheaply.</li>
<li>Scalability: On application needs to be able to cope with increases in size and use.</li>
<li>Reliability: The application needs to be reliable.</li>
<li>Extensibility: The application needs to be easily expanded beyond its original scope.</li>
</ul>
<p>Flex is object oriented, compiled and can be developed using Flash Builder (the name is confusing, I know).  The feature set supported by the Flash runtime and the code base available to Flex is maintained by Adobe, a single company with a single vision.  This means that if I write a Flex application and it works well on my computer, it will work well on someone else&#8217;s computer too.  It also means that I can hand my code over to one of my colleagues and they can immediately continue work on it.  HTML 5 is a standard that specifies certain behaviours but not implementations.  Each browser vendor creates their own interpretation of how it should all work.  Some implement optional features, some invent their own features and some simply don&#8217;t comply with the standards.  The features supported by one version of a browser may not be supported by the next version and so on.  As a result, trying to write a complex application in HTML/Javascript/css turns into a nightmare game of tail-chasing.  Does this mean HTML 5 should not be used?  Heck no.  HTML 5 is a fantastic, modular and flexible way to create web sites.  It provides a quick and easy way to put content into the web and because it is light-weight, you can create small sites much faster than you could with Flex.  But until someone creates a standard and stable implementation, used by all vendors, it just can&#8217;t pass muster for large and complex projects.  People will disagree with me, but I think that would be a matter of how they define large or complex.</p>
<h1>Summary</h1>
<p>HTML vs Flex is horses for courses.  If you want to build an application, particularly an enterprise level one, you would be best served by Flex.  Its stable and predictable performance and ease of maintenance and extensibility will save you many hours and many dollars.  HTML is much better for company web sites or single purpose applications where you will not be doing a lot of expanding or maintenance work.  Mind you, I won&#8217;t be surprised when Adobe releases a compiler that will turn Flex code into HTML 5 content so the future might well belong to HTML.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reignite.com.au/html-5-vs-flex/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Blaze Push Messaging In A Cluster</title>
		<link>http://www.reignite.com.au/blaze-push-messaging-in-a-cluster/</link>
		<comments>http://www.reignite.com.au/blaze-push-messaging-in-a-cluster/#comments</comments>
		<pubDate>Fri, 25 Feb 2011 03:08:36 +0000</pubDate>
		<dc:creator>surrey</dc:creator>
				<category><![CDATA[Blaze]]></category>

		<guid isPermaLink="false">http://www.reignite.com.au/?p=908</guid>
		<description><![CDATA[The Scene: Imagine the scenario where you have two application servers behind a hardware load balancer.  Imagine that the load balancer uses &#8220;round-robin&#8221; style balancing.  That is, rather than using sticky sessions to associate a client machine with a single &#8230; <a href="http://www.reignite.com.au/blaze-push-messaging-in-a-cluster/" class="link-more">more</a>]]></description>
			<content:encoded><![CDATA[<h3>The Scene:</h3>
<p>Imagine the scenario where you have two application servers behind a hardware load balancer.  Imagine that the load balancer uses &#8220;round-robin&#8221; style balancing.  That is, rather than using sticky sessions to associate a client machine with a single server for the duration of their session, the load balancer simply alternates which machine each request goes to.</p>
<h3>The Problem:</h3>
<p>The problem is that BlazeDS stores client subscriptions at the servlet level, that is in the server context.  So when the subscribe message from the client hits the server, Blaze creates a subscription that is stored in the memory (web context) of that servlet container.  Then the client sends a poll request for data and the load balancer flicks it off to the other server.  You can see that the second server would have no knowledge of the client and would return a &#8220;no subscription found&#8221; error and so the client would attempt to re-subscribe.  That new subscription message would be directed to the original server, which would say &#8220;I&#8217;ve already got your subscription&#8221;.  The funny business would repeat until the client finally quits.</p>
<p><span id="more-908"></span></p>
<h3>Possible Solutions:</h3>
<ol>
<li>Blaze comes with JGroups clustering.  You could use this to flick messages about the place.  I tried it, and it worked a bit.  What tended to happen though is that servers would drop out of the JGroups cluster and not re-merge, or messages would be delayed and get out of sync or the gremlins would eat the packets.  I&#8217;m not really sure why these things happened, but it was completely unacceptable for a business critical, software-as-a-service application.</li>
<li>I tried using the Apache Tomcat session replication feature.  It was pretty easy to set up and as easy to break.    It worked, sort of, but I had the same issues of unreliable message propagation.  The way Tomcat detected a dirty session was by looking at attribute changes in the session context, not several layers in to an object in the context.  Blaze keeps a subscription object with a list / map of messages and connected clients.  Tomcat couldn&#8217;t detect the changes that happened deep inside that subscription object, so I had to manually muck about.  Suffice to say it was a mess.</li>
</ol>
<h3>So What Works?</h3>
<p><span style="font-size: small;">Taking a leaf from my old middleware days playing in the Victorian (state of Australia, not during the reign of the Queen) Power Market, I decided to use the database to guarantee message delivery.  The system I was working on used MySQL with two way replication.  That is, each app server had an instance that was both the master of, and slave to, each other.  If you haven&#8217;t used it before, MySQL server replication as of v5.1 is extremely reliable over two computers and very quick.  In over 2 years of operation, this set up has failed only twice.  Both of those failures were due to operating system crashes caused by unexpected shutdown situations.</p>
<h3>Solution Part One:</h3>
<p>Create two new tables in the DB: subscription and message.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> <span style="color: #ff0000;">`subscription`</span>;CREATE <span style="color: #993333; font-weight: bold;">TABLE</span>  <span style="color: #ff0000;">`subscription`</span> <span style="color: #66cc66;">&#40;</span>  <span style="color: #ff0000;">`ID`</span> <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`CLIENT_ID`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`MESSAGE_CLIENT_ID`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`SELECTOR`</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`EXPIRY_DATE`</span> datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`LAST_MESSAGE_ID`</span> <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`CREATED_DATE`</span> datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`MODIFIED_DATE`</span> datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`ID`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>  <span style="color: #993333; font-weight: bold;">UNIQUE</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #ff0000;">`Index_CLIENT_ID_UNIQUE`</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`CLIENT_ID`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>InnoDB <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">17</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>latin1;</pre></div></div>

<p>and</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">DROP</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #993333; font-weight: bold;">IF</span> <span style="color: #993333; font-weight: bold;">EXISTS</span> <span style="color: #ff0000;">`blaze_message`</span>;CREATE <span style="color: #993333; font-weight: bold;">TABLE</span>  <span style="color: #ff0000;">`blaze_message`</span> <span style="color: #66cc66;">&#40;</span>  <span style="color: #ff0000;">`ID`</span> <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">10</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`MESSAGE_BYTES`</span> <span style="color: #993333; font-weight: bold;">BLOB</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`MESSAGE_BODY`</span> text<span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`CREATED_DATE`</span> datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #ff0000;">`MODIFIED_DATE`</span> datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`ID`</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>InnoDB <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">=</span><span style="color: #cc66cc;">152</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>latin1;</pre></div></div>

<p>When a client subscribes to a server, an entry is placed in the subscription table.  Then, when that same client polls, either server can get the subscription from the DB and service it.  The DB takes care of replicating the subscription to each server, and it does it very well.  But what is stored?</p>
<p>CLIENT_ID: this is the unique id created by the instance of Flash or Air.</p>
<p>MESSAGE_CLIENT_ID: this is the unique id created by the instance of the consumer running on Flash or Air.  You can let Flash/Air create this for you, but we like to append our own user id to the end of it so we can make sense of log messages and such.</p>
<p>SELECTOR: Adobe have implemented the idea of &#8220;selectors&#8221; to channel messages to different consumers.  For example we have normal users and admins.  Normal users receive only those messages meant for them based on role and client company (software as a service) but admins get all messages.</p>
<p>LAST_MESSAGE_ID: This is how I guarantee delivery of messages.  Messages are queued in the message table and each subscriber receives all messages from the last id to the most recent, in that order.  That way, if a poll goes missing we can keep the message around until the client gets it.</p>
<p>When a message is to be sent, the publisher inserts a record of it in the message table.   The main bit to see is the MESSAGE_BYTES column which is simply the Blaze message object serialized using an ObjectOutputStream.  I also store the text representation of the message body (XML) so I can trace it in logs and so on.  Every so often I clean out the message table by removing all messages that have been received by all subscribers.  I check that by looking at the LAST_MESSAGE_ID in the subscription table.</p>
<h3>Solution Part Two:</h3>
<p>So part one covered the database side of things, but you want to know how I made Blaze play by the new rules&#8230; I extended a couple of classes .  One that takes care of subscriptions and one that takes care of publishing.</p>
<p>In my messaging-config.xml file, instead of using the standard adapter, I created my own:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">au.com.reignite.amf</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.ByteArrayOutputStream</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.ObjectOutputStream</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.context.ApplicationContext</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.web.context.support.WebApplicationContextUtils</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">au.com.reignite.logging.LogWriter</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">au.com.reignite.orchestration.MessageOrchestrator</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.FlexContext</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.MessageDestination</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.config.ConfigMap</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.messages.AsyncMessage</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.messages.CommandMessage</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.messages.Message</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.services.messaging.SubscriptionManager</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.services.messaging.adapters.MessagingAdapter</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> DatabaseMessagingAdapter <span style="color: #000000; font-weight: bold;">extends</span> MessagingAdapter <span style="color: #009900;">&#123;</span>
&nbsp;
&nbsp;
 <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> messageOrchestratorName <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;messageOrchestrator&quot;</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
 <span style="color: #000000; font-weight: bold;">private</span> MessageOrchestrator messageOrchestrator<span style="color: #339933;">;</span>
&nbsp;
&nbsp;
 @Override
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Object</span> invoke<span style="color: #009900;">&#40;</span>Message message<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
 <span style="color: #666666; font-style: italic;">// just store this message in the database queues</span>
 <span style="color: #666666; font-style: italic;">// when the client polls for messages it will get</span>
 <span style="color: #666666; font-style: italic;">// them direct from the db. If there aren't any</span>
 <span style="color: #666666; font-style: italic;">// in the db it will wait and the server will poll</span>
 <span style="color: #666666; font-style: italic;">// the db on behalf of the client until timeout or</span>
 <span style="color: #666666; font-style: italic;">// a message is returned.</span>
&nbsp;
&nbsp;
 <span style="color: #003399;">ByteArrayOutputStream</span> bos <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ByteArrayOutputStream</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #003399;">ObjectOutputStream</span> out<span style="color: #339933;">;</span>
 <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
    out <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ObjectOutputStream</span><span style="color: #009900;">&#40;</span>bos<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    out.<span style="color: #006633;">writeObject</span><span style="color: #009900;">&#40;</span>message<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    getMessageOrchestrator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">storeMessage</span><span style="color: #009900;">&#40;</span>bos.<span style="color: #006633;">toByteArray</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>,
    message.<span style="color: #006633;">getBody</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">IOException</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    LogWriter.<span style="color: #006633;">error</span><span style="color: #009900;">&#40;</span>getClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;Failed to serialize message: &quot;</span> <span style="color: #339933;">+</span> e, e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
 <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
 <span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * @see flex.messaging.services.ServiceAdapter#handlesSubscriptions()
 */</span>
 @Override
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> handlesSubscriptions<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
 <span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * Manages subscriptions and unsubscriptions. In particular the creation of
 * subscriptions in the database.
 * 
 * @see flex.messaging.services.ServiceAdapter#manage(flex.messaging.messages.CommandMessage)
 */</span>
 @Override
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Object</span> manage<span style="color: #009900;">&#40;</span>CommandMessage commandMessage<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>commandMessage.<span style="color: #006633;">getOperation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> CommandMessage.<span style="color: #006633;">SUBSCRIBE_OPERATION</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       LogWriter.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span>getClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;SUBSCRIBE: &quot;</span>
       <span style="color: #339933;">+</span> commandMessage.<span style="color: #006633;">getClientId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot; in MessagingAdapter&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       MessageDestination destination <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>MessageDestination<span style="color: #009900;">&#41;</span> getDestination<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       SubscriptionManager subscriptionManager <span style="color: #339933;">=</span> destination
       .<span style="color: #006633;">getSubscriptionManager</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       <span style="color: #003399;">String</span> selectorExpr <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span> commandMessage
       .<span style="color: #006633;">getHeader</span><span style="color: #009900;">&#40;</span>CommandMessage.<span style="color: #006633;">SELECTOR_HEADER</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       subscriptionManager.<span style="color: #006633;">removeSubscriber</span><span style="color: #009900;">&#40;</span>commandMessage.<span style="color: #006633;">getClientId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>,
       selectorExpr, <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span> commandMessage
       .<span style="color: #006633;">getHeader</span><span style="color: #009900;">&#40;</span>AsyncMessage.<span style="color: #006633;">SUBTOPIC_HEADER_NAME</span><span style="color: #009900;">&#41;</span>,
       <span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span> commandMessage.<span style="color: #006633;">getHeader</span><span style="color: #009900;">&#40;</span>Message.<span style="color: #006633;">ENDPOINT_HEADER</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       getMessageOrchestrator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">storeSubscription</span><span style="color: #009900;">&#40;</span>
       FlexContext.<span style="color: #006633;">getFlexClient</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>,
       commandMessage.<span style="color: #006633;">getClientId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, selectorExpr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>commandMessage.<span style="color: #006633;">getOperation</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> CommandMessage.<span style="color: #006633;">UNSUBSCRIBE_OPERATION</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
       <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>FlexContext.<span style="color: #006633;">getFlexClient</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
           LogWriter
           .<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span>getClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;UNSUBSCRIBE: &quot;</span>
           <span style="color: #339933;">+</span> commandMessage.<span style="color: #006633;">getClientId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
           <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot; in MessagingAdapter&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
           getMessageOrchestrator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">deleteSubscription</span><span style="color: #009900;">&#40;</span>
           FlexContext.<span style="color: #006633;">getFlexClient</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
 <span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * @see flex.messaging.services.messaging.adapters.MessagingAdapter#initialize(java.lang.String,
 *      flex.messaging.config.ConfigMap)
 */</span>
 @Override
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> initialize<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> id, ConfigMap properties<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">super</span>.<span style="color: #006633;">initialize</span><span style="color: #009900;">&#40;</span>id, properties<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    messageOrchestratorName <span style="color: #339933;">=</span> properties.<span style="color: #006633;">getPropertyAsString</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">&quot;message-orchestrator-name&quot;</span>, <span style="color: #0000ff;">&quot;messageOrchestrator&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
 <span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * @return the messageOrchestratorName
 */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getMessageOrchestratorName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> messageOrchestratorName<span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
 <span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * @param messageOrchestratorName
 *            the messageOrchestratorName to set
 */</span>
 <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setMessageOrchestratorName<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> messageOrchestratorName<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">messageOrchestratorName</span> <span style="color: #339933;">=</span> messageOrchestratorName<span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
 <span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * @return the messageOrchestrator
 */</span>
 <span style="color: #000000; font-weight: bold;">public</span> MessageOrchestrator getMessageOrchestrator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>messageOrchestrator <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ApplicationContext appContext <span style="color: #339933;">=</span> WebApplicationContextUtils
        .<span style="color: #006633;">getRequiredWebApplicationContext</span><span style="color: #009900;">&#40;</span>FlexContext
        .<span style="color: #006633;">getServletContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        messageOrchestrator <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>MessageOrchestrator<span style="color: #009900;">&#41;</span> appContext
       .<span style="color: #006633;">getBean</span><span style="color: #009900;">&#40;</span>messageOrchestratorName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000000; font-weight: bold;">return</span> messageOrchestrator<span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h6>The important bits:</h6>
<p>INVOKE: The invoke method serialises the Blaze message object and stores it in the database as a new message.  The MessageOrchestrator object I&#8217;m using is just my service for database persistence, you would use your own method there.</p>
<p>HANDLESSUBSCRIPTIONS: You need to make sure you return true, for obvious reasons.</p>
<p>MANAGE: This method actually manages the subscriptions and unsubscriptions.  You can see that when I get a subscribe message I log a bit of info, grab a stack of info from the message and store it using the MessageOrchestrator.  The fancy bit of trickery I do in here is to use the Blaze SubscriptionManager to remove a subscriber.  That sounds like the opposite of what I want to do, but the problem is that Blaze store the subscription even though I&#8217;m managing it myself.  So I take it out of Blaze to keep things clean.  In the case of an unsubscribe message I just log it and delete the subscription from the DB.</p>
<p>The second class I had to extend was Endpoint.  Thusly:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">au.com.reignite.amf</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.ByteArrayInputStream</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.IOException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.ObjectInputStream</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.ArrayList</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.List</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.context.ApplicationContext</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.springframework.web.context.support.WebApplicationContextUtils</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">au.com.reignite.domain.message.BlazeMessage</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">au.com.reignite.domain.message.Subscription</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">au.com.reignite.logging.LogWriter</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">au.com.reignite.orchestration.MessageOrchestrator</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.FlexContext</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.MessageException</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.client.FlexClient</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.client.FlushResult</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.config.ConfigMap</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.endpoints.ConfigurableAMFEndpoint</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.messages.CommandMessage</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.messages.Message</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.services.MessageService</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">flex.messaging.services.messaging.selector.JMSSelector</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #008000; font-style: italic; font-weight: bold;">/**
 * An AMF endpoint that is not only configurable (may configure additional amf
 * filters) but also uses the database as a backing for poll commands.
 * 
 * @author Surrey
 * 
*/</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> DatabaseConfigurableAMFEndpoint <span style="color: #000000; font-weight: bold;">extends</span> ConfigurableAMFEndpoint <span style="color: #009900;">&#123;</span>
&nbsp;
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> messageOrchestratorName <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;messageOrchestrator&quot;</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Long</span> dataBasePollMillis <span style="color: #339933;">=</span> 500l<span style="color: #339933;">;</span>		
&nbsp;
&nbsp;
	<span style="color: #000000; font-weight: bold;">private</span> MessageOrchestrator messageOrchestrator<span style="color: #339933;">;</span>
&nbsp;
&nbsp;
	<span style="color: #008000; font-style: italic; font-weight: bold;">/**
	* Polls the database instead of using the flex client. It is necessary to
	* divert the normal poll action here because in an environment with
	* multiple blaze servers it is unknown which server a poll will be against
	*  but the normal polling requires the poll to be against the same server as
	* the subscription. Subscriptions are held in the database and are managed
	* and timed out by a separate reaper thread.
	* 
	* @see flex.messaging.endpoints.AbstractEndpoint#handleFlexClientPollCommand
	*      (flex.messaging.client.FlexClient,
	*      flex.messaging.messages.CommandMessage)
	*/</span>
	@SuppressWarnings<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;unchecked&quot;</span><span style="color: #009900;">&#41;</span>
	@Override
	<span style="color: #000000; font-weight: bold;">protected</span> FlushResult handleFlexClientPoll<span style="color: #009900;">&#40;</span>FlexClient flexClient,
	CommandMessage pollCommand<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		LogWriter.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span>getClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;HANDLE_FLEX_CLIENT_POLL: &quot;</span>
		<span style="color: #339933;">+</span> flexClient.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		FlushResult result <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
		Subscription subscription <span style="color: #339933;">=</span> getMessageOrchestrator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">loadSubscription</span><span style="color: #009900;">&#40;</span>
		flexClient.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>subscription <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			LogWriter.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span>getClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;CLIENT: &quot;</span> <span style="color: #339933;">+</span> flexClient.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot; has no subscription.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			MessageException e <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> MessageException<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			e.<span style="color: #006633;">setMessage</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">10028</span>, <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Object</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#123;</span> getId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			e.<span style="color: #006633;">setCode</span><span style="color: #009900;">&#40;</span>MessageService.<span style="color: #006633;">NOT_SUBSCRIBED_CODE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000000; font-weight: bold;">throw</span> e<span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #666666; font-style: italic;">// begin wait and poll of the database</span>
		<span style="color: #000066; font-weight: bold;">long</span> wait <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
		JMSSelector jmsSelector <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> JMSSelector<span style="color: #009900;">&#40;</span>subscription.<span style="color: #006633;">getSelector</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003399;">Integer</span> lastMessageId <span style="color: #339933;">=</span> subscription.<span style="color: #006633;">getLastMessageId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000000; font-weight: bold;">do</span> <span style="color: #009900;">&#123;</span>
			<span style="color: #666666; font-style: italic;">// get messages and check for match of selector</span>
			List<span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span>BlazeMessage<span style="color: #339933;">&amp;</span>gt<span style="color: #339933;">;</span> msgs <span style="color: #339933;">=</span> getMessageOrchestrator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">loadMessages</span><span style="color: #009900;">&#40;</span>
			lastMessageId<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>BlazeMessage blazeMessage <span style="color: #339933;">:</span> msgs<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				lastMessageId <span style="color: #339933;">=</span> blazeMessage.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #003399;">ByteArrayInputStream</span> bin <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ByteArrayInputStream</span><span style="color: #009900;">&#40;</span>
				blazeMessage.<span style="color: #006633;">getMessageBytes</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #003399;">ObjectInputStream</span> in <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
				<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
					in <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ObjectInputStream</span><span style="color: #009900;">&#40;</span>bin<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
					Message message <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>Message<span style="color: #009900;">&#41;</span> in.<span style="color: #006633;">readObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
					<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>jmsSelector.<span style="color: #006633;">match</span><span style="color: #009900;">&#40;</span>message<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
						<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>result <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
							result <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> FlushResult<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
							result.<span style="color: #006633;">setMessages</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ArrayList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
						<span style="color: #009900;">&#125;</span>
						message.<span style="color: #006633;">setClientId</span><span style="color: #009900;">&#40;</span>subscription.<span style="color: #006633;">getMessageClientId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
						result.<span style="color: #006633;">getMessages</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>message<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
					<span style="color: #009900;">&#125;</span>
				<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
					LogWriter.<span style="color: #006633;">error</span><span style="color: #009900;">&#40;</span>getClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;Failed to deserialize: &quot;</span> <span style="color: #339933;">+</span> e, e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">finally</span> <span style="color: #009900;">&#123;</span>
					<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>in <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
						<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
							in.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
						<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">IOException</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
							<span style="color: #666666; font-style: italic;">// do nothing</span>
						<span style="color: #009900;">&#125;</span>
					<span style="color: #009900;">&#125;</span>
				<span style="color: #009900;">&#125;</span>
			<span style="color: #009900;">&#125;</span>
			<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>result <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
			<span style="color: #666666; font-style: italic;">// there were no matching messages so wait and check again</span>
			<span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
				wait <span style="color: #339933;">+=</span> dataBasePollMillis<span style="color: #339933;">;</span>
				<span style="color: #000000; font-weight: bold;">synchronized</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">this</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
					<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">wait</span><span style="color: #009900;">&#40;</span>dataBasePollMillis<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
				<span style="color: #009900;">&#125;</span>
			<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">InterruptedException</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
				<span style="color: #666666; font-style: italic;">// do nothing</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span><span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>wait <span style="color: #339933;">&amp;</span>lt<span style="color: #339933;">;</span> waitInterval<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		LogWriter.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span>getClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, <span style="color: #0000ff;">&quot;END POLL for: &quot;</span> <span style="color: #339933;">+</span> flexClient.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		getMessageOrchestrator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">storeSubscription</span><span style="color: #009900;">&#40;</span>subscription.<span style="color: #006633;">getClientId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>,
		subscription.<span style="color: #006633;">getMessageClientId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, subscription.<span style="color: #006633;">getSelector</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>,
		lastMessageId<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000000; font-weight: bold;">return</span> result<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
	<span style="color: #008000; font-style: italic; font-weight: bold;">/**
	* @return the messageOrchestrator
	*/</span>
	<span style="color: #000000; font-weight: bold;">public</span> MessageOrchestrator getMessageOrchestrator<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>messageOrchestrator <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
			ApplicationContext appContext <span style="color: #339933;">=</span> WebApplicationContextUtils
			.<span style="color: #006633;">getRequiredWebApplicationContext</span><span style="color: #009900;">&#40;</span>FlexContext
			.<span style="color: #006633;">getServletContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			messageOrchestrator <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>MessageOrchestrator<span style="color: #009900;">&#41;</span> appContext
			.<span style="color: #006633;">getBean</span><span style="color: #009900;">&#40;</span>messageOrchestratorName<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span>
		<span style="color: #000000; font-weight: bold;">return</span> messageOrchestrator<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
	<span style="color: #008000; font-style: italic; font-weight: bold;">/**
	* @return the messageOrchestratorName
	*/</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getMessageOrchestratorName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">return</span> messageOrchestratorName<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
	<span style="color: #008000; font-style: italic; font-weight: bold;">/**
	 * @param messageOrchestratorName
	 *            the messageOrchestratorName to set
	 */</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setMessageOrchestratorName<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> messageOrchestratorName<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">messageOrchestratorName</span> <span style="color: #339933;">=</span> messageOrchestratorName<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
	<span style="color: #008000; font-style: italic; font-weight: bold;">/**
	* @return the dataBasePollMillis
	*/</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">Long</span> getDataBasePollMillis<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">return</span> dataBasePollMillis<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
	<span style="color: #008000; font-style: italic; font-weight: bold;">/**
	* @param dataBasePollMillis
	*            the dataBasePollMillis to set
	*/</span>
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setDataBasePollMillis<span style="color: #009900;">&#40;</span><span style="color: #003399;">Long</span> dataBasePollMillis<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">dataBasePollMillis</span> <span style="color: #339933;">=</span> dataBasePollMillis<span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
	<span style="color: #008000; font-style: italic; font-weight: bold;">/**
	* @see flex.messaging.endpoints.ConfigurableAMFEndpoint#initialize(java.lang
	*      .String, flex.messaging.config.ConfigMap)
	*/</span>
	@Override
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> initialize<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> id, ConfigMap properties<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">super</span>.<span style="color: #006633;">initialize</span><span style="color: #009900;">&#40;</span>id, properties<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		messageOrchestratorName <span style="color: #339933;">=</span> properties.<span style="color: #006633;">getPropertyAsString</span><span style="color: #009900;">&#40;</span>
		<span style="color: #0000ff;">&quot;message-orchestrator-name&quot;</span>, <span style="color: #0000ff;">&quot;messageOrchestrator&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h6>The Important Bits:</h6>
<p>HANDLEFLEXCLIENTPOLL: In essence all I&#8217;m doing here is grabbing enough info from the poll request to pull the subscription from the database, check the selector and if it matches, I return the message.  I update the subscription with the message id as the LAST_MESSAGE_ID so I know where I&#8217;m up to.  Of course there is a stack of logging and error catching going on as well.</p>
<p>There you go.  You update your config xml to use this endpoint and that adapter and away you go.  This messaging system has worked very well for a couple of years now.  I am about to do some reworking of it in cooperation with flex client changes to handle &#8220;delivery in doubt&#8221; messages.  These are the ones where the client sends a poll, but for some unknown reason it doesn&#8217;t reach the server properly.  At present this causes a retry, but Justin and I want to make it a bit more water tight so push messaging is 100% reliable.</p>
<p>Till next time,</p>
<p>Surrey.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reignite.com.au/blaze-push-messaging-in-a-cluster/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Editable Bullets, List Items with TLF and Flex 4</title>
		<link>http://www.reignite.com.au/editable-bullets-list-items-with-tlf-and-flex-4/</link>
		<comments>http://www.reignite.com.au/editable-bullets-list-items-with-tlf-and-flex-4/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 10:22:25 +0000</pubDate>
		<dc:creator>Justin Pante</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[TLF]]></category>

		<guid isPermaLink="false">http://www.reignite.com.au/?p=889</guid>
		<description><![CDATA[So Everyone knows the story&#8230; Why oh why were there no bullets with TLF 1?! I Know TLF 2 is in development and around the corner but unfortunately we couldn&#8217;t wait.  We had the requirement to move to the more &#8230; <a href="http://www.reignite.com.au/editable-bullets-list-items-with-tlf-and-flex-4/" class="link-more">more</a>]]></description>
			<content:encoded><![CDATA[<p>So Everyone knows the story&#8230; Why oh why were there no bullets with TLF 1?!</p>
<p>I Know TLF 2 is in development and around the corner but unfortunately we couldn&#8217;t wait.  We had the requirement to move to the more stable TLF from the old Flash TextFields but also needed to render bullets.</p>
<p>The most common solution I&#8217;ve seen to combat this issue is the use of the Bullet Unicode character appended to a paragraph or span element.  This poses a number of problems.</p>
<ol>
<li>Bullets are editable (which can be worked around by shifting the selection any time a user clicks into or keys into the bullet region)</li>
<li>Bulleted paragraphs do not wrap gracefully.  List Items that span multiple lines will need different indents if the font size changes due to the fact that the Bullet Character&#8217;s width will change so lists will not line up as expected.</li>
</ol>
<p>There are more issues we encountered but unfortunately I don&#8217;t have all day to go through each in detail</p>
<p>As another solution I wrote a function that loops through the textlines in the flow composer on each composition_completion and draw&#8217;s bullets on a child layer of the RichEditableText based on a styleName of the paragraph.</p>

    <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="swfobj_0" width="320" height="300">
      <param name="movie" value="http://www.justinpante.net/flex/bulletExample/TLFBulletExample.swf" />
      <!--[if !IE]>-->
      <object type="application/x-shockwave-flash" data="http://www.justinpante.net/flex/bulletExample/TLFBulletExample.swf" width="320" height="300">
      <!--<![endif]-->
        
      <!--[if !IE]>-->
      </object>
      <!--<![endif]-->
    </object>

<p>You can view the source by <a title="Bullet Example Source" href="http://www.justinpante.net/flex/bulletExample/srcview/index.html" target="_blank">clicking here</a></p>
<p>Enjoy!</p>
<p>J.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.reignite.com.au/editable-bullets-list-items-with-tlf-and-flex-4/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
