<?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>Fusioncube &#187; frameworks</title>
	<atom:link href="http://www.fusioncube.net/index.php/category/development/frameworks/feed" rel="self" type="application/rss+xml" />
	<link>http://www.fusioncube.net</link>
	<description>The online journey of a technophile, by Steve Brownlee</description>
	<lastBuildDate>Wed, 01 Feb 2012 04:17:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>New AjaxCFCProxy class for Sencha ExtJS</title>
		<link>http://www.fusioncube.net/index.php/new-ajaxcfcproxy-class-for-sencha-extjs</link>
		<comments>http://www.fusioncube.net/index.php/new-ajaxcfcproxy-class-for-sencha-extjs#comments</comments>
		<pubDate>Fri, 15 Apr 2011 15:47:56 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[coldspring]]></category>
		<category><![CDATA[ExtJS]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[ajaxcfc]]></category>
		<category><![CDATA[ComboBox]]></category>
		<category><![CDATA[ext.data.store]]></category>
		<category><![CDATA[ext.form.combobox]]></category>
		<category><![CDATA[httpproxy]]></category>
		<category><![CDATA[memoryproxy]]></category>
		<category><![CDATA[Sencha]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/?p=1176</guid>
		<description><![CDATA[In my continued integration of ExtJS and ColdFusion, I've created a new DataProxy sub-class to utilize a predefined AJAX call rather than a URL to a separate page.]]></description>
			<content:encoded><![CDATA[<p>Related Article(s): <a href="http://www.fusioncube.net/index.php/porting-my-coldspring-enabled-ajaxcfc-code-to-extjs">AjaxCFC ported to ExtJS</a></p>
<p>My integration of ExtJS, ajaxCFC and ColdFusion continues.</p>
<p>Note: This is for version 3.3.1. I&#8217;ve also been happily playing around with version 4, but until it&#8217;s officially released, I must continue building with 3.3.1.</p>
<p>Anyway, here&#8217;s what I was trying to solve. When I want to allow users to serach for items from a <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.form.ComboBox" target="_blank">ComboBox</a>, I configure a store, and inside the store, I configure an <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.HttpProxy" target="_blank">Ext.data.HttpProxy</a> to hit a separate ColdFusion page that performs a query and returns the results.</p>
<h3>Standard HttpProxy Method</h3>
<pre class="brush: jscript; title: ; notranslate">
var WidgetStore = new Ext.data.Store({
    proxy: new Ext.data.HttpProxy({
        url: 'liveQueries/widgets.cfm'
    }),
    reader: new Ext.data.JsonReader({
        root: 'data',
        totalProperty:'totalRecords'
    }, Widget)
});
</pre>
<h3>ColdFusion &#8216;Live&#8217; Query</h3>
<pre class="brush: coldfusion; title: ; notranslate">
&lt;cfsetting enablecfoutputonly=&quot;true&quot;&gt;

&lt;cfparam name=&quot;query&quot; default=&quot;&quot;&gt;

&lt;cfquery name=&quot;chargeCodes&quot; datasource=&quot;#getDatasource().getName()#&quot;&gt;
SELECT UNIQUE widget_seq_no, identifier, descr
FROM 	widgets
WHERE 	(REGEXP_LIKE(identifier,&lt;cfqueryparam cfsqltype=&quot;cf_sql_varchar&quot; value=&quot;^#query#&quot;&gt;,'i')
   OR REGEXP_LIKE(descr,&lt;cfqueryparam cfsqltype=&quot;cf_sql_varchar&quot; value=&quot;^#query#&quot;&gt;,'i'))
   AND widget_type_cd='SNAPPYDS'
ORDER BY identifier asc
&lt;/cfquery&gt;

&lt;cfscript&gt;
jsonBean = createobject(&quot;component&quot;,&quot;ajaxCFC.JSON&quot;);
jsonEncodedCriteria = jsonBean.encode(data=chargeCodes, queryFormat=&quot;array&quot;);
writeOutput(jsonEncodedCriteria);
&lt;/coldfusion&gt;

&lt;cfsetting enablecfoutputonly=&quot;false&quot;&gt;
</pre>
<p>I hate this, because I already am using my <a href="http://www.fusioncube.net/index.php/porting-my-coldspring-enabled-ajaxcfc-code-to-extjs" target="_blank">Ext.AjaxCFC</a> class to query my <a href="http://www.coldspringframework.org/" target="_blank">ColdSpring</a> beans asynchronously, so why do I have to set up these standalone ColdFusion pages to performs queries that should be executed in the component?</p>
<p>I decided to take matters into my own hands, and I have to give the ExtJS team props again, because it was easy to accomplish by extending the <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.MemoryProxy" target="_blank">Ext.data.MemoryProxy</a> class. As you can see, all I need to do is override the doRequest() method to execute Ext.AjaxCFC.request() with the data passed in during initialization.</p>
<h3>Ext.ux.data.AjaxCFCProxy.js</h3>
<pre class="brush: jscript; title: ; notranslate">
Ext.ns('Ext.ux.data');

Ext.ux.data.AjaxCFCProxy = Ext.extend(Ext.data.MemoryProxy, {
   constructor : function(data){
      Ext.ux.data.AjaxCFCProxy.superclass.constructor.call(this);
      this.data = data;
   },
   doRequest : function(action, rs, params, reader, callback, scope, arg){
      this.data.data.query = params.query;
      Ext.AjaxCFC.request({
         bean : this.data.bean,
         method : this.data.method,
         data : this.data.data,
         success: function(rs) {
            var result = reader.readRecords(rs);
            callback.call(scope, result, arg, true);
         },
         error: function(results) {
            Ext.MessageBox.alert('Load Failed', 'Unable to load requested data');
         }
      });
   }
});
</pre>
<h3>New and Improved Combobox for Searching</h3>
<pre class="brush: jscript; title: ; notranslate">
WidgetSearch = new Ext.form.ComboBox({
    minChars:           2,
    loadingText:        '',
    itemSelector:       'div.search-item',
    triggerClass:       'x-form-search-trigger',
    emptyText:          '',
    width:              300,
    listWidth:          0,
    store: new Ext.data.Store({
        // I've extended the base Ext.data.MemoryProxy()
        // class to use the AjaxCFC object for searching
        // instead of having to use a liveQuery. Much cleaner.
        proxy: new Ext.ux.data.AjaxCFCProxy({
            bean    : 'Widget',
            method  : 'search',
            data    : { source_table : 'WIDGET' }
        }),
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/new-ajaxcfcproxy-class-for-sencha-extjs/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Porting my ColdSpring-enabled AjaxCFC code to ExtJS</title>
		<link>http://www.fusioncube.net/index.php/porting-my-coldspring-enabled-ajaxcfc-code-to-extjs</link>
		<comments>http://www.fusioncube.net/index.php/porting-my-coldspring-enabled-ajaxcfc-code-to-extjs#comments</comments>
		<pubDate>Tue, 07 Dec 2010 17:28:33 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[ajaxCFC]]></category>
		<category><![CDATA[coldfusion]]></category>
		<category><![CDATA[coldspring]]></category>
		<category><![CDATA[ExtJS]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[ajaxcfc]]></category>
		<category><![CDATA[connection]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[Sencha]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/index.php/porting-my-coldspring-enabled-ajaxcfc-code-to-extjs</guid>
		<description><![CDATA[I&#8217;ve been using the AjaxCFC library for years. It&#8217;s my preferred way of integrating Javascript and ColdFusion via AJAX. I&#8217;ve even modified it from its original form so that my implementation was strictly for integration with jQuery, only returns JSON strings (ignoring WDDX and simple string), and can work with ColdSpring. Now that I&#8217;m a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using the <a href="http://ajaxcfc.riaforge.org/index.cfm" target="_blank">AjaxCFC</a> library for years. It&#8217;s my preferred way of integrating Javascript and ColdFusion via AJAX. I&#8217;ve even modified it from its original form so that my implementation was strictly for integration with <a href="http://jquery.com/" target="_blank">jQuery</a>, only returns JSON strings (ignoring WDDX and simple string), and can <a href="http://www.fusioncube.net/index.php/invoking-coldspring-bean-with-ajaxcfc" target="_blank">work with ColdSpring</a>.</p>
<p>Now that I&#8217;m a heavy user of the <a href="http://www.sencha.com/products/js/" target="_blank">Sencha ExtJS framework</a>, I thought it would be useful to port the jQuery.ajaxCFC.js file over to an Ext.AjaxCFC.js file that extended the native <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.data.Connection" target="_blank">Ext.data.Connection</a> class and utilized the <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.Ajax" target="_blank">Ext.Ajax</a> object.</p>
<p>Took me about half the day, but I finally got a working Ext.AjaxCFC.request() method that uses the same syntax as the $.AjaxCFC() method. For those familiar with the inner workings and code of the jQuery AjaxCFC class, this will look very familiar.</p>
<p>So now I can make AJAX calls using native ExtJS classes, access ColdSpring beans in my application&#8217;s bean factory, or connect directly to any CFC</p>
<h3>Ext.AjaxCFC.js</h3>
<pre class="brush: jscript; title: ; notranslate">
Ext.AjaxCFCConnection = Ext.extend(Ext.data.Connection, {
   data        : null,
   queryFormat : 'array',
   factory     : (typeof(__ajaxConfig) == 'undefined') ? null : __ajaxConfig.beanFactory,
   timeout     : (typeof(__ajaxConfig) == 'undefined') ? 30000 : __ajaxConfig.defaultTimeout,
   url         : __ajaxConfig.url,
   bean        : null,

   request : function(arguments) {
      var params = (typeof(arguments.data) == 'undefined') ? {} : arguments.data;
      arguments.params = {};
      arguments.params['C0-ID']         = (Math.floor(Math.random() * 10001) + &quot;_&quot; + new Date().getTime()).toString(),
      arguments.params['method']        = 'init';
      arguments.params['component']     = arguments.component;
      arguments.params['bean']          = (typeof(arguments.bean) == 'undefined') ? this.bean : arguments.bean;
      arguments.params['factory']       = this.factory;
      arguments.params['C0-METHODNAME'] = arguments.method;
      arguments.params['queryFormat']   = (typeof(arguments.queryFormat) == 'undefined') ? this.queryFormat : arguments.queryFormat;
      arguments.params['C0-PARAM0']     = params;

      arguments.url = this.url + '?method=' + arguments.params['method'];
      arguments.method = 'POST';
      arguments.failure = arguments.error;
      arguments.timeout = this.timeout;

      var ____success = arguments.success;

      arguments.success = function(data) {
         data = data.responseText.replace(/^\s*|\s*$/g, '');

         if (data.substring(0,9) == '__json__:') {
            data = Ext.util.JSON.decode(data.slice(9));
         }
         ____success(data, this);
      };

      if ( params ) {
         if (typeof params != 'string') {
            arguments.params['C0-PARAM0'] = Ext.util.JSON.encode(params);
         }
      }

      Ext.Ajax.request(arguments);
   }
});

Ext.AjaxCFC = new Ext.AjaxCFCConnection();
</pre>
<h3>Usage</h3>
<pre class="brush: jscript; title: ; notranslate">
// Include Ext.AjaxCFC code
&lt;script type=&quot;text/javascript&quot; src=&quot;js/Ext.AjaxCFC.js&quot;&gt;&lt;/script&gt;

// Default configuration properties for the ajaxCFC library
__ajaxConfig = {
   'url':'/myApp/ajaxCFC/ajax.cfc',
   'defaultTimeout':30000,
   'beanFactory':'application.beanFactory'
};

// AjaxCFC call using Ext.data.Connection class
Ext.AjaxCFC.request({
   bean: 'AColdSpringBean',
   method: 'aMethod',
   data: {
      'id': 416198,
      'first_name': 'Steve',
      'last_name': 'Brownlee'
   },
   success: function(details, s){
      DataStore.loadData(details);
   },
   error: function(results){
      Ext.MessageBox.alert('Search Failed', 'An unexpected error occurred. Please try again.');
   }
});
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/porting-my-coldspring-enabled-ajaxcfc-code-to-extjs/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cairngorm 3: The cat is out of the bag</title>
		<link>http://www.fusioncube.net/index.php/cairngorm-3-the-cat-is-out-of-the-bag</link>
		<comments>http://www.fusioncube.net/index.php/cairngorm-3-the-cat-is-out-of-the-bag#comments</comments>
		<pubDate>Wed, 07 Oct 2009 18:53:32 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[cairngorm]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/?p=662</guid>
		<description><![CDATA[Now that I can officially talk about Cairngorm 3, I thought I&#8217;d put some of my thoughts down (more for my future reference, but feel free to follow along). Alex Uhlmann officially announced the release of Cairngorm 3 beta on October 5th, and from my limited access to the documentation and code, I have a [...]]]></description>
			<content:encoded><![CDATA[<p>Now that I can officially talk about Cairngorm 3, I thought I&#8217;d put some of my thoughts down (more for my future reference, but feel free to follow along).</p>
<p>Alex Uhlmann officially <a href="http://blogs.adobe.com/auhlmann/archives/2009/10/cairngorm_3_bet.html">announced the release of Cairngorm 3</a> beta on October 5th, and from my limited access to the documentation and code, I have a few opinions.</p>
<h3>Cairngorm 3 != MVC</h3>
<p>I think that it is a positive thing that Adobe Consulting decided to take their hat out of the ring of application architecture providers.  The next release of Cairngorm is a complete paradigm shift for the project, in that it is &#8211; to simplify it a bit &#8211; a set of best practices and support libraries that developers can use within an application architecture such as Mate, Swiz or Parsley.</p>
<p>After I learned this fact, I was surprised that they kept the same project name, but it is a strong brand which will retain the current developer base and level of interest.</p>
<p>I also think that it lays the groundwork for a more free-market environment for other application architectures available today, or soon to be available.  I know that a large consideration we made at my company was that since Cairngorm was produced by Adobe Consulting, that it would always be a strong contender, and most likely the proverbial 400-pound gorilla.  Now that there is not an &#8220;official&#8221; application architecture supported by Adobe, then the weight of the brand is removed from the decision making. Now becomes about who has the architecture that is best implemented, best documented, easiest to integrate, etc.</p>
<h3>It&#8217;s Smart Business</h3>
<p>Looking at it strictly from a consulting business perspective, this approach to application development support is much more sustainable and has higher revenue-generating potential.  If a shop chose to implement the Cairngorm 2 architecture, they may require assistance initially to get up to speed but eventually they become highly proficient and that well dries up.</p>
<p>In addition, it limits their business to people who implement Cairngorm 2.</p>
<p>Now that Cairngorm 3 can enhance and extend any architecture available &#8211; since it is about applying best practices &#8211; their consulting possibilities are now limitless.  It doesn&#8217;t matter if you choose to use Mate, or PureMVC, because the Cairngorm 3 libraries can enhance them to support enterprise Flex development.</p>
<p>It&#8217;s a win-win situation.  They get more business and more expertise, which in turn generates more ideas for Cairngorm, and makes their package more useful as time goes on.</p>
<h3>Past Imperfect</h3>
<p>However, I now wish I could turn back the clock 1 year and change the decision we made to implement Cairngorm 2 architecture.  After doing internal testing of the major packages available, Cairngorm was not our main choice from a technical perspective, but was the top contender from the business perspective, and so we bit the bullet and adapted.</p>
<p>At the time, Mate was my choice for our application development efforts, and now we may have the discussion again internally about moving over.  I know it won&#8217;t happen, for we&#8217;ve invested far too much time and effort into adopting Cairngorm, but I at least want to have the conversation.</p>
<h3>Exciting Times</h3>
<p>Lastly, I will say I am excited about this new direction that Adobe has taken, and we&#8217;ve already begun to play around with some of the code in-house.  I&#8217;ll post reviews once I&#8217;ve had a chance to digest most of it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/cairngorm-3-the-cat-is-out-of-the-bag/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Cairngorm: Abstract Events Updated</title>
		<link>http://www.fusioncube.net/index.php/cairngorm-abstract-events-updated</link>
		<comments>http://www.fusioncube.net/index.php/cairngorm-abstract-events-updated#comments</comments>
		<pubDate>Wed, 03 Jun 2009 13:19:30 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[cairngorm]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/?p=560</guid>
		<description><![CDATA[Purpose The intended purpose for the AbstractEvent class in Cairngorm was three-fold: Reduce the number of files needed to manage business events by organizing Events into domains Implement a callback feature so that a view can specify another action to perform upon the successful completion of an event Make each domain event class as lightweight [...]]]></description>
			<content:encoded><![CDATA[<h1>Purpose</h1>
<p>The intended purpose for the AbstractEvent class in Cairngorm was three-fold:</p>
<ol>
<li>Reduce the number of files needed to manage business events by organizing Events into domains</li>
<li>Implement a callback feature so that a view can specify another action to perform upon the successful completion of an event</li>
<li>Make each domain event class as lightweight as possible</li>
</ol>
<h1>Related Posts</h1>
<p><a href="http://www.fusioncube.net/index.php/cairngorm-abstract-events-updated">Abstract Commands</a> | <a href="http://www.fusioncube.net/index.php/abstractdelegate-for-cairngorm">Abstract Delegates</a></p>
<h1>Concept</h1>
<p>To accomplish these goals, each domain event (e.g. ProjectEvent, PaymentEvent, etc.) would be polymorphic (kinda) in that there is no longer just one identifier designated with the EVENT_ID constant. In addition, I wanted to abstract as much functionality and classification as possible into a common class that each domain event would extend.<br />
<img src="http://www.fusioncube.net/wp-content/uploads/2009/06/abstract_event.png" alt="abstract_event" title="abstract_event" width="344" height="78" class="alignnone size-full wp-image-564" /></p>
<h1>Lightweight, Polymorphic Event Class</h1>
<p>Here&#8217;s an example of a domain event.  It has three public identifiers &#8211; CREATE_PROJECT, LOAD_PROJECTS, DEACTIVATE_PROJECT- and has no logic other than to pass its constructor&#8217;s arguments to AbstractEvent.</p>
<h3>ProjectEvent.as</h3>
<pre class="code"><code>package business.events
{
   import com.adobe.cairngorm.control.CairngormEvent;

   public class ProjectEvent extends AbstractEvent
   {
      public static const CREATE_PROJECT:String = "createProject";
      public static const LOAD_PROJECTS:String = "getProjects";
      public static const DEACTIVATE_PROJECT:String = "deactivateProject";

      public function ProjectEvent(type:String, data:Object = null, callbacks:Array=null)
      {
         super(type, data, callback);
      }
   }
}</code></pre>
<h1>AbstractEvent Class</h1>
<p>The AbstractEvent class itself isn&#8217;t much more complicated at all.  It simply has three public variables to hold the type of the event, an object containing key/value pairs for the data, and the reference to the callback function in the view (if specified).</p>
<h3>AbstractEvent.as</h3>
<pre class="code"><code>package business.events
{
   import com.adobe.cairngorm.control.CairngormEvent;

   public class AbstractEvent extends CairngormEvent
   {
      public var callbacks:Array = null;

      public function AbstractEvent(type:String, data:Object = null, callbacks:Array=[])
      {
         super(type);

         this.data = data;
         this.callbacks = callbacks;
      }
   }
}</code></pre>
<h1>Example View &#8211; Projects</h1>
<p>Here&#8217;s some snippets of code from my project view. One piece of functionality is for a user to disable a selected project from a list in an AdvancedDataGrid. When the user clicks on the &#8220;Disable Project&#8221; button, the btnDeactivateProject_Click() function fires and creates a new Project event in which the loadProjects() function is specified as the callback function.</p>
<h3>Projects.mxml</h3>
<pre class="code"><code>private function btnDeactivateProject_Click(e:Event):void
{
   var thisProject:Project = gridProjects.selectedItem as Project;
   new ProjectEvent(ProjectEvent.DEACTIVATE_PROJECT,
            {project:thisProject},
            [loadProjects]).dispatch();
}

public function loadProjects():void
{
   new ProjectEvent(ProjectEvent.LOAD_PROJECTS).dispatch();
}

&lt;mx:Button id="btnDeactivateProject"
	click="btnDeactivateProject_Click(event)"
	x="10" y="393"
	label="Deactivate Project"/&gt;</code></pre>
<h1>Mapping Events to Commands</h1>
<p>Your controller logic doesn&#8217;t change.  The only difference is that you&#8217;re using one domain event, with specified identities, mapped to different Commands.</p>
<h3>Controller.as</h3>
<pre class="code"><code>package business
{
   import business.commands.*;
   import business.events.*;
   import com.adobe.cairngorm.control.FrontController;

   public class Controller extends FrontController
   {
      public function Controller()
      {
         super();
         addCommand(ProjectEvent.LOAD_PROJECTS, LoadProjectsCommand);
         addCommand(ProjectEvent.CREATE_PROJECT, CreateProjectCommand);
         addCommand(ProjectEvent.DEACTIVATE_PROJECT, DeactivateProjectCommand);
      }
   }
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/cairngorm-abstract-events-updated/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cairngorm: Abstract Commands Updated</title>
		<link>http://www.fusioncube.net/index.php/cairngorm-abstract-commands-updated</link>
		<comments>http://www.fusioncube.net/index.php/cairngorm-abstract-commands-updated#comments</comments>
		<pubDate>Wed, 03 Jun 2009 13:19:10 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[cairngorm]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/?p=543</guid>
		<description><![CDATA[Purpose The intended purpose for the AbstractCommand class in Cairngorm is three-fold: Further implementation of a callback feature &#8211; in conjunction with the AbstractEvent &#8211; so that a view can specify other actions to perform upon the successful completion of business event Create a Responder object for the Delegate to use Make each Command class [...]]]></description>
			<content:encoded><![CDATA[<h1>Purpose</h1>
<p>The intended purpose for the AbstractCommand class in Cairngorm is three-fold:</p>
<ol>
<li>Further implementation of a callback feature &#8211; in conjunction with the AbstractEvent &#8211; so that a view can specify other actions to perform upon the successful completion of business event</li>
<li>Create a Responder object for the Delegate to use</li>
<li>Make each Command class as lightweight as possible</li>
</ol>
<h1>Related Posts</h1>
<p><a href="http://www.fusioncube.net/index.php/cairngorm-patterns-batch-commands">Batch Commands</a> | <a href="http://www.fusioncube.net/index.php/cairngorm-abstract-events-updated">Abstract Events</a> | <a href="http://www.fusioncube.net/index.php/abstractdelegate-for-cairngorm">Abstract Delegates</a></p>
<h1>Concept</h1>
<p><img src="http://www.fusioncube.net/wp-content/uploads/2009/06/abstract_command.png" alt="abstract_command" title="abstract_command" width="300" height="248" class="alignnone size-full wp-image-547" /></p>
<h1>Standard, Responseful Command</h1>
<p>Below is an example Command in my system, it extends AbstractCommand which in turn implements the ICustomCommand interface. To make the Command responseful, an array of functions is passed from the Event to the Command, which will execute them upon success (see more below).  Here&#8217;s an example call:</p>
<pre class="code"><code>new EmployeeEvent(EmployeeEvent.GET_DETAILS,
         {employee_id:params.empID},
         [showEmployeeDetails, updateEmployeeGraph])</code></pre>
<p>To implement a very basic command, it is only required to set the delegate property to a new instance of the appropriate Delegate class, and then invoke the needed method.  The AbstractCommand will automatically create a new Responder object and assign it to the delegate.</p>
<h3>LoadProjectCommand.as</h3>
<pre class="code"><code>public class LoadProjectCommand extends AbstractCommand
{
   private var _model:ModelLocator = ModelLocator.getInstance();

   override public function execute():void
   {
      delegate = new ProjectDelegate();
      (delegate as ProjectDelegate).loadProject(invoker.data);
   }

   override public function commandSuccess(event:Event):void
   {
      if (event.result.success)
      {
         _model.project = (event as ResultEvent).result.data;
         notifyInvoker();
      }
   }
}
}</code></pre>
<p>The invoker object is a reference to the original Event that was called, and to get it assigned as a property of the Command, I extended the FrontController class so that it is assigned before the Command is executed.</p>
<pre class="code"><code>protected function executeAbstractCommand(event:AbstractEvent):void
{
   var commandRef:Class = getCommand(event.type);
   var commandToExecute:ICustomCommand = new commandRef();

   commandToExecute.invoker = event;
   commandToExecute.execute();
}</code></pre>
<h1>AbstractCommand Class</h1>
<p>This class is straightforward and handles the tedious aspects of creating a Command.  The notifyInvoker() method simply loops through the array of callback functions &#8211; if they exist &#8211; and runs them.</p>
<h3>AbstractCommand.as</h3>
<pre class="code"><code>public class AbstractCommand
{
   private var _callbacks:Array = null;
   private var _invoker:AbstractEvent = null;
   private var _delegate:AbstractDelegate = null;

   public function AbstractCommand() { }
   public function execute():void { }
   public function commandSuccess(event:Event):void { }
   public function commandFault(event:Event):void { }

   public function set delegate(d:*):void
   {
      _delegate = d;
      _delegate.setResponder(new Responder(commandSuccess, commandFault));
   }

   public function get delegate():*
   {
      return _delegate;
   }

   public function set invoker(e:AbstractEvent):void
   {
      _invoker = e;
      if (e.callbacks != null) _callbacks = e.callbacks;
   }

   public function get invoker():AbstractEvent
   {
      return _invoker;
   }

   public function notifyInvoker(info:Object = null):void
   {
      if (_callbacks != null)
      {
         for (var i:uint = 0; i &lt; _callbacks.length; i++)
         {
            var callback:Function = _callbacks[i];
           (info != null) ? callback.call(this, info) : callback.call(this);
         }
      }
   }
}</code></pre>
<h1>ICustomCommand Interface</h1>
<h3>ICustomCommand.as</h3>
<pre class="code"><code>package business.commands
{
   import business.events.AbstractEvent;
   import flash.events.Event;

   public interface ICustomCommand
   {
      function commandSuccess(event:Event):void;
      function commandFault(event:Event):void;
      function execute():void;
      function set invoker(event:AbstractEvent):void;
      function set delegate(delegate:*):void;
   }
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/cairngorm-abstract-commands-updated/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cairngorm: Sharing a common ModelLocator with modules</title>
		<link>http://www.fusioncube.net/index.php/cairngorm-sharing-a-common-modellocator-with-modules</link>
		<comments>http://www.fusioncube.net/index.php/cairngorm-sharing-a-common-modellocator-with-modules#comments</comments>
		<pubDate>Tue, 07 Apr 2009 19:51:07 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[actionscript]]></category>
		<category><![CDATA[cairngorm]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/?p=472</guid>
		<description><![CDATA[High-level overview of how I've been able to share common data models between modules in a Flex application.]]></description>
			<content:encoded><![CDATA[<h1>Application Design 201</h1>
<p>Granularity is a well-known topic in software development.  Another common concept is encapsulation.  There&#8217;s books, magazine articles, and blog posts about these topics going back decades (well, not the blog posts).</p>
<p>One challenge we&#8217;ve had recently is trying to apply these concepts to a Flex application that uses modules.  We want a global data model that modules can access, but have no way to access its internal mechanisms (i.e. no public variables).</p>
<h1>The Shell</h1>
<p>The core idea is that we want a common data model loaded into a basic Flex app &#8211; the Shell &#8211; which has no functionality, in and of itself, other than to load and unload modules that contain the business functionality.</p>
<p>This common data would then need to be accessible to every module that got loaded into the Shell &#8211; regardless of whether the module needed it or not.</p>
<p><img src="http://www.fusioncube.net/wp-content/uploads/2009/04/module_communication.png" alt="module_communication" title="module_communication" width="458" height="309" class="alignnone size-full wp-image-473" /></p>
<h1>The Interface</h1>
<p>First thing we need is establish an interface that each module can use to identify itself so that when the Shell loads it, the Shell recognizes that it should send its global data model to the module.</p>
<p>People and places have had their names changed to protect their identity&#8230;</p>
<pre class="code"><code>package com.widget.common.interfaces
{
   public interface ICoolModule
   {
      function getModuleController():Class
      function setGlobalModel(model:Class):void
   }
}</code></pre>
<p>The key method defined for this mechanism is the setGlobalModel() method.  This is the method that it called by the Shell (shown below) when it loads a module to ensure that each module has a reference to the global data model.</p>
<h1>The CoolModule</h1>
<p>I then extended the basic Flex Module class, so that I could implement the ICoolModule interface and provide basic functionality for accessing the global data model</p>
<h3>CoolModule.as</h3>
<pre class="code"><code>package com.widget.common.components
{
   import com.widget.common.interfaces.ICoolModule;

   import mx.core.Singleton;
   import mx.modules.Module;

   public class CoolModule extends Module implements ICoolModule
   {
      [Bindable] public var _globalModel:*;

      public function CoolModule()
      {
         super();
      }

      public function getModuleController():Class
      {
         return null;
      }

      public function setGlobalModel(globalModelLocator:Class):void
      {
          _globalModel = Singleton.getInstance("IModelLocator") as globalModelLocator;
      }
   }
}</code></pre>
<p>Now when I create a new module, it&#8217;s a CoolModule instead of the base Module.</p>
<h3>Module1.mxml</h3>
<pre class="code"><code>&lt;component:CoolModule xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:component="com.widget.common.components.*"&gt;</code></pre>
<h1>Loading the Module</h1>
<p>So now that we&#8217;ve set up things on the Module end, let&#8217;s see how the Shell actually injects its model into each Module. I&#8217;ve got a command that handles loading modules with a commandSuccess() method that handles the coupling (significantly stripped down version here just to show the relevent code).</p>
<h3>LoadModuleCommand.as</h3>
<pre class="code"><code>package com.widget.thisApp.business.commands
{
   import com.widget.thisApp.model.ModelLocator;

   public class ModuleLoaderCommand extends <a href="http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-commands">AbstractCommand</a> implements ICustomCommand
   {
      ...
      public function commandSuccess(event:Event):void
      {
         if(_component is ICoolModule)
         {
            var coolModule:ICoolModule = _component as ICoolModule;
            ...
            coolModule.setGlobalModel(ModelLocator);
         }
      }
      ...
   }
}</code></pre>
<p>Now, for those who were paying attention, you may have figured out the key to all of this is that the ModelLocator is a singleton.  As long as the module gets loaded into the current application and security domain&#8230;</p>
<pre class="code"><code>module.load(ApplicationDomain.currentDomain, SecurityDomain.currentDomain);</code></pre>
<p>&#8230;then it can access the Model singleton.</p>
<h1>Conclusion</h1>
<p>We&#8217;ve found that while module-parent, and module-module, communication is certainly not elegantly built into the Flex framework, it is possible with a little bit of grunt work.  I&#8217;m hoping that as the Flex SDK matures and becomes more feature-rich that this feature become more robust.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/cairngorm-sharing-a-common-modellocator-with-modules/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Cairngorm Patterns: Batch Commands</title>
		<link>http://www.fusioncube.net/index.php/cairngorm-patterns-batch-commands</link>
		<comments>http://www.fusioncube.net/index.php/cairngorm-patterns-batch-commands#comments</comments>
		<pubDate>Tue, 31 Mar 2009 14:19:45 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[cairngorm]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/?p=451</guid>
		<description><![CDATA[Related Posts Abstract Commands Basic Cairngorm Commands In the base implementation of the Cairngorm micro-architecture, events and commands are mapped on a 1-1 basis. For every invoker (event) you have to specify one command in your controller. public function Controller() { super(); addCommand(TeammateEvent.LOAD_TEAMMATES, LoadTeammatesCommand); addCommand(EffortEvent.LOAD_TYPES, LoadEffortTypesCommand); addCommand(ProjectEvent.LOAD_PROJECTS, LoadProjectsCommand); addCommand(TeammateEvent.LOAD_TEAMMATE_ROLES, LoadTeammateRolesCommand); ... } For most cases, [...]]]></description>
			<content:encoded><![CDATA[<h1>Related Posts</h1>
<p><a href="http://www.fusioncube.net/index.php/cairngorm-abstract-commands-updated">Abstract Commands</a></p>
<h1>Basic Cairngorm Commands</h1>
<p>In the base implementation of the Cairngorm micro-architecture, events and commands are mapped on a 1-1 basis.  For every invoker (event) you have to specify one command in your controller.</p>
<pre class="code"><code>public function Controller()
{
   super();
   addCommand(TeammateEvent.LOAD_TEAMMATES, LoadTeammatesCommand);
   addCommand(EffortEvent.LOAD_TYPES, LoadEffortTypesCommand);
   addCommand(ProjectEvent.LOAD_PROJECTS, LoadProjectsCommand);
   addCommand(TeammateEvent.LOAD_TEAMMATE_ROLES, LoadTeammateRolesCommand);
   ...
}</code></pre>
<p>For most cases, this is perfectly fine, but in a data-heavy model, such as the one being built for my current application, I need to initialize the application and fire off many individual events in order to load my model with base data.</p>
<pre class="code"><code>// Load all teammates in the database for display in the reports tab
new TeammateEvent(TeammateEvent.LOAD_TEAMMATES).dispatch();

// Load all effort types
new EffortEvent(EffortEvent.LOAD_TYPES).dispatch();

// Load all projects
new ProjectEvent(ProjectEvent.LOAD_PROJECTS).dispatch();

// Load all roles
new TeammateEvent(TeammateEvent.LOAD_TEAMMATE_ROLES).dispatch();

...</code></pre>
<h1>Batch Commands</h1>
<p>In order to avoid having to dispatch <em>n</em> events for <em>n</em> commands to be executed, I would rather map 1 event to <em>n</em> commands and have them fired off in sequence.  Then, if I need a batch of commands to fire, I only need to dispatch one event, instead of the 4 I used in the example above.</p>
<pre class="code"><code>new ApplicationEvent(ApplicationEvent.LOAD_MODEL).dispatch();</code></pre>
<p>Unfortunately, Cairngorm does not allow this, so I had to extend the basic architecture.  I created a addCommands() function that maps a single event to multiple commands as an array.</p>
<pre class="code"><code>public class Controller extends ExtendedFrontController
{
   public function Controller()
   {
      addCommands(ApplicationEvent.LOAD_MODEL, [LoadTeammatesCommand,
                                LoadEffortTypesCommand,
                                LoadProjectsCommand,
                                LoadTeammateRolesCommand,
                                ...]);
   }
}</code></pre>
<h1>Extended Controller Class</h1>
<p>Here&#8217;s the code that I&#8217;ve come up with so far.  This is working fine, but there still some things I plan on implementing in the future.</p>
<h3>ExtendedFrontController.as</h3>
<pre class="code"><code>public class ExtendedFrontController extends FrontController
{
   public function ExtendedFrontController()
   {
      super();
   }

   public function addCommands(commandName:String, commandRefs:Array, useWeakReference:Boolean = true):void
   {
      if(commands[ commandName ] != null)
      {
         throw new CairngormError( CairngormMessageCodes.COMMAND_ALREADY_REGISTERED, commandName );
      }

      if (commandRefs == null)
      {
         throw new Error("The commandRefs argument to addCommands() is null");
      }

      commands[commandName] = commandRefs;

      for (var priority:uint = 0; priority &lt; commandRefs.length; priority++)
      {
         CairngormEventDispatcher.getInstance().addEventListener(commandName, executeCommands, false, priority, useWeakReference);
      }
   }

   protected function executeCommands(event:AbstractEvent):void
   {
      var commandsToInitialise:Array = getCommands(event.type);
      var commandRef:Class;

      for (var i:uint = 0; i &lt; commandsToInitialise.length; i++)
      {
         commandRef = commandsToInitialise[i];
         var commandToExecute:ICustomCommand = new commandRef();
         commandToExecute.execute(event);
      }
   }

   protected function getCommands(commandName:String):Array
   {
      var commands:Array = commands[commandName];

      if ( commands == null )
         throw new CairngormError( CairngormMessageCodes.COMMAND_NOT_FOUND, commandName );

      return commands;
   }
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/cairngorm-patterns-batch-commands/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>A Better, Stronger Flex Architecture</title>
		<link>http://www.fusioncube.net/index.php/a-better-stronger-flex-architecture</link>
		<comments>http://www.fusioncube.net/index.php/a-better-stronger-flex-architecture#comments</comments>
		<pubDate>Tue, 24 Mar 2009 02:25:39 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[cairngorm]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/?p=422</guid>
		<description><![CDATA[Cairngorm++ Call me a junkie, that&#8217;s fine, but this stuff works. I&#8217;ve said many times in the past that the whole purpose of using design patterns, code frameworks, and application architectures should be to reduce the code I write (as time progresses), make an application easier to extend, and reduce the cost of turnover. After [...]]]></description>
			<content:encoded><![CDATA[<h1>Cairngorm++</h1>
<p>Call me a junkie, that&#8217;s fine, but this stuff works.  I&#8217;ve said many times in the past that the whole purpose of using design patterns, code frameworks, and application architectures should be to reduce the code I write (as time progresses), make an application easier to extend, and reduce the cost of turnover.</p>
<p>After quickly learning what the <a href="http://opensource.adobe.com/wiki/display/cairngorm/">Cairngorm architecture</a> had to offer, I noticed several gaps that needed to be filled.  One of which was the inordinate amount of files that are created using the base patterns (which I alleviated with my abstract classes for <a href="http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-events">Event</a>, <a href="http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-commands">Command</a>, and <a href="http://www.fusioncube.net/index.php/abstractdelegate-for-cairngorm">Delegate</a>).  Another gap is that it doesn&#8217;t have a view mediator.  That&#8217;s the one feature from the <a href="http://puremvc.org/component/option,com_wrapper/Itemid,144/">PureMVC framework</a> that I actually was a huge fan of.</p>
<h1>Mediators</h1>
<p>You see, PureMVC uses a <a href="http://en.wikipedia.org/wiki/Mediator_pattern">Mediator pattern</a> in order to provide a mechanism by which views could interact with the business logic, as well as with each other, while remaining ignorant of the man behind the curtain.  Keeping the views decoupled from the model is good &#8211; especially with my apps &#8211; because subtle changes to the data model happen often, and while a good part of that is handled in the business logic, it often bubbles up to the UI model as well.</p>
<h1>I am a Command, I am an Island</h1>
<p>Another value feature that other frameworks have is that ability for a View &#8211; via a Mediator &#8211; to actually know if a Command was successful or not.  Gasp!  With the base Cairngorm implementation, the only way to perform an action on success of a Command was in the Command itself.  Very bad, otherwise you end up with situations that call for <strong>SaveProjectAndReloadModelCommand</strong> in which you do one action and then immediately call another Command, and <strong>SaveProjectWithNoModelReloadCommand</strong> for when you don&#8217;t need to do the second Command.</p>
<p>A Command should be as insular as possible.  It should never directly call another Command.</p>
<h1>Responseful Commands</h1>
<p>My way around this was to implement a function callback feature in the <a href="http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-events">Event</a> and <a href="http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-commands">Command</a> abstract classes.  </p>
<p><img src="http://www.fusioncube.net/wp-content/uploads/2009/03/abstract.png" alt="abstract" title="abstract" width="194" height="178" class="alignnone size-full wp-image-427" /></p>
<p>When an Event is dispatched from a View, the name of a local function is passed as an argument.  The Command consumes this function reference and then runs it if the execution was successful.</p>
<h1>Tested in the Field</h1>
<p>Sure, theory is fine, but how does all this work when actually writing a Flex app?  Well, I put that to the test just the other day.  An app I&#8217;m working needed a significant enhancement and change.  After changing the database model, I was able to crank out the business logic, and three views in Flex in which users could create new items, deactivate/activate them, and a few other doo-dads in just under 40 minutes.</p>
<h1>Conclusion</h1>
<p>Don&#8217;t be afraid to enhance a framework or code architecture with your own ideas.  Trust yourself and your ideas because you&#8217;re smart, too.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/a-better-stronger-flex-architecture/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cairngorm Patterns: Abstract Commands</title>
		<link>http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-commands</link>
		<comments>http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-commands#comments</comments>
		<pubDate>Wed, 18 Mar 2009 15:21:06 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[design patterns]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[frameworks]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/?p=377</guid>
		<description><![CDATA[Purpose My intended purpose for the AbstractCommand class in Cairngorm was two-fold: Implement a callback feature so that a view can specify another action to perform upon the successful completion of an event Make each Command class as lightweight as possible Related Posts Batch Commands &#124; Abstract Events &#124; Abstract Delegates Concept Standard, Responseful Command [...]]]></description>
			<content:encoded><![CDATA[<h1>Purpose</h1>
<p>My intended purpose for the AbstractCommand class in Cairngorm was two-fold:</p>
<ol>
<li>Implement a callback feature so that a view can specify another action to perform upon the successful completion of an event</li>
<li>Make each Command class as lightweight as possible</li>
</ol>
<h1>Related Posts</h1>
<p><a href="http://www.fusioncube.net/index.php/cairngorm-patterns-batch-commands">Batch Commands</a> | <a href="http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-events">Abstract Events</a> | <a href="http://www.fusioncube.net/index.php/abstractdelegate-for-cairngorm">Abstract Delegates</a></p>
<h1>Concept</h1>
<p><img style="margin:30px 0 30px 0;" src="http://www.fusioncube.net/wp-content/uploads/2009/03/davita_cairngorm_command.png" alt="Abstract Command and Interface" title="Abstract Command and Interface" width="311" height="222" class="alignnone size-full wp-image-388" /></p>
<h1>Standard, Responseful Command</h1>
<p>Here&#8217;s an example Command in my system, it extends AbstractCommand and implements the ICustomCommand interface &#8211; which simply enforces a commandSuccess() and commandFault() method be present.</p>
<p>When the execute() method is invoked, the callback function property of the <a href="http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-events">domain event</a> is assigned by calling the setCallbackFunction() of the AbstractCommand, then the standard process of instantiating the proper delegate happens.</p>
<p>Now that the Command has a reference to the callback function (if it exists), in the commandSuccess() method, we simply call the AbstractCommand&#8217;s notifyCaller() method which executes that function.</p>
<h3>DeactivateProjectCommand.as</h3>
<pre class="code"><code>package business.commands
{
   public class DeactivateProjectCommand extends AbstractCommand implements ICustomCommand
   {
      private var _model:ModelLocator = ModelLocator.getInstance();

      public function execute(event:CairngormEvent):void
      {
         setCallbackFunction((event as ProjectEvent).callbackFunction);

         var delegate:ProjectDelegate = new ProjectDelegate();
         delegate.setResponder(new Responder(commandSuccess, commandFault));
         delegate.deactivate((event as ProjectEvent).eventData);
      }

      public function commandSuccess(event:ResultEvent):void
      {
         if (event.result.success)
         {
            notifyCaller(event.result.data.project as Project);
         }
      }

      public function commandFault(event:FaultEvent):void { }
   }
}</code></pre>
<h1>AbstractCommand Class</h1>
<p>This class is straightforward and simple.  It simply contains the setCallbackFunction() and notifyCaller() methods with a private class member _callback.</p>
<h3>AbstractCommand.as</h3>
<pre class="code"><code>package business.commands
{
   public class AbstractCommand
   {
      private var _callback:Function = null;

      public function setCallbackFunction(value:Function):void
      {
         if (value != null) _callback = value;
      }

      public function notifyCaller(info:Object = null):void
      {
         if (_callback != null)
         {
            if (info != null)
            {
               _callback.call(this, info);
            } else {
               _callback.call(this);
            }
         }
      }
   }
}</code></pre>
<h1>ICustomCommand Interface</h1>
<p>This interface simply enforces the implementation of the commandSuccess() and commandFault() methods.</p>
<h3>ICustomCommand.as</h3>
<pre class="code"><code>package business.commands
{
   import com.adobe.cairngorm.commands.ICommand;
   import mx.rpc.events.FaultEvent;
   import mx.rpc.events.ResultEvent;

   public interface ICustomCommand extends ICommand
   {
      function commandSuccess(event:ResultEvent):void;
      function commandFault(event:FaultEvent):void;
   }
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-commands/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cairngorm Patterns: Abstract Events</title>
		<link>http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-events</link>
		<comments>http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-events#comments</comments>
		<pubDate>Wed, 18 Mar 2009 15:20:57 +0000</pubDate>
		<dc:creator>Steve Brownlee</dc:creator>
				<category><![CDATA[design patterns]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[frameworks]]></category>

		<guid isPermaLink="false">http://www.fusioncube.net/?p=354</guid>
		<description><![CDATA[Purpose My intended purpose for the AbstractEvent class in Cairngorm was three-fold: Reduce the number of files needed to manage business events by organizing Events into domains Implement a callback feature so that a view can specify another action to perform upon the successful completion of an event Make each domain event class as lightweight [...]]]></description>
			<content:encoded><![CDATA[<h1>Purpose</h1>
<p>My intended purpose for the AbstractEvent class in Cairngorm was three-fold:</p>
<ol>
<li>Reduce the number of files needed to manage business events by organizing Events into domains</li>
<li>Implement a callback feature so that a view can specify another action to perform upon the successful completion of an event</li>
<li>Make each domain event class as lightweight as possible</li>
</ol>
<h1>Related Posts</h1>
<p><a href="http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-commands">Abstract Commands</a> | <a href="http://www.fusioncube.net/index.php/abstractdelegate-for-cairngorm">Abstract Delegates</a></p>
<h1>Concept</h1>
<p>To accomplish my goals, each domain event (e.g. ProjectEvent, PaymentEvent, etc.) would be polymorphic (kinda) in that there is no longer just one identifier designated with the EVENT_ID constant. In addition, I wanted to abstract as much functionality and classification as possible into a common class that each domain event would extend.<br />
<img style="margin:30px 0 0 0;" src="http://www.fusioncube.net/wp-content/uploads/2009/03/davita_cairngorm_event.png" alt="Abstract Event" title="Abstract Event" width="369" height="78" class="alignnone size-full wp-image-362" /></p>
<h1>Lightweight, Polymorphic Event Class</h1>
<p>Here&#8217;s an example of a domain event.  It has three public identifiers &#8211; CREATE_PROJECT, LOAD_PROJECTS, DEACTIVATE_PROJECT- and has no logic other than to pass its constructor&#8217;s arguments to AbstractEvent.</p>
<h3>ProjectEvent.as</h3>
<pre class="code"><code>package business.events
{
   import com.adobe.cairngorm.control.CairngormEvent;

   public class ProjectEvent extends AbstractEvent
   {
      public static const CREATE_PROJECT:String = "createProject";
      public static const LOAD_PROJECTS:String = "getProjects";
      public static const DEACTIVATE_PROJECT:String = "deactivateProject";

      public function ProjectEvent(type:String, data:Object = null, callback:Function = null)
      {
         super(type, data, callback);
      }
   }
}</code></pre>
<h1>AbstractEvent Class</h1>
<p>The AbstractEvent class itself isn&#8217;t much more complicated at all.  It simply has three public variables to hold the type of the event, an object containing key/value pairs for the data, and the reference to the callback function in the view (if specified).</p>
<h3>AbstractEvent.as</h3>
<pre class="code"><code>package business.events
{
   import com.adobe.cairngorm.control.CairngormEvent;

   public class AbstractEvent extends CairngormEvent
   {
      public var eventType:String = "";
      public var eventData:Object = new Object();
      public var callbackFunction:Function = null;

      public function AbstractEvent(type:String, data:Object = null, callback:Function = null)
      {
         super(type);
         eventType = type;
         eventData = data;
         callbackFunction = callback;
      }
   }
}</code></pre>
<h1>Example View &#8211; Projects</h1>
<p>Here&#8217;s some snippets of code from my project view. One piece of functionality is for a user to disable a selected project from a list in an AdvancedDataGrid. When the user clicks on the &#8220;Disable Project&#8221; button, the btnDeactivateProject_Click() function fires and creates a new Project event in which the loadProjects() function is specified as the callback function.</p>
<h3>Projects.mxml</h3>
<pre class="code"><code>private function btnDeactivateProject_Click(e:Event):void
{
   var p:Project = gridProjects.selectedItem as Project;
   var event:ProjectEvent = new ProjectEvent(
                                  ProjectEvent.DEACTIVATE_PROJECT,
                                  {project:p},
                                  loadProjects);
   event.dispatch();
}

public function loadProjects():void
{
   var projectEvent:ProjectEvent = new ProjectEvent(ProjectEvent.LOAD_PROJECTS);
   projectEvent.dispatch();
}

&lt;mx:Button id="btnDeactivateProject"
	click="btnDeactivateProject_Click(event)"
	x="10" y="393"
	label="Deactivate Project"/&gt;</code></pre>
<h1>Mapping Events to Commands</h1>
<p>Your controller logic doesn&#8217;t change.  The only difference is that you&#8217;re using one domain event, with specified identities, mapped to difference Commands.</p>
<h3>Controller.as</h3>
<pre class="code"><code>package business
{
   import business.commands.*;
   import business.events.*;
   import com.adobe.cairngorm.control.FrontController;

   public class Controller extends FrontController
   {
      public function Controller()
      {
         super();
         addCommand(ProjectEvent.LOAD_PROJECTS, LoadProjectsCommand);
         addCommand(ProjectEvent.CREATE_PROJECT, CreateProjectCommand);
         addCommand(ProjectEvent.DEACTIVATE_PROJECT, DeactivateProjectCommand);
      }
   }
}</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fusioncube.net/index.php/cairngorm-patterns-abstract-events/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

