<?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>Christophe Coenraets &#187; LCDS</title>
	<atom:link href="http://coenraets.org/blog/category/lcds/feed/" rel="self" type="application/rss+xml" />
	<link>http://coenraets.org/blog</link>
	<description>Rich Internet Applications, Flex, AIR, Java, Android</description>
	<lastBuildDate>Fri, 23 Jul 2010 14:45:06 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Using the Flash Builder 4 Data Centric Features with Parsley (and other frameworks)</title>
		<link>http://coenraets.org/blog/2010/05/using-the-flash-builder-4-data-centric-features-with-parsley-and-other-frameworks/</link>
		<comments>http://coenraets.org/blog/2010/05/using-the-flash-builder-4-data-centric-features-with-parsley-and-other-frameworks/#comments</comments>
		<pubDate>Wed, 05 May 2010 13:59:13 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[BlazeDS]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[LCDS]]></category>
		<category><![CDATA[Parsley]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=673</guid>
		<description><![CDATA[I have blogged about the new data-centric features in Flash Builder 4 here and here. One question people often ask me is: “Can I use this feature if I use a Framework (Cairngorm, Mate, Parsley, Spring ActionScript, Swiz, etc)?” The answer is yes: The classes generated by Flash Builder (Value Objects and Service Stubs) are [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://coenraets.org/apps/contacts/contacts.jpg" alt="" /></p>
<p>I have blogged about the new data-centric features in Flash Builder 4 <a href="http://coenraets.org/blog/2010/03/flex-4-sample-application-using-a-java-back-end-blazeds-4-and-flash-builder-4-data-wizards/">here </a>and <a href="http://coenraets.org/blog/2010/03/flex-4-sample-application-using-a-java-back-end-blazeds-4-and-flash-builder-4-data-wizards/">here</a>. One question people often ask me is: “Can I use this feature if I use a Framework (Cairngorm, Mate, Parsley, Spring ActionScript, Swiz, etc)?”</p>
<p>The answer is yes: The classes generated by Flash Builder (Value Objects and Service Stubs) are standard building blocks that are part of most RIA design patterns, regardless of whether or not you use a framework.</p>
<p>The way you leverage these classes in your application may differ slightly depending on the framework you are using. For example, each framework may have a different approach to configure service endpoints or to instantiate generated service stubs.</p>
<p>To demonstrate this, I built a version of my “Contacts” application (also known as InSync) using the Flash Builder 4 data-centric features and the <a href="http://www.spicefactory.org/parsley/">Parsley Framework</a>.</p>
<p><span id="more-673"></span><br />
<strong>Configuring Service Endpoints</strong></p>
<p>By default, an application built using a BlazeDS or LCDS project determines its service endpoints using a combination of assumptions made at runtime and hardcoded references baked into the swf at compile time. Read my <a href="http://coenraets.org/blog/2009/03/externalizing-service-configuration-using-blazeds-and-lcds/">Externalizing Service Configuration</a> blog post for more information on this topic. The bottom line is that this default behavior is insufficient for any application other than a simple demo: you want endpoints to be fully configurable so that you can move services around without having to recompile your application.</p>
<p>Using Parsley, I inject the service endpoint configuration (in the form of a ChannelSet) in the generated service stubs as follows:</p>
<pre class="brush: jscript;">
public class ContactService extends _Super_ContactService
{
	[Inject]
	override public function set channelSet(cs:ChannelSet):void
	{
		super.channelSet = cs;
	}
}
</pre>
<p>Note that I added this code in ContactService.as and not _Super_ContactService.as. Contrary to _Super_ContactService.as, ContactService.as will never be regenerated and is therefore the right place to add your custom code.</p>
<p>The injected ChannelSet is defined in my own channels-config.xml configuration file as follows:</p>
<pre class="brush: xml;">
&lt;object type=&quot;mx.messaging.ChannelSet&quot;&gt;
 	&lt;property name=&quot;channels&quot;&gt;
    		&lt;array&gt;
		    	&lt;object type=&quot;mx.messaging.channels.AMFChannel&quot;&gt;
		        	&lt;property name=&quot;uri&quot; value=&quot;http://localhost:8400/testdrive/messagebroker/amf&quot;/&gt;
		        &lt;/object&gt;
	        &lt;/array&gt;
	&lt;/property&gt;
&lt;/object&gt;
</pre>
<p>Note: Unlike the BlazeDS/LCDS services-config.xml file, channels-config.xml is read at runtime.</p>
<p>Because the ChannelSet is configured in an xml file, you can easily change the channel’s endpoint URI without recompiling the application. You could also add failoverURIs to this channel, or add completely new fall back channels to the ChannelSet.</p>
<p><strong>Instantiating Service Stubs</strong></p>
<p>As we already alluded to, Parsley is a dependency injection framework: Instead of letting a component instantiate its dependencies, those dependencies are injected in the component at runtime. For example, in ContactForm, instead of instantiating a ContactService as follows:</p>
<pre class="brush: xml;">
&lt;services:ContactService/&gt;
</pre>
<p>… I simply defined a contactService reference variable that I annotated with [Inject] to let Parsley inject a ContactService instance a runtime.</p>
<pre class="brush: jscript;">
[Inject]
public var contactService:ContactService
</pre>
<p>The instance of ContactService that Parsley injects is defined in Config.mxml and has itself been injected with a ChannelSet. Object configuration in Parsley is very flexible. In this application I combine the xml and mxml configuration options. I use the xml configuration option for the things I don’t want to hardcode in my application, and the mxml configuration for traditional object instantiation and configuration.</p>
<p>Note: Parsley doesn’t force you to use any specific design pattern. For simplicity in this sample application, I inject a service directly into the view. You can of course use other patterns (like the Presentation Model) to achieve a greater level of abstraction. The Dependency Injection and Messaging infrastructure of Parsley will make the implementation of these patterns easier.</p>
<h2>Installation Instructions</h2>
<ol>
<li><a href="https://www.adobe.com/cfusion/entitlement/index.cfm?e=lc_blazeds">Download</a> and install BlazeDS 4</li>
<li>Make a copy the blazeds web application in blazeds/tomcat/webapps, and call the new web application contacts</li>
<li>Download <a href="http://coenraets.org/apps/contacts/contacts.zip">contacts.zip</a>, and unzip it anywhere on your file system.</li>
<li>Overlay contacts/webapps/contacts (from contacts.zip) on top of blazeds/webapps/contacts</li>
<li>Start the server</li>
<li>Open a Command Window or Shell, navigate to /blazeds/tomcat/bin, and start Tomcat (for instance: catalina run).</li>
<li>Open a browser and access <a href="http://localhost:8400/contacts/ContactsParsley/ContactsParsley.html">http://localhost:8400/contacts/ContactsParsley/ContactsParsley.html</a>.</li>
</ol>
<p>Note: The web application also include a plain (framework-less) version of the application available at this URL: <a href="http://localhost:8400/contacts/Contacts/Contacts.html">http://localhost:8400/contacts/Contacts/Contacts.html</a></></p>
<h2>Importing the projects in Flash Builder 4</h2>
<ol>
<li>In Flash Builder 4, click <strong>File > Import > General > Existing Projects into Workspace</strong>.</li>
<li>Specify <strong>contacts/projects</strong> as the root directory and click finish.</li>
<li>Explore the projects: Contacts is the Flex project for the plain version of the application, ContactsParsley is the version discussed in this article, and java-testdrive is the Java project for the server-side classes.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2010/05/using-the-flash-builder-4-data-centric-features-with-parsley-and-other-frameworks/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Model Driven Development with Flex 4 and LCDS 3 Screencast</title>
		<link>http://coenraets.org/blog/2009/09/flex4mdd/</link>
		<comments>http://coenraets.org/blog/2009/09/flex4mdd/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 13:35:47 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Flex]]></category>
		<category><![CDATA[Flex4]]></category>
		<category><![CDATA[LCDS]]></category>
		<category><![CDATA[MDD]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=125</guid>
		<description><![CDATA[I recently presented a new &#8220;Model Driven Development with Flex 4&#8243; session at a few conferences and Flash Camps, so I figured I would record a screencast of the demo app for people who did not attend. If you saw a previous version of this demo, this screencast is still worth watching because I&#8217;m using [...]]]></description>
			<content:encoded><![CDATA[<p>I recently presented a new &#8220;Model Driven Development with Flex 4&#8243; session at a few conferences and Flash Camps, so I figured I would record a screencast of the demo app for people who did not attend. If you saw a previous version of this demo, this screencast is still worth watching because I&#8217;m using the latest daily builds of Flash Builder 4 and LCDS 3 and we made really good progress!</p>
<p>You can watch it in the player below, however I recommend you click <a href="http://www.vimeo.com/6612999">here</a> to watch it in HD (go full screen for a better viewing experience. Also make sure HD is on).   </p>
<p><object width="640" height="496"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=6612999&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=1&amp;color=00ADEF&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=6612999&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=0&amp;show_portrait=1&amp;color=00ADEF&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="496"></embed></object></p>
<p>A few things I&#8217;m not mentioning in the demo:</p>
<ul>
<li>Value objects and service stubs are automatically generated based on the model</li>
<li>Data persistence occurs through JPA/Hibernate, but you don&#8217;t have to know that if you just want it to work</li>
<li>Code generation of form is template-based (you can modify the existing template or create new ones)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/09/flex4mdd/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Building the Server-Side of the &#8220;Tour de Flex&#8221; Real-Time Dashboard</title>
		<link>http://coenraets.org/blog/2009/05/tdfdashboard/</link>
		<comments>http://coenraets.org/blog/2009/05/tdfdashboard/#comments</comments>
		<pubDate>Tue, 26 May 2009 15:18:30 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[BlazeDS]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[LCDS]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=121</guid>
		<description><![CDATA[Greg Wilson and Damien Mandrioli are also blogging about the new Tour de Flex real time dashboard today. Greg is the inspiration behind everything “Tour de Flex”, including the idea of the dashboard. He has the story behind the genesis of this project on his blog. Damien (from IBM/ILOG) did a fantastic job at building [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://coenraets.org/downloads/tdfdashboard.png" alt="" /></p>
<p><a href="http://gregsramblings.com/">Greg Wilson</a> and <a href="http://blogs.ilog.com/elixir/author/dmandrioli/">Damien Mandrioli</a> are also blogging about the new Tour de Flex real time dashboard today. Greg is the inspiration behind everything “Tour de Flex”, including the idea of the dashboard. He has the story behind the genesis of this project <a href="http://gregsramblings.com/2009/05/26/tour-de-flex-live-planetary-dashboard">on his blog</a>. Damien (from IBM/ILOG) did a fantastic job at building the client-side of the dashboard using the very cool <a href="http://www.ilog.com/products/ilogelixir/">ILOG Elixir components</a>, and he <a href="http://blogs.ilog.com/elixir/2009/05/26/tdfdashboard/">walks you through the details</a> on his blog.</p>
<p>My contribution to the project is the &#8220;real-time messaging&#8221; infrastructure. I provide the details below.</p>
<p>First the overall workflow&#8230;</p>
<p><img src="http://coenraets.org/downloads/tdfdashboardflow.png" alt="" /></p>
<p>The reason we are combining PHP and Java in this workflow is mostly historical. In the initial version of Tour de Flex, there was no Java involved: Greg was persisting loaded samples data (sample id and timestamp) directly from his PHP page. We later added LiveCycle Data Services to the picture to support the data push requirement of the dashboard, and we took the opportunity to move some code (such as the database persistence) from PHP to Java. Note that we are using LCDS for the performance and scalability of its high-end channels, but the application could also be deployed on BlazeDS.</p>
<p>A more straightforward architecture would be for the client to communicate directly with LCDS. For example, the client could invoke a remote object that would directly publish the loaded sample data (sample id and geolocation of the client) to the message destination. Alternatively, the client could use a Producer object to directly publish the message to the destination. Because some logic (such as geolocating the IP address and persisting the data) has to be executed at the server-side before routing the messages to the subscribed clients, you would have to write a custom message adapter if you used this approach.</p>
<p>We will probably streamline the workflow with one of these two approaches in the future, but in the meantime here is the source code for the servlet (logging and non-essential code removed for brevity):</p>
<pre class="brush: java;">
package com.adobe.tdf;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.maxmind.geoip.Location;
import com.maxmind.geoip.LookupService;

import flex.messaging.MessageBroker;
import flex.messaging.messages.AsyncMessage;
import flex.messaging.util.UUIDUtils;

public class TDFServlet extends HttpServlet {

	// Unique clientID for the message service
	private String clientID = UUIDUtils.createUUID();

	// The geocoding service
	protected LookupService lookupService;

	// A DAO to store sample requests in a database
	protected SampleRequestDAO dao = new SampleRequestDAO();

	// The LCDS message broker
	protected MessageBroker messageBroker;

	// The LCDS messaging destination where real time sample requests information is pushed
	protected String destination; 

	public void init() throws ServletException {

		ServletConfig config = getServletConfig();
		destination = config.getInitParameter(&quot;messaging.destination.name&quot;);
		String path = config.getInitParameter(&quot;geocoding.database.path&quot;);
		try {
			// Load the geocoding database in init() to make sure we load it only once
			lookupService = new LookupService(path, LookupService.GEOIP_MEMORY_CACHE);
		} catch (IOException e) {
			// We swallow the exception here. If the database is not available, the feed
			// will still work but won't provide the location info.
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		if (messageBroker == null)
		{
			messageBroker = MessageBroker.getMessageBroker(null);
		}

		SampleRequest sampleRequest = new SampleRequest();

		try {
			sampleRequest.setSampleId(Integer.parseInt(request.getParameter(&quot;sampleId&quot;)));
		} catch (Exception e) {
			String message = &quot;A valid sampleId is required to process this request&quot;;
			throw new RuntimeException(message);
		}

		sampleRequest.setTimestamp(new Date());

		String ipAddress = request.getParameter(&quot;ipAddress&quot;);

		// Geolocate the IP address and add the info to the message
		if (lookupService != null &amp;&amp; ipAddress != null)
		{
	                Location location = lookupService.getLocation(ipAddress);
			if (location != null)
			{
				sampleRequest.setLatitude(location.latitude);
				sampleRequest.setLongitude(location.longitude);
				sampleRequest.setCountry(location.countryCode);
				sampleRequest.setCity(location.city);
			}
		}

		try {
			dao.create(sampleRequest, ipAddress);
		} catch (RuntimeException e) {

		}

		String subtopic = request.getParameter(&quot;subtopic&quot;);
		if (subtopic == null) subtopic = &quot;flex&quot;;

		// Publish the message to specified destination and subtopic.
		AsyncMessage msg = new AsyncMessage();
		msg.setDestination(destination);
		msg.setHeader(&quot;DSSubtopic&quot;, subtopic);
		msg.setClientId(clientID);
		msg.setMessageId(UUIDUtils.createUUID());
		msg.setTimestamp(System.currentTimeMillis());
		msg.setBody(sampleRequest);
		messageBroker.routeMessageToService(msg, null);

		PrintWriter out = response.getWriter();
	        out.println(&quot;&lt;html&gt;&lt;body&gt;ok&lt;/body&gt;&lt;/html&gt;&quot;);

	}

}
</pre>
<p>The servlet is responsible for three things:</p>
<ol>
<li>Geolocate the IP address of the client requesting the sample. We currently use the MaxMind Geolocation API. The API is straightforward and the results seem pretty accurate.</li>
<li>Save the information about the loaded sample in a database. We keep track of historical data to be able to support future data visualization projects.</li>
<li>Publish the data about the loaded sample to a message destination. The servlet uses the Message Service Java API to directly push messages to the Flex destination (lines 97 to 104). Note that the same API exists for ColdFusion, so CF developers could use a CF page instead of this servlet to push messages to the client.</li>
</ol>
<h3>Channels</h3>
<p>The messaging destination is set up to support different communication channels: RTMP, long polling, and regular polling. The client-side developer can decide which channel to use to communicate with the server. For example, if you wanted to use RTMP as the primary channel, fall back to long polling if the RTMP connection fails, and fall back to regular polling if the long polling connection fails you could set up your client-side ChannelSet as follows:</p>
<pre class="brush: xml;">
&lt;mx:ChannelSet id=&quot;channelSet&quot;&gt;
	&lt;mx:RTMPChannel id=&quot;rtmp&quot; url=&quot;rtmp://hostname:2037&quot;/&gt;
	&lt;mx:AMFChannel url=&quot;http://hostname/context/messagebroker/amflongpolling&quot;/&gt;
	&lt;mx:AMFChannel url=&quot;http://hostname/context/messagebroker/amfpolling&quot;/&gt;
&lt;/mx:ChannelSet&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/05/tdfdashboard/feed/</wfw:commentRss>
		<slash:comments>52</slash:comments>
		</item>
		<item>
		<title>New Test Drive for Spring BlazeDS Integration RC1</title>
		<link>http://coenraets.org/blog/2009/05/new-test-drive-for-spring-blazeds-integration-rc1/</link>
		<comments>http://coenraets.org/blog/2009/05/new-test-drive-for-spring-blazeds-integration-rc1/#comments</comments>
		<pubDate>Fri, 08 May 2009 20:34:55 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[BlazeDS]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[LCDS]]></category>
		<category><![CDATA[Spring]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=117</guid>
		<description><![CDATA[UPDATE: An updated version of this Test Drive is available here SpringSource just released the RC1 build for the Spring / BlazeDS integration project. The key new feature in RC1 is the integration of the BlazeDS Message Service. I updated my Spring BlazeDS Integration Test Drive to showcase the messaging integration. In addition to Remoting [...]]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE: An updated version of this Test Drive is available <a href="http://coenraets.org/blog/2009/05/new-update-to-the-spring-blazeds-integration-test-drive/">here</a></strong></p>
<p>SpringSource just released the RC1 build for the <a href="http://www.springsource.org/spring-flex">Spring / BlazeDS integration project</a>. The key new feature in RC1 is the integration of the BlazeDS Message Service.</p>
<p>I updated my Spring BlazeDS Integration Test Drive to showcase the messaging integration.</p>
<p>In addition to Remoting and Security samples, the Test Drive now includes the following Messaging samples:</p>
<ul>
<li><strong>Chat</strong>: Messaging basics</li>
<li><strong>Simple Data Push</strong>: A simple data push example</li>
<li><strong>Traderdesktop</strong>: A more sophisticated data push example showing how to use subtopics</li>
<li><strong>JMS Chat</strong>: A chat application using a JMS topic and exchanging messages with a Swing-based client</li>
<li><strong>Collaboration</strong>: An example showing how to use messaging to remotely drive another client&#8217;s application</li>
</ul>
<h3>Installation Instructions:</h3>
<ol>
<li>Download the Spring / Flex TestDrive here: <a href="http://coenraets.org/downloads/spring-flex-testdrive-RC1.zip">http://coenraets.org/downloads/spring-flex-testdrive-RC1.zip</a></li>
<li>Unzip it in your root directory</li>
<li>Navigate to /spring-flex-testdrive/tomcat/bin and start Tomcat (for instance: catalina run)</li>
<li>Open a browser and access http://localhost:8080</li>
<li>Follow the instructions</li>
</ol>
<p>As always, I&#8217;d love to hear your feedback and your ideas to improve this Test Drive.</p>
<p>I will probably have another version next week with a couple of additional samples and more documentation for the Message Service, but I already wanted to make this version available to allow you to experiment RC1 samples.</p>
<p>Christophe</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/05/new-test-drive-for-spring-blazeds-integration-rc1/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Externalizing Service Configuration using BlazeDS and LCDS</title>
		<link>http://coenraets.org/blog/2009/03/externalizing-service-configuration-using-blazeds-and-lcds/</link>
		<comments>http://coenraets.org/blog/2009/03/externalizing-service-configuration-using-blazeds-and-lcds/#comments</comments>
		<pubDate>Mon, 23 Mar 2009 17:57:06 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Air]]></category>
		<category><![CDATA[BlazeDS]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[LCDS]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=113</guid>
		<description><![CDATA[A typical source of confusion when developers start working with RemoteObject or other BlazeDS/LCDS related classes is where and most importantly *when* the configuration of your services is being read. The question often arises after an application stops working when you move it to another server. This is one of the most frequently asked questions [...]]]></description>
			<content:encoded><![CDATA[<p>A typical source of confusion when developers start working with RemoteObject or other BlazeDS/LCDS related classes is where and most importantly *when* the configuration of your services is being read.</p>
<p>The question often arises after an application stops working when you move it to another server. This is one of the most frequently asked questions related to BlazeDS and LCDS, so I figured I would answer it here. There is nothing really new in this post, but hopefully this will be a good point of reference.</p>
<p>When you create a new BlazeDS or LCDS project in Flex Builder, you are typically told to select J2EE as the “Application Server Type” and then check “use remote object access service”. This adds a compiler argument pointing to the location of your services-config.xml. If you check the Flex Compiler properties of your Flex Builder project, you’ll see something like this:</p>
<p>-services &#8220;c:\blazeds\tomcat\webapps\samples\WEB-INF\flex\services-config.xml&#8221;</p>
<p>When you then compile your application, the required values of services-config.xml are baked into the SWF. In other words, services-config.xml is read at <strong>compile time</strong> and not at runtime as you may have thought intuitively. To abstract things a little bit, you can use tokens such as {server.name}, {server.port}, and {context.root} in services-config.xml. However, {context.root} is still substituted at compile time, while {server.name} and {server.port} are replaced at runtime using the server name and port number of the server the SWF was loaded from (which is why you can&#8217;t use these tokens for AIR applications).</p>
<p><span id="more-113"></span></p>
<p>Fortunately, the Flex SDK provides an API that allows you to configure your channels at runtime and entirely externalize your services configuration from your code (you definitely don&#8217;t want to recompile your application when you move it to another server).  At a high level, it works like this:</p>
<pre class="brush: jscript;">
var channelSet:ChannelSet = new ChannelSet();
var channel:AMFChannel = new AMFChannel(&quot;my-amf&quot;, &quot;http://localhost:8400/lcds-samples/messagebroker/amf&quot;);
channelSet.addChannel(channel);
remoteObject.channelSet = channelSet;
</pre>
<p>This is still not what we want because the endpoint URL is still hardcoded in the application. At least in this case it’s obvious that it is. So, the last step is to pass that endpoint URL value at runtime. There are a number of ways you can pass values to a SWF at runtime (flashvars, page parameters, etc). The approach I usually use is to read a configuration file using HTTPService at application startup. That configuration file includes (among other things) the information I need to programmatically create my channel set at runtime. Here is a basic implementation:
</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot;
	applicationComplete=&quot;configSrv.send()&quot;&gt;

	&lt;mx:Script&gt;
	&lt;![CDATA[

	import mx.controls.Alert;
	import mx.messaging.channels.AMFChannel;
	import mx.messaging.ChannelSet;
	import mx.rpc.events.ResultEvent;

	private var channelSet:ChannelSet;

	private function configResultHandler(event:ResultEvent):void
	{
		var xml:XML = event.result as XML;
		var amfEndpoint:String = &quot;&quot; + xml..channel.(@id==&quot;amf&quot;).@endpoint;
		if (amfEndpoint == &quot;&quot;)
		{
			Alert.show(&quot;amf channel not configured&quot;, &quot;Error&quot;);
		}
		else
		{
			channelSet = new ChannelSet();
			var channel:AMFChannel = new AMFChannel(&quot;my-amf&quot;, amfEndpoint);
			channelSet.addChannel(channel);
			ro.channelSet = channelSet;
			ro.getProducts();
		}
	}

	]]&gt;
	&lt;/mx:Script&gt;

	&lt;mx:HTTPService id=&quot;configSrv&quot; url=&quot;config.xml&quot; resultFormat=&quot;e4x&quot; result=&quot;configResultHandler(event)&quot;/&gt;

	&lt;mx:RemoteObject id=&quot;ro&quot; destination=&quot;product&quot;/&gt;

	&lt;mx:DataGrid dataProvider=&quot;{ro.getProducts.lastResult}&quot; width=&quot;100%&quot; height=&quot;100%&quot;/&gt;

&lt;/mx:Application&gt;
</pre>
<p>The configuration file looks like this:</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;config&gt;
	&lt;channels&gt;
		&lt;channel id=&quot;amf&quot; endpoint=&quot;http://localhost:8400/lcds-samples/messagebroker/amf&quot;/&gt;
	&lt;/channels&gt;
&lt;/config&gt;
</pre>
<p>NOTE: With that type of runtime configuration in place, you can create plain Flex Builder projects (you can select None as the application server type).</p>
<p>This particular example is not extremely flexible. It assumes I will always work with an AMF channel and therefore the only thing my application needs to know at runtime is the AMF channel endpoint URL. For RemoteObject that’s a fairly safe bet, however for messaging-related classes (Producer and Consumer), you may also want to externalize the type of channel you use (AMF Polling, long polling, streaming, RTMP, etc.). Before you start creating that kind of dynamic configuration system, you may want to take a look at the <a href="http://www.pranaframework.org/">Flex ActionScript framework</a> that <a href="http://www.herrodius.com/blog/158">does that</a> very well.</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/03/externalizing-service-configuration-using-blazeds-and-lcds/feed/</wfw:commentRss>
		<slash:comments>28</slash:comments>
		</item>
		<item>
		<title>Sample application using the Swiz Framework and BlazeDS</title>
		<link>http://coenraets.org/blog/2009/02/sample-application-using-the-swiz-framework-and-blazeds/</link>
		<comments>http://coenraets.org/blog/2009/02/sample-application-using-the-swiz-framework-and-blazeds/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 18:30:28 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Air]]></category>
		<category><![CDATA[BlazeDS]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[LCDS]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=101</guid>
		<description><![CDATA[There have been a lot of discussions around Flex Frameworks lately. Tony Hillerson has an interesting series here: 1 2 3 4 5 6 A relative newcomer on the list is Swiz, the work of Chris Scott. I figured I would give it a try, and create a Swiz version of the inSync application that [...]]]></description>
			<content:encoded><![CDATA[<p>There have been a lot of discussions around Flex Frameworks lately. Tony Hillerson has an interesting series here: <a href="http://www.insideria.com/2008/12/frameworkquest-2008-introducti.html">1</a> <a href="http://www.insideria.com/2008/12/frameworkquest-2008-part-2-get.html">2</a> <a href="http://www.insideria.com/2008/12/frameworkquest-2008-part-3-fra.html">3</a> <a href="http://www.insideria.com/2008/12/frameworkquest-2008-part-4-ioc.html">4</a> <a href="http://www.insideria.com/2008/12/frameworkquest-2008-part-5-mat.html">5</a> <a href="http://www.insideria.com/2009/01/frameworkquest-2008-part-6-the.html">6</a></p>
<p>A relative newcomer on the list is <a href="http://code.google.com/p/swizframework/">Swiz</a>, the work of <a href="http://cdscott.blogspot.com/">Chris Scott</a>. I figured I would give it a try, and create a Swiz version of the inSync application that I often use to try out and demonstrate different features and techniques in Flex and Adobe AIR. This is not an endorsement of Swiz over other frameworks. I simply wanted to share the sample application I built as part of my own research as a (neutral like a Swiss) Evangelist.</p>
<p><img src="http://coenraets.org/downloads/insync-swiz/insync-swiz.png"/></p>
<p><a href="http://coenraets.org/downloads/insync-swiz/srcview/index.html">View the source code</a>.</p>
<p><span id="more-101"></span></p>
<h3>Application Highlights:</h3>
<p>At his core, Swiz is a simple inversion of control framework. Using an IoC framework, the components of your application (for example, Views) don’t instantiate or even look up their dependencies (the objects they work with). The framework injects those dependencies when the components are created (hence the term “Dependency Injection” also used to describe this approach). The result is looser coupling and more reusable components. The components managed by the Swiz IoC framework are called beans.</p>
<h3>1. Defining your beans</h3>
<p>The beans of the inSync applications are defined in Beans.mxml:</p>
<pre class="brush: xml;">
&lt;BeanLoader xmlns=&quot;org.swizframework.util.*&quot; xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; xmlns:controllers=&quot;insync.controllers.*&quot;&gt;

    &lt;DynamicChannelSet id=&quot;myAmfChannel&quot;&gt;
		&lt;serverPort&gt;8400&lt;/serverPort&gt;
		&lt;contextRoot&gt;/lcds-samples&lt;/contextRoot&gt;
    &lt;/DynamicChannelSet&gt;

    &lt;mx:RemoteObject id=&quot;contactService&quot; destination=&quot;contacts&quot; channelSet=&quot;{myAmfChannel}&quot;/&gt;

    &lt;controllers:ContactController id=&quot;contactController&quot;/&gt;

&lt;/BeanLoader&gt;
</pre>
<h3>2. Bootstrapping Swiz</h3>
<p>You bootstrap Swiz in the preinitialize event of the application. You can have multiple Beans configuration classes. You pass your configuration classes in an array as an argument of the loadBeans function. In inSync, we have only one configuration class (Beans.mxml).</p>
<pre class="brush: jscript;">
Swiz.loadBeans( [Beans] );
</pre>
<h3>3. Injecting dependencies</h3>
<p>Swiz uses the [Autowire] custom metadata to inject beans into other beans and views.<br />
In inSync, the contactService RemoteObject is injected into ContactController.as as follows:</p>
<pre class="brush: jscript;">
[Autowire(bean=&quot;contactService&quot;)]
public var contactService:RemoteObject;
</pre>
<p>… and contactController is injected in the Views. For example, in ContactForm.mxml:</p>
<pre class="brush: jscript;">
[Autowire(bean=&quot;contactController&quot;)]
public var controller:IContactController;
</pre>
<p>Because we use an interface, the View is not coupled to a specific implementation of the controller. If you don’t like to have a reference to the controller in your view, keep reading…</p>
<h3>4. Dynamic Mediators</h3>
<p>Swiz is an IoC framework. Beyond that, it doesn’t force you to use any specific design pattern. So, if you don’t like to have a controller in your view, you can, for example, set up the view to dispatch events instead. For example, in the save() function of ContactForm.mxml, you would replace:</p>
<pre class="brush: jscript;">
controller.save(contact);
</pre>
<p>with:</p>
<pre class="brush: jscript;">
Swiz.dispatchEvent(ContactEvent.SAVE, contact);
</pre>
<p>You could then listen to this event in some &#8220;mediator&#8221; class using Swiz.addEventListener(ContactEvent.UPDATE, someHandler), but the dynamic mediator feature of Swiz allows you to automate this process. For example, you could annotate the save() function of the ContactController class as follows:</p>
<pre class="brush: jscript;">
[Mediate(event=&quot;ContactEvent.SAVE&quot;, properties=&quot;contact&quot;)]
public function save(contact:Contact):void
{
	executeServiceCall(contactService.save(contact), save_result, null, [contact]);
}
</pre>
<p>Swiz will automatically set up an event listener, invoke the annotated method when the event is dispatched, and pass the specified event properties (in this case: &#8220;contact&#8221;) as the function parameters.</p>
<h3>5. Prototypes</h3>
<p>By default, components defined in your Beans configuration classes are singletons. In other words, the same instance of a Bean gets injected everytime it is autowired. In some situations, you may want to inject a new instance of a Bean everytime it is autowired. For example, if you open multiple instances of the same View, you may decide you need one controller per view. Prototypes allow you to define non-singleton Beans in your Beans configuration class using the following syntax:</p>
<p>More on prototypes <a href="http://cdscott.blogspot.com/2009/01/more-swiz-features-or-swiz-005-part-2.html">here</a>.</p>
<pre class="brush: xml;">
&lt;factory:Prototype xmlns:factory=&quot;org.swizframework.factory.*&quot;
        id=&quot;contactController&quot;
        className=&quot;insync.controllers.ContactController&quot;/&gt;
</pre>
<p></p>
<h3>Installation instructions:</h3>
<ol>
<li>Install the <a href="http://opensource.adobe.com/blazeds">BlazeDS turnkey server</a>. (To be clear: you don’t have to use BlazeDS to use Swiz… That’s just the sample I wanted to build.)</li>
<li>Download <a href="http://coenraets.org/downloads/insync-swiz/srcview/insync-swiz.zip">insync-swiz.zip</a>, and unzip it on your local file system.</li>
<li>Copy insync-swiz/java/classes/insync to blazeds/tomcat/webapps/samples/WEB-INF/classes/insync.</li>
<li>Add the following destination to blazeds/tomcat/webapps/samples/WEB-INF/flex/remoting-config.xml:</li>
<p><pre class="brush: xml;">
&lt;destination id=&quot;contacts&quot;&gt;
        &lt;properties&gt;
            &lt;source&gt;insync.dao.ContactDAO&lt;/source&gt;
            &lt;scope&gt;application&lt;/scope&gt;
        &lt;/properties&gt;
&lt;/destination&gt;
</pre>
</p>
<li>Copy insync-swiz/sampledb/insync to blazeds/sampledb/insync</li>
<li>Edit server.properties in blazeds/sampledb, and modify the file as follows to add the insync database to the startup procedure.
<p><pre class="brush: plain;">
server.database.0=file:flexdemodb/flexdemodb
server.dbname.0=flexdemodb
server.database.1=file:insync/insync
server.dbname.1=insync
server.port=9002
server.silent=true
server.trace=false
</pre>
</p>
</li>
<li>Start the database (startdb.bat or startdb.sh)</li>
<li>Start BlazeDS</li>
<li>In Flex Builder, create a new Flex project called insync-swiz. You don’t have to select any “Application server type”. </li>
<li>Copy the Swiz swc and the flexlib swc (used for the SuperTabNavigator) from insync-swiz/flex/lib to the lib directory of your project</li>
<li>Copy the files and folders from insync-swiz/flex/src to the src directory of your project</li>
<li>Open Beans.mxml and make sure the serverPort and contextRoot properties in DynamicChannelSet match your server setup.</li>
<li>Run the application</li>
</ol>
<h3>Summary</h3>
<p>Swiz was easy and enjoyable to work with. It is also non intrusive and definitely introduces some interesting ideas. A few lingering questions I didn’t have time to investigate&#8230;</p>
<ul>
<li>Swiz relies on introspection (describeType) to find its custom metadata in the objects added to the display list (with the exception of classes in the flash.* and mx.* packages). This has a performance impact. I’m not exactly sure how much of an impact it would have in real life apps yet…</li>
<li>How well does Swiz work with Modules or Marshall Plan subapplications?</li>
</ul>
<p>If you are looking for more information, check out the following resources:</p>
<ul>
<li><a href="http://link.brightcove.com/services/link/bcpid1753161885/bctid1738803894">Chris Scott’s presentation at Flex 360</a></li>
<li><a href="http://code.google.com/p/swizframework/wiki/GettingStarted">Getting Started</a></li>
<li><a href="http://cdscott.blogspot.com/">Chris Scott’s blog</a></li>
<li><a href="http://soenkerohde.com/2008/09/swiz-framework-brutally-simple/">Sönke Rohde’s blog</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2009/02/sample-application-using-the-swiz-framework-and-blazeds/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>My MAX LCDS/BlazeDS Sessions Materials Available</title>
		<link>http://coenraets.org/blog/2008/11/my-max-lcdsblazeds-sessions-materials-available/</link>
		<comments>http://coenraets.org/blog/2008/11/my-max-lcdsblazeds-sessions-materials-available/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 20:28:11 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Air]]></category>
		<category><![CDATA[BlazeDS]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[LCDS]]></category>
		<category><![CDATA[MAX]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=89</guid>
		<description><![CDATA[Many of you have asked me for the materials I used in my LCDS/BlazeDS hands-on sessions at MAX. Here are the links: Lab instructions PDF (Powering Flex Applications with BlazeDS and Data Services) Lab files (including final solutions) If you didn&#8217;t have a chance to attend, you should be able to use this as a [...]]]></description>
			<content:encoded><![CDATA[<p>Many of you have asked me for the materials I used in my LCDS/BlazeDS  hands-on sessions at MAX. </p>
<p>Here are the links:</p>
<ul>
<li><a href="http://coenraets.org/downloads/max2008/flex-dataservices-tutorial.pdf">Lab instructions PDF</a> (Powering Flex Applications with BlazeDS and Data Services)</li>
<li><a href="http://coenraets.org/downloads/max2008/flex-dataservices-tutorial.zip">Lab files (including final solutions)</a></li>
</ul>
<p>If you didn&#8217;t have a chance to attend, you should be able to use this as a BlazeDS/LCDS tutorial as well.</p>
<p>It was great to see all of you at MAX. I hope to see you next year in Los Angeles.</p>
<p>Christophe</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2008/11/my-max-lcdsblazeds-sessions-materials-available/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Sneak Peek of LiveCycle Data Services &#8220;Next&#8221; Tomorrow at MAX</title>
		<link>http://coenraets.org/blog/2008/11/sneak-peak-of-livecycle-data-services-next-tomorrow-at-max/</link>
		<comments>http://coenraets.org/blog/2008/11/sneak-peak-of-livecycle-data-services-next-tomorrow-at-max/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 07:24:41 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[BlazeDS]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[LCDS]]></category>
		<category><![CDATA[LiveCycle Data Services]]></category>
		<category><![CDATA[MAX]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=87</guid>
		<description><![CDATA[I will demonstrate some new and really exciting features of LiveCycle Data Services &#8220;Next&#8221; tomorrow (Monday), as part of my session called &#8220;Introduction to BlazeDS and LiveCycle Data Services ES&#8221;. I hope to see you there if you are interested in Data Services for Flex. Introduction to BlazeDS and LiveCycle Data Services ES Moscone West [...]]]></description>
			<content:encoded><![CDATA[<p>I will demonstrate some new and really exciting features of LiveCycle Data Services &#8220;Next&#8221; tomorrow (Monday), as part of my session called &#8220;Introduction to BlazeDS and LiveCycle Data Services ES&#8221;. I hope to see you there if you are interested in Data Services for Flex.</p>
<p>Introduction to BlazeDS and LiveCycle Data Services ES<br />
Moscone West 2007<br />
5:00pm to 6:00pm</p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2008/11/sneak-peak-of-livecycle-data-services-next-tomorrow-at-max/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Google Maps Collaboration Using Google&#8217;s New ActionScript API, Flex, and BlazeDS</title>
		<link>http://coenraets.org/blog/2008/05/google-maps-collaboration-using-googles-new-actionscript-api-and-blazeds/</link>
		<comments>http://coenraets.org/blog/2008/05/google-maps-collaboration-using-googles-new-actionscript-api-and-blazeds/#comments</comments>
		<pubDate>Fri, 23 May 2008 20:00:06 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[BlazeDS]]></category>
		<category><![CDATA[Collaboration]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[LCDS]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=81</guid>
		<description><![CDATA[Google recently released the Google Maps API for Flash. I took the opportunity to create a Google version of the MapRooms sample application I posted recently. MapRooms works like Chat Rooms. You can create a room, or join an existing one. In addition to chatting, MapRooms allows you to collaborate on a map: the application [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://coenraets.org/apps/gmaprooms/gmaprooms.gif"/><br />
Google recently released the <a href="http://code.google.com/apis/maps/documentation/flash/">Google Maps API for Flash</a>. I took the opportunity to create a Google version of the MapRooms sample application <a href="http://coenraets.org/blog/2008/04/yahoo-maps-collaboration-using-flex-and-blazeds/">I posted recently</a>. MapRooms works like Chat Rooms. You can create a room, or join an existing one. In addition to chatting, MapRooms allows you to collaborate on a map: the application leverages the real time capabilities of BlazeDS or LCDS to provide map synchronization between users in the room, and allow you to &#8220;whiteboard&#8221; on top of a map.<br />
<span id="more-81"></span></p>
<h3>Testing the hosted version</h3>
<p>Disclaimer: I&#8217;m currently hosting the application on the server I use to host this blog (basic PHP and Tomcat hosting plan). I don&#8217;t know much about the characteristics of my server, but I&#8217;m probably sharing it with a few dozens of other domains and the resources allocated to me are obviously limited in that shared environment. This is clearly not the ideal environment to host a potentially large scale real time application and I&#8217;m investigating other hosting solutions. In the meantime, if you experience difficulties running the app, you can install it locally using the instructions provided below (in &#8220;Local installation instructions&#8221;). The hosted version tries to connect using RTMP by default (available only as part of LCDS) and falls back to &#8220;long AMF polling&#8221; or regular AMF polling if the RTMP connection fails.</p>
<ol>
<li>Access <a href="http://coenraets.org/apps/gmaprooms/gmaprooms.html">http://coenraets.org/apps/gmaprooms/gmaprooms.html</a> on two different machines or in two browser windows on the same machine.</li>
<li>Make sure you logon with two different user names and <strong>the same room name</strong>.</li>
<li>Move the map in one browser and notice that the position of the map is synchronized in the other browser.</li>
<li>You can also search an address in one browser and the resulting map position will appear in the two browsers.</li>
<li>The zoom level and the map type are also synchronized between users.</li>
<li>Click the &#8220;Whiteboard&#8221; button in one browser, pick a color to draw on the map (upper left corner), and start drawing.</li>
</ol>
<p>Note: you can right-click the application and select View Source or click <a href="http://coenraets.org/apps/gmaprooms/srcview/index.html">here</a> to see the source code of the application.</p>
<h3>Local installation instructions:</h3>
<ol>
<li>Install BlazeDS. You can download the BlazeDS turnkey server (a version of Tomcat with BlazeDS preinstalled) <a href="http://opensource.adobe.com/wiki/display/blazeds/Release+Builds">here</a>.</li>
<li>Open {blazeds-install-dir}/tomcat/webapps/samples/WEB-INF/flex/services-config.xml and add an AMF long polling channel defined as follows:
<p><pre class="brush: xml;">
&lt;channel-definition id=&quot;my-longpolling-amf&quot; class=&quot;mx.messaging.channels.AMFChannel&quot;&gt;
	&lt;endpoint url=&quot;http://{server.name}:{server.port}/{context.root}/messagebroker/amflongpolling&quot; class=&quot;flex.messaging.endpoints.AMFEndpoint&quot;/&gt;
	&lt;properties&gt;
		&lt;polling-enabled&gt;true&lt;/polling-enabled&gt;
		&lt;polling-interval-seconds&gt;5&lt;/polling-interval-seconds&gt;
		&lt;wait-interval-millis&gt;60000&lt;/wait-interval-millis&gt;
		&lt;client-wait-interval-millis&gt;1&lt;/client-wait-interval-millis&gt;
		&lt;max-waiting-poll-requests&gt;200&lt;/max-waiting-poll-requests&gt;
	&lt;/properties&gt;
&lt;/channel-definition&gt;
</pre>
</p>
</li>
<li>Open WEB-INF/messaging-config.xml and add the following destination:
<p><pre class="brush: xml;">
&lt;destination id=&quot;gmaprooms&quot;&gt;
	&lt;properties&gt;
		&lt;server&gt;
			&lt;allow-subtopics&gt;true&lt;/allow-subtopics&gt;
			&lt;subtopic-separator&gt;.&lt;/subtopic-separator&gt;
		&lt;/server&gt;
	&lt;/properties&gt;
	&lt;channels&gt;
		&lt;channel ref=&quot;my-longpolling-amf&quot;/&gt;
		&lt;channel ref=&quot;my-polling-amf&quot;/&gt;
	&lt;/channels&gt;
&lt;/destination&gt;
</pre>
</p>
</li>
<li>(Re)start the BlazeDS turnkey server.</li>
<li>Download the source code of the Google Maps Application <a href="http://coenraets.org/apps/gmaprooms/srcview/gmaprooms.zip">here</a>.</li>
<li>Create a Flex Builder project for the Flex application (gmaprooms). <strong>Make sure you configure your Flex Builder project to work with BlazeDS.</strong> To read instructions on how to set up a Flex Builder project that works with BlazeDS, make sure your BlazeDS turnkey server is started, and click <a href="http://localhost:8400/samples/fb-project-setup.htm">here</a>.</li>
<li>Download the Google Maps ActionScript 3 API <a href="http://code.google.com/apis/maps/documentation/flash/">here</a>, and add the swc file in the libs folder of your project.</li>
<li>Get a Google Maps API key and assign it to map.key in the initMap() function in MapArea.mxml.</li>
<li>Compile the application.</li>
<li>Open the Flex application in two browser windows (to simulate two users in different locations) and test the application as described above (in &#8220;Testing the hosted version&#8221;).</li>
</ol>
<p><br/><br/></p>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2008/05/google-maps-collaboration-using-googles-new-actionscript-api-and-blazeds/feed/</wfw:commentRss>
		<slash:comments>69</slash:comments>
		</item>
		<item>
		<title>InSync: Automatic Offline Data Synchronization in AIR using LCDS 2.6</title>
		<link>http://coenraets.org/blog/2008/05/insync-automatic-offline-data-synchronization-in-air-using-lcds-26/</link>
		<comments>http://coenraets.org/blog/2008/05/insync-automatic-offline-data-synchronization-in-air-using-lcds-26/#comments</comments>
		<pubDate>Tue, 20 May 2008 03:31:15 +0000</pubDate>
		<dc:creator>Christophe Coenraets</dc:creator>
				<category><![CDATA[Air]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[LCDS]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Offline]]></category>

		<guid isPermaLink="false">http://coenraets.org/blog/?p=80</guid>
		<description><![CDATA[LCDS 2.6 allows you to build AIR applications with automatic offline data synchronization. This feature leverages the SQLite relational database system embedded in the AIR runtime, but the advantage is that the data synchronization process is entirely automatic: you don’t have to write SQL statements or synchronization logic to keep your local database in sync [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://coenraets.org/apps/insync/insync1.png" alt="" /></p>
<p><img src="http://coenraets.org/apps/insync/insync2.png" alt="" /></p>
<p>LCDS 2.6 allows you to build AIR applications with automatic offline data synchronization. This feature leverages the SQLite relational database system embedded in the AIR runtime, but the advantage is that the data synchronization process is entirely automatic: you don’t have to write SQL statements or synchronization logic to keep your local database in sync with your central database.</p>
<p>I have been getting a number of questions related to this feature, so I decided to build a sample application that demonstrates how it works.<br />
<span id="more-80"></span><br />
In this application the synchronization process is implicit. When you are online, the cache (a SQLite database) is automatically updated along with the server database to make sure the user can go offline with the latest data without explicitly triggering a synchronization process. When you are offline, the changes are saved in the local cache. If the network becomes available while working in the application, the application will detect the network status change and automatically synchronize data (send your offline changes to the server, and get changes made by other users while you were offline).</p>
<h3>Installation Instructions</h3>
<ol>
<li>If you haven&#8217;t already done so, <a href="http://labs.adobe.com/technologies/livecycle_dataservices2_6/">install LCDS 2.6</a>.</li>
<li>Unzip <a href="http://coenraets.org/apps/insync/insync.zip">insync.zip</a></li>
<li>Copy the content of the sampledb folder in the sampledb folder of your existing LCDS directory</li>
<li>Copy the content of the tomcat folder in the tomcat folder of your existing LCDS directory</li>
<li>Add the following destination to data-management-config.xml
<p><pre class="brush: xml;">
&lt;destination id=&quot;insync&quot;&gt;
    &lt;adapter ref=&quot;java-dao&quot; /&gt;
    &lt;properties&gt;
        &lt;source&gt;lcds.samples.contact.ContactAssembler&lt;/source&gt;
        &lt;scope&gt;application&lt;/scope&gt;
        &lt;metadata&gt;
            &lt;identity property=&quot;contactId&quot; undefined-value=&quot;0&quot;/&gt;
        &lt;/metadata&gt;
    &lt;/properties&gt;
&lt;/destination&gt;
</pre>
</p>
</li>
<li>Restart the sample database: run sampledb.bat (Windows) or sampledb.sh (Unix) in the sampledb directory</li>
<li>Restart your application server</li>
</ol>
<h3>Quick Tour</h3>
<ol>
<li>Install and run the AIR application. Notice the green light in the status bar indicating that the application is in online mode.
<p><div id="flashcontent7658" style="width:215px; height:180px;"><strong>Please upgrade your Flash Player</strong> This is the content that would be shown if the user does not have Flash Player 9.0.115 or higher installed.</div><script type="text/javascript">
<!-- // <![CDATA[
var so = new SWFObject("http://coenraets.org/blog/wp-content/plugins/air-badge/AIRInstallBadge.swf", "Badge", "215", "180", "9.0.115", "#FFFFFF");
so.useExpressInstall("http://coenraets.org/blog/wp-content/plugins/air-badge/expressinstall.swf");
so.addVariable("airversion", "1.0");
so.addVariable("appname", "sqliteadmin");
so.addVariable("appurl", "http://coenraets.org/apps/insync/insync.air");
so.addVariable("appid", "sqliteadmin");
so.addVariable("pubid", "");
so.addVariable("appversion", "v1.0");
so.addVariable("imageurl", "http://coenraets.org/apps/insync/insync1.png");
so.addVariable("appinstallarg", "installed from web");
so.addVariable("applauncharg", "launched from web");
so.addVariable("helpurl", "help.html");
so.addVariable("hidehelp", "true");
so.addVariable("skiptransition", "false");
so.addVariable("titlecolor", "#00AAFF");
so.addVariable("buttonlabelcolor", "#00AAFF");
so.addVariable("appnamecolor", "#00AAFF");
so.addVariable("str_err_airswf", "<u>Running locally?</u><br/><br/>The AIR proxy swf won't load properly when this is run from the local file system.");
so.write("flashcontent7658");
// ]]&gt; -->
</script>

</p>
</li>
<li>Double click a contact to view the contact details.</li>
<li>Modify the data in a few fields and click Save. Your server console indicates that the contact has been updated.</li>
<li>Click the + button in the application title bar. Enter a first name, last name, etc and click Save. Your server console indicates that the contact has been updated.</li>
<li>Shut down the server</li>
<li>Notice that the green light turns grey to indicate that the application is now working in offline mode.</li>
<li>Repeat steps 2 to 4 above: changes are saved locally. Notice that the offline status (not modified, created, or updated is displayed in the contact form (bottom left corner)</li>
<li>Restart the server.</li>
<li>The green light appears in that status bar as soon as the server is up and running. Notice that LCDS automatically detects the offline changes and sends them to the server.</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://coenraets.org/blog/2008/05/insync-automatic-offline-data-synchronization-in-air-using-lcds-26/feed/</wfw:commentRss>
		<slash:comments>60</slash:comments>
		</item>
	</channel>
</rss>
