Saturday, October 30, 2010

Quick Dive into Parsley (Automatic Component Wiring - Part 9)

 This is part of a series of articles that should get you up and started using Spicesfactory's Parsley by Jens Halm.. It includes examples on how to use Parsley for Flex.
This is part 9.
In Part 3, I showed how to set up Parsley and showed a Parsley basic injection example.
In Part 4, I showed how to send messages using Parsley that do not extend the Event class.
In Part 5, I showed how to send messages using Flex Events.
In Part 6, I showed nested contexts and object lifecycle methods.
In Part 7, I showed Decoupled Bindings
In Part 8, I showed how to use Dynamic Commands & Dynamic Objects

This article builds upon what was covered in the previous examples, so if you haven't seen them, I encourage you to start with at the beginning of this series.  This article focuses on Parsley's Automatic Component Wiring.


Automatic Component Wiring
   In all of the previous examples from this series, I explicitly told Parsley that I wanted a particular view to be managed by Parsley through using the <Configure /> tag.  Although this is very convenient, it is not the only way.  It also poses one problem.  What if your view is written entirely in ActionScript?  You can fire off the configure event, but it is meant only for Flash and you are strongly discourage to use it under Flex because the configure could get dispatched before the Context is ready.  Additionally, you might be interested in a method in which you can centrally manage which views get added to the Context or not?

  Well, you are in luck, Parsley has an Automatic Component Wiring feature that allows you to centrally configure which views are managed and which are not.

   The concept is fairly simple.  If you enable the autowire component feature, you can specify in your context config file, which views you want Parsley to manage.  Alternatively, rather than specifying all the views in your context config file, you can write a filter function that can decide programmatically which views are managed and which are not.  I’ve added two examples that shows each method.

   So how do you set this up?   It’s actually quite simple.  First we must change a little our context config tag declaration from what we are used to.  Usually we set it up in a one line tag, but not in this case.  We must use the <ViewSettings /> sub tag of the <ContextBuilder> tag.

   So when you declare your context you would have something similar to this:
<parsley:ContextBuilder>
    <parsley:ViewSettings autowireComponents="true"/>
    <parsley:FlexConfig type="{MyConfig}"/>
</parsley:ContextBuilder>

   In your context config file you would add <View> tags.  Something similar to this:
<View type="{CustomViewOne}"/>

   As you can see it’s actually pretty simple.  You can read more in section 8.4 Automatic Component Wiring of the developer manual.

  I’ve got two examples again.  One that you specify the views in the context config file, and the other where a filter function is used so that you don’t have to specify each view in the context config file.

Specifying the views in the context config file example

   Here is the working Parsley Automatic Component wiring example with view source enabled:



Now let take a look at the structure of the project.

   As you can see, the structure is very simple.  We have one model that will be shared called SimpleModel, and we have 3 views.  The main view and two custom views inside the views package.

   If you pay close attention, you will notice that I've updated the Parsley and the spicelib libraries to the 2.3.1 version which is the current one at the time of this writing.

   Ok let's start by taking a look at the model. Here is SimpleModel.as:

package model
{
    /*****************************************
     *  This is a very simple model that holds a string that will be shared
     * among some different views.
     *
     *  For more Flex and Parsley examples visit: artinflex.blogspot.com 
     */
    public class SimpleModel
    {
        /**********
         *  This is the shared string of the Model 
         */
        [Bindable]
        public var sharedString:String = "Hello Parsley";
    }
}

   Well, this is a very simple model that hold just a single string set to be bindable.  Pretty much like the original example.

  Now let's take a look at the views.  Here is CustomViewOne.mxml:

<?xml version="1.0" encoding="utf-8"?>
<!--
   Custom View Component used to demonstrate automatic wiring to Parsley
   Notice that there is no <Configure /> tag in this file.
   
   For more Parsley and Flex examples visit:  artinflex.blogspot.com
-->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="200" cornerRadius="5" 
    backgroundColor="#FADEDE" 
    xmlns:parsley="http://www.spicefactory.org/parsley" 
    borderStyle="solid" horizontalAlign="center" verticalAlign="middle" verticalGap="5">

    <mx:Label text="Custom View One" fontWeight="bold" fontSize="12"/>
    
    <!-- Text Input bound to shared string in the shared model -->
    <mx:TextInput width="192" id="sharedTextInput"/>
    <!-- Binding is set to be bi-directional  -->
    <mx:Binding destination="sharedTextInput.text" source="sharedModel.sharedString" />
    <mx:Binding destination="sharedModel.sharedString" source="sharedTextInput.text" />    
    
    <mx:Script>
        <![CDATA[
            import model.SimpleModel;
            /***********************************************
             * Shared Model injecected into this view.
             */
            [Inject] [Bindable]
            public var sharedModel:SimpleModel;
        ]]>
    </mx:Script>    
</mx:VBox>

   This is a pretty similar like the views on the Basic Injection Example.  A TextInput set with bi-directional binding to the string in the shared model.  The big difference is that there is no <Configure/> tag here.  This view gets added to the context by the Context Config file.  CustomViewTwo.mxml is identical to CustomViewOne, except that the title is changed and the background color is set to a different color.  Other than that they are the same.


   Now let's take a look at the context configuration file.  Here is AutowireContextConfig.mxml:

<?xml version="1.0" encoding="utf-8"?>
    <!---
    This is the file that declares which objects you wish to manage through Parsley.
    Any object declared within the Object Tag will be allowed to participate in any of Parsley's 
    features.  This is a Simple MXML implementation, but this can also be declared in and XML file.
    -->    
<mx:Object
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:spicefactory="http://www.spicefactory.org/parsley"  
    xmlns:model="model.*"
    xmlns:views="views.*"
    >    
<!---    
   Our simple Model that holds the shared String  
-->    
    <model:SimpleModel />    
    
<!--  Here is where I declare the two views that I want Parsley to autowire as soon
as they are added to the display list.  Type is the Class name of the view component -->    
    <spicefactory:View type="{CustomViewOne}" />
    <spicefactory:View type="{CustomViewTwo}" />
    
    <mx:Script>
        <![CDATA[
        /**   Must use import to specify the class of the view */
            import views.*;
        ]]>
    </mx:Script>
</mx:Object>

   The config file is fairly standard.  The new kids on the block are the two <View /> tags that I mentioned towards the beginning of this post.  With the <View/> tag I tell Parsley that I want the view specified in the type parameter to be wired to the context whenever it is added to the stage as a child view of the view that holds this context, in this particular case as a child of AutowireComponents.  Nested contexts still apply.

So let's take a look at the main view file that holds the context. here is AutowireComponents.mxml:

<?xml version="1.0" encoding="utf-8"?>
<!--  This example demonstrates the ability to autowire view components.
  Rather than using <Configure /> in each view component, you can specify the
  view components that you wish Parsley to manage for you in the context config
  file.
  
  For more Flex and Parsley examples visit: http://artinflex.blogspot.com
 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
    xmlns:parsley="http://www.spicefactory.org/parsley" 
    xmlns:views="views.*" width="215" height="140" viewSourceURL="srcview/index.html">

<!---    
    ContextBuilder is how you tell parsley to manage objects.
      Notice that the syntax used is a bit different from the previous examples.
      This is so that I can set the View Settings option to use Autowire.  This
      is not enabled by default. 
-->        
    <parsley:ContextBuilder>
        <parsley:ViewSettings autowireComponents="true" />
        <parsley:FlexConfig type="{AutowireContextConfig}" />
    </parsley:ContextBuilder>
    
    <mx:Label text="Autowire Component Example Ver 1" top="3" fontWeight="bold" horizontalCenter="0"/>
    <!-- Two view components that get added -->
    <views:CustomViewOne top="25" horizontalCenter="0"/>    
    <views:CustomViewTwo top="80" horizontalCenter="0"/>
</mx:Application>

   As mentioned in the comments, the <ContextBuilder> tag is no longer set in one line.  It has two child tags.  <ViewSettings/> that specifies that the components should be wired automatically and the <FlexConfig/> which is the context config file, that we usually set just with the config parameter.

   Not much to it.

Using the autowireFilter option example
   Imagine that you have a fairly large project in which you have many view components.  You would like to programmatically set which views are wired to the Context, let's say by the package they are in, that way you don't have to specify each individual component in your context config file with <View> tags.  Or you wish to apply some condition, any condition to check to see if the view component should get wired to the context or not.

   Well, that's what the autowireFilter option is for.  With it, you can specify a class that will have a specific method that will be called by Parsley in which you receive the view component as a parameter and you just tell Parsley if it should wire that component to the Context.

   So here is the example with view source enabled:



Here is the structure of this project.

   The overall structure didn't change.  I simply added a new file and package.  The new file is the AutowireFilterExample.as file which is a class that extends the DefaultViewAutowireFilter class from Parsley.  So technically it's not just a filter function, it's a filter function inside a filter class.  Other than that, it's the same.

   So let's take a look at what this class looks like:  Here is AutowireFilterExample.as:

package parsleyFilters
{
    import flash.display.DisplayObject;
    import flash.utils.getQualifiedClassName;
    
    import org.spicefactory.parsley.core.factory.ViewSettings;
    import org.spicefactory.parsley.core.view.ViewAutowireMode;
    import org.spicefactory.parsley.core.view.impl.DefaultViewAutowireFilter;

    /*****************************************
     *  This class is the filter that decides whether a view will be 
     * managed or not by Parsley.  When declaring the context you must
     * specify to use the filter class in the ViewSettings section
     * 
     * For more Flex examples visit:  http://artinflex.blogspot.com
     */
    public class AutowireFilterExample extends DefaultViewAutowireFilter
    {
        /******************************
         * The constructor
         */
        public function AutowireFilterExample(settings:ViewSettings=null, excludedTypes:RegExp=null)
        {
            super(settings, excludedTypes);            
        }
        
        /******************************
         * The actual filter function.  It receives a view DisplayObject that
         * Parsley wants to know if it should add or not to it's managed views.
         * I simply get the full qualified class name of the view.  And
         * check to see if it is in the package called "views".  If it is, then it is
         * managed, if not, then it's not.
         */
        public override function filter (view:DisplayObject) : ViewAutowireMode
        {
            var fullClassname:String = getQualifiedClassName(view);
            
            if (fullClassname.indexOf("views::") == 0) 
             {
                return ViewAutowireMode.ALWAYS;
             }
            else 
             {
                return ViewAutowireMode.NEVER;
             }
        }
    }
}

   As you can see, it's fairly simple.  It's a class in which you have to override the public filter() function.  The filter function receives one argument which is a DisaplayObject that Parsley wants to know if it should be wired to the context.  You either return an Always  for yes, or Never for no.  In this particular example I make the decision based on if the view is in the "views" package.  If it is, then wire it, if not, then don't.  Parsley calls this method for every view that is a child of the view holding the context, and also for the view that holds the context itself.

  So what else is new?  Well, in the context config file I removed the <View> tags as these are no longer needed.  Here is the AutowireContextConfig.mxml file:

<?xml version="1.0" encoding="utf-8"?>
    <!---
    This is the file that declares which objects you wish to manage through Parsley.
    Any object declared within the Object Tag will be allowed to participate in any of Parsley's 
    features.  This is a Simple MXML implementation, but this can also be declared in and XML file.
    
    The views are now longer specified as they are handled through the AutowireFilter
    -->    
<mx:Object
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:spicefactory="http://www.spicefactory.org/parsley"  
    xmlns:model="model.*"
    xmlns:views="views.*"
    >    
<!---    
   Our simple Model that holds the shared String  
-->    
    <model:SimpleModel />
</mx:Object>

   As stated, just the <View> tags were removed, and the script section as the imports where no longer needed.

   The only other file that was changed is the main file where the context is created.  Here is AutowireComponents.mxml:

<?xml version="1.0" encoding="utf-8"?>
<!--  This example demonstrates the ability to autowire view components.
  Rather than using <Configure /> in each view component, you can specify the
  view components that you wish Parsley to manage for you in the context config
  file.
  
  For more Flex and Parsley examples visit: http://artinflex.blogspot.com
 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
    xmlns:parsley="http://www.spicefactory.org/parsley" 
    xmlns:views="views.*" width="215" height="140">
    <mx:Script>
        <![CDATA[
            import parsleyFilters.AutowireFilterExample;
        ]]>
    </mx:Script>

<!---    
    ContextBuilder is how you tell parsley to manage objects.
      Notice that the syntax used is a bit different from the previous examples.
      This is so that I can set the View Settings option to use Autowire.  This
      is not enabled by default. 
-->        
    <parsley:ContextBuilder>
        <parsley:ViewSettings  autowireComponents="true" autowireFilter="{new AutowireFilterExample()}" />
        <parsley:FlexConfig type="{AutowireContextConfig}" />
    </parsley:ContextBuilder>
    
    <mx:Label text="Autowire Component Example Ver 2" top="3" fontWeight="bold" horizontalCenter="0"/>
    <!-- Two view components that get added -->
    <views:CustomViewOne top="25" horizontalCenter="0"/>    
    <views:CustomViewTwo top="80" horizontalCenter="0"/>    
</mx:Application>

   The only new addition to this file is the autowireFilter parameter in the <ViewSettings> tag.  You just assign a new instance of the class you created that extends Parsley's DefaultViewAutowireFilter class.  It's fairly simple to set up.

   Well, I do hope that you found this post useful.

   Next -> Fast Inject.  Injection without Reflection.

Wednesday, October 27, 2010

Flash Builder Burrito & Flex Hero Pre-release Available now

   In case you aren’t aware, Adobe Max Conference in LA is going on right now, this is where Adobe shows their cool new stuff and where you can go and learn a bunch of stuff. In the Keynote Adobe emphasized the concept of publishing to all kinds of devices, tablets, phones, Blue-ray Players, and TV’s. Yes, Samsung will be releasing a TV that runs Adobe Air. It’s nice to see that Adobe isn’t standing still and it’s finally moving forward into the device market, so you can continue to Flash on.

   With this announcement they released publicly the Flash Builder Burrito preview. Flash Builder Burrito is the “next” Flash Builder. It’s pretty stable and it has some new features that should have been there so long ago, but it’s nice to have them finally. For example you get snipplets, code completion on Metadata tags, generate functions and more.

   It also includes a pre-release Flex Hero SDK (which is Flex 4.5 SDK). Flex Hero is supposed to be able to run on Devices, and Flash Builder Burrito actually let’s you start projects specifically for Devices. Flex Hero is not complete, but there is enough to get you started. It does have some neat features to help you build UI’s for devices. It also has support for TLF2, a new Spark Image and a new Spark Data Grid.

   I like the new features of “Burrito” and I have already made use of the new Spark Image. It’s pretty sweet. You can have one or more master content loaders, which you can use to cache content, or queue content loading, and actually set priority to the queue. These features are great for me, as I have run into the issue of loading thumb images before.

   Also with Flash Builder Burrito, they release Flash Catalyst Panini. The new “great” thing about Panini is that it’s now finally possible to create a project in Catalyst “Panini”, sent it to Flash Builder, send it back to Catalyst, send it back to Builder… you get the point. Round tripping is finally possible.

With Burrito you get a 60 day trial, which you can extend if you have a valid Flash Builder 4 key.
With Panini you get a 30 dary trial, which you can extend with a valid Suite CS5 key or a Catalyst key.

You can watch the keynotes of Max and some other session here: http://max.adobe.com/online/

You can also download:
Flash Builder Burrito here: http://labs.adobe.com/technologies/flashbuilder_burrito/
Flex Hero (4.5) SDK here: http://labs.adobe.com/technologies/flexsdk_hero/ which is included in Burrito
Flash Catalyst Panini here: http://labs.adobe.com/technologies/flashcatalyst_panini/

  Happy coding!

Saturday, October 23, 2010

Quick Dive into Parsley (Dynamic Command & Dynamic Object - Part 8)

This is part of a series of articles that should get you up and started using Spicesfactory's Parsley.
This is part 8.
In Part 3, I showed how to set up Parsley and showed a basic injection example.
In Part 4, I showed how to send messages using Parsley that do not extend the Event class.
In Part 5, I showed how to send messages using Flex Events.
In Part 6, I showed nested contexts and object lifecycle methods.
In Part 7, I showed Decoupled Bindings

This article builds upon what was covered in the previous examples, so if you haven't seen them, I encourage you to start with at the beginning of this series.  This article focuses on Parsley's Dynamic Commands and Dynamic Objects.

Parsley’s Dynamic Command & Dynamic Object
  Parsley offers two very useful short lived objects:  the <DynamicCommand> and the <DynamicObject>.  Short lived objects are those who aren’t persistent during the life of the context.  They are created, used, and destroyed, once or multiple times during the life of their context.  You could also call them non-singleton.  Let’s take a closer look to each one.

Dynamic Command
  Parsley’s Dynamic Command is a built in implementation of the MVC’s Command.

   For those not familiar with MVC (Model View Controller), here is a very short summary of what the purpose of Command.  The main goal of MVC is to create decoupling, in which you break the application into three main sections.  The View which holds your User Interface elements, the Model which holds your data, and the Controller which gets and puts data into the model.  The Command is part of the Controller.

   The key concept is that the View (the the UI components) really should not care where the data comes from, that being a local database, an ASP page, php, Remote Object, WebService, local object, etc… It should worry only about interacting with the User.  This is useful since it keeps your view components cleaner, easier to debug, and it certainly makes it easier to: Reuse the View component, Reuse the data acquiring/saving code, swap the view component, and swap the data acquiring/saving code.  So under the MVC concept, the view simply dispatches a message in which it requests the acquiring of data or saving of data, how that is performed is not it’s problem.

  Getting and saving data is the Controller’s job.  Most MVC implementations have a concept of a Front Controller.  The front controller’s job is to receive the messages dispatched (most likely from the View) and to invoke specific Commands to execute the request, that being either: acquiring data from where it should, or saving the data.

   When you use Parsley’s <DynamicCommand>, you do not need to create your own Front Controller, since Parsley and its Context take the job of the Front Controller.  Whenever you dispatch a message of a specific type, Parsley will create an instance of the specified Command Class type, and it will call it’s execute method.  When done, it destroys that instance automatically, hence it is short-lived.

   In Parsley, Command Classes do not need to implement any interface, nor they need to extend any class.  They simply have to have at bare minimum a method called execute() that receives one parameter of the associated message type.

At a bare minimum a Command class in Parsley would look like:

package commands
{
    public class MyCommand
    {
        public function execute (message:MyMessage) : void
         {
            // Do something
         }
    }
}

In your context config file you must declare the Dynamic Command with the <DynamicCommand> tag:

<spicefactory:DynamicCommand type="{MyCommand}"
             selector="A Specific Request" />

   If you pay close attention, there is nothing in the context config file that associates the specific command with the message type.  That is because Parsley figures this out automatically.  Parsley reads that you wish to create a DynamicCommand of the class type “MyCommand”.  It looks into that class for a public method named execute.  It then looks at the parameter type that is expected by the execute method and then it associates that parameter type as a message, with that command.  So whenever a Parsley managed message is dispatched with that parameter type, Parsley automatically creates an instance of the DynamicCommand type, calls it’s execute method and passes the message as the parameter.

   So what is this “selector”.  Parsley’s DynamicCommand was designed to be used with or without standard Events.  All events have an event type property.  What selectors allow you to do, is to have the same message type (class) and invoke different commands depending on the selector.

   For example you could have a UserSettingsMessage class that has some properties that would be the same, regardless if you save the user settings or retrieve the user settings.  So you could have a “SAVE User Settings” selector, and a “GET User Settings” selector that invoke different commands with the same Message type.

  In Parsley the selector does not have to be a string type, nor it actually has to be called type.  That’s just the default.  As long as it returns a value that can be compared by value and not by reference it can be called anything.  So selectors can be Number, String and Integers, but I would stick to Strings and Integers.  In your message class, you just use the [Selector] tag in front of the property you wish to be the selector and Parsley does the rest.
Since Parsley’s DyanmicCommand is a managed object, it can participate in all of Parsley’s features, including Messaging and Injection, which takes us to Dynamic Objects

Dynamic Object
   Parsley’s Dynamic Object aren’t associated in any way with Dynamic Commands, they simply work well together.   Dynamic Objects can be any non-view classes that you wish to have Parsley manage, but you do not want them to be persistant.  A standard managed object of Parsley is instantiated when you inject its class type into any other Parsley managed object or view, but that instance remains persistent, if you inject the same class within the same context the same instance is injected in each injection, basically being shared.  This is also called singleton, as it’s a single instance.

   Dynamic Objects are not persistent.  Each injection of that class type creates a whole new instance, something akin of using new() on each injection.

   You might be wondering, why in the world would you just not simply use new() then?  Well, couple of reasons.  First; since it is a Parsley Managed object, that class can participate in any of Parsley features, so it can itself have injections and do Messaging, receive and send.  Second; when using Interfaces, it is easy to swap out the Real class in all places where you Inject that Interface.  You just change it in the context config file once.

Ok, enough background info, let’s look at how this actually works.

The Examples
I want to set some things straight:

First:  This is NOT a complete MVC implementation.  It is focused primarily on the Controller side.  The Model and View are extremely simple to keep the focus on the Controller and the Command.  I will later show a complete MVC example with Presentation Model.
Second:  There is no one single way to implement Controllers and Commands the "right way".  The right way depends on many things.  Don’t forget that the goal is to make things simpler by decoupling, but don’t forget to keep things simple.

  Generally speaking, Commands usually invoke services, as the command itself is not the service.  The Service will be either a Remote Object call, a WebService, or a HTTPService for example.  You can instantiate new services within the command or Inject Services to the Command.  I particularly like Injecting services into the command as it makes it simpler to swap out the service, with little or no change to the Command.  In Cairngorm, for example, Commands usually invoke “Delegates” which have the services in them, it’s a little extra step that you might consider.

   Another decision to make is who should handle the result from the request of the service.  The Service itself or the Command?  Both have their pros and cons.  If you wish to have the Service handle the result, then you must extend the service and create your own class that has the result handler in it, or use the Delegate concept.  If the Command handles the result, then the Command gets tied to that service implementation.

  There is no one perfect answer.  You should consider your implementation on the following:  How likely are you to use this application with a different server technology, or update your communication protocol with the server.  If you think that there is a fair chance of you implementing a different server technology or move from XML to JSON or AMF, or something of your own, I would suggest having the Service handle the result.

   Well, just to keep everyone happy, I’ve implemented both here.  Two examples of the same thing, one with the Service handling the result, and the other with the Command handling the result.

   Ok, this is a very simple RSS reader, and I really mean simple, the view and the model are as simple as they can get, and it was only tested with the RSS feed from this blog, but it should work with any other blogspot RSS feed.  For those unfamiliar with what an RSS feed is, it’s a feed used to publish frequently updated work.  More info on Wikipedia (http://en.wikipedia.org/wiki/RSS).  RSS feeds are returned in XML, and I did almost no parsing of the XML, just the bare minimum, as the focus here is not to create a full RSS reader, but look on how to implement a <DynamicCommand>.  In the real world, I would very rarely store XML data in my model.  One of the great things about Flex is that it lets you prototype so easily.

The Service handling the result example:
Here is the running version of the Service handling the result. View Source is enabled.

NOTE: I had to make a quick change to the examples.  After I posted the example I realized that blogger's crossdomain.xml file doesn't allow for swf's hosted on other domains to read the RSS feed.  I resolved the issue by reading the RSS feed through "Feed burner" (http://www.feedburner.com).



Now let take a look at the structure of the project.

   This project has the basic structure of an MVC project, where you have models, views, and the controller all independent from each other.

   We have one Command which is the GetRssFeedCommand class.

   We have one Message which is the GetRSSFeedMessage class.  When we dispatch this message, the GetRssFeedCommand should be instantiated, and have its execute method called.

   Our Model is very simple, it’s the RssFeedModel.  The model will store the result from the service invoked by the command.  The view will be bound to a property of our model, so whenever the model gets data, so will our view.

   In regards to the service, there are two classes.  One is an Interface, called IRssService.  Interfaces are not requiered, it simply makes it much easier to swap out the real service class if we wish to.  For example we could have a mockup Service class that fakes getting data and we could quickly swap it latter.  The real service class is the RssXMLHttpService class.  That is the class that connects and gets the data.

   The view, well, I stuck the List component in the main component called DynamicCommandExample, so the main file is the view.  I have simply one item renderer for the List which is called RssFeedItemRenderer.


Of course we also have our Context configuration object, which is called DynamicCommandContextConfig.

Now let’s go into the details.

Let's start of with the Context config file which actually makes this work.  Here is DynamicCommandContextConfig.mxml:

 <?xml version="1.0" encoding="utf-8"?>
    <!---
    This is the file that declares which objects you wish to manage through Parsley.
    Any object declared within the Object Tag will be allowed to participate in any of Parsley's 
    features.  This is a Simple MXML implementation, but this can also be declared in and XML file.
    -->   
<mx:Object
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:spicefactory="http://www.spicefactory.org/parsley" 
    xmlns:models="models.*"
    xmlns:services="services.*" xmlns:local="*">
<!---   
   Our simple Rss Model that holds the results 
-->   
    <models:RssFeedModel />

<!---
   Here is the Service that we ask Parsley to use.  Since this service implements
   IRssService, Parsley figures out that it should inject this service whenever 
   an Injection request for IRssService is made.
   Notice that I've declared the Service as a DynamicObject.  This means that a new
   instance will be created every time it is injected, and when the reference to this
   instace is finished, the old instance is removed.  Type is the name of the class
   you wish to have created.
   Alternatively I could have declared it as a "Singleton" in the sense that once
   created it remains during the life of this context.  When using Soap WebServices
   I always use the singleton aproach so that the wsdl only downloads once.
   Using the singleton aproach the declaration should be:  
   <services:RssXMLHttpService />
-->   
    <spicefactory:DynamicObject type="{RssXMLHttpService}" />
<!---
  This is the declaration for the Dynamic Command. DynamicCommands are created automatically
  when a message of the type of the parameter received by the execute method is dispatched.
  type is the name of the class that you wish to have invoked.  Selector is the specific
  identifier so that you can have more than one message of the same message class dispatched
  and the selector let's you select wich dynamic command is associated with it.  I use
  public static const so that it is obvious wich message class is associated, although
  it is obtained by Parsley from the parameter of the execute method.
  You can also specify the name of the execute method, if it's not execute, but I would
  discourage you to do so.  Execute is standard across all MVC frameworks.
 -->   
    <spicefactory:DynamicCommand type="{GetRssFeedCommand}" selector="{GetRSSFeedMessage.REQUEST_FEED}" />
    
    <mx:Script>
        <![CDATA[
/*         The imports are necesary for the { } class usage */        
            import messages.GetRSSFeedMessage;
            import commands.GetRssFeedCommand;
            import services.RssXMLHttpService;
        ]]>
    </mx:Script>   
</mx:Object>

  Although not obvious in the declaration (it is in the comment), when the GetRSSFeedMessage is dispatched that’s when GetRssFeedCommand is instatiated.  This is one thing I don’t like about Parsley’s implementation of the DynamicCommand.  I feel that it is really cool that it figures it out automatically from the parameter type expected in the execute method, but I have to go dig for it if I don’t remember it.  That’s why I try to make it obvious in the selector attribute, but keep in mind that they don’t actually have to be related, to Parsley the specified selector in the <DynamicCommand> declaration is just a value to look for.

Now let’s take a look at the message that will be dispatched.  Here is GetRSSFeedMessage.as:

package messages
{
    /********************************************************
     * This is the message that is instatiated and dispatched.
     * It is meant to request an RSS Feed.
     * Parsley uses primarely the class type to select what Command
     * to execute, but it recognizes that you could also have the same
     * class and wish to invoke different Commands depending on some 
     * values of this class.  So it also uses a selector property of this class.
     * Somewhat similar to the Event type selector, but without the same limitations.
     *
     * For more Parsley Examples visit artinflex.blogspot.com 
     */
    public class GetRSSFeedMessage
    {        
        /*************************
         * This will be the selector type.  Notice that it doesn't have
         * to be a String, but use types that are compared by value by default.
         */
        public static const REQUEST_FEED:int = 1;        
        
        /*****
         *  Internal type holder 
         */
        private var _type:int;

        /***********************
         * Constructor that receives the type 
         * @param requestedType the type selector for this message 
         */
        public function GetRSSFeedMessage(requestedType:int)
        {
            _type = requestedType;
        }
        
        /***********************
         *  In parsley the Selector can be any property name.  You must use
         * types that are easily compared by value and not by reference. 
         * You simply tag the property with the Selector tag to indicate to
         * Parsley that this is the property you wish to use as selector. 
         */
         [Selector]
        public function get type():int
         {             
             return _type;
         }
    }
}

In this example I used the property name type as the selector, which is fairly standard, but you can name it whatever you want.  Just make sure you use the [Selector] tag to let Parsley know which property you want to use.  Also here is the public static const to help me identify the message class in the context config file mentioned earlier.

   Now, let’s look at the simple model, this is where the data will be stored. Here is RssFeedModel.as:

package models
{
    /*****************************************
     *  This is a very simple model that holds an XMLList to hold the
     * result from the RSS Feed service request.  It will be bound by a
     * mx::List to get the values.  
     *
     *  For more Flex and Parsley examples visit: artinflex.blogspot.com 
     */
    public class RssFeedModel
    {        
        /************************************
         *  The list that holds the rss feed.  It is bindable 
         */
        [Bindable]
        public var feedXML:XMLList;
    }
}

   Nothing special in our model. It simply has a property called feedXML that will hold the data. I would usually not hold data as an XMLList but I wanted to keep this simple.

Let’s move on to the Command.  Here is GetRssFeedCommand.as:

package commands
{
    import messages.GetRSSFeedMessage;    
    import mx.rpc.AsyncToken;    
    import services.IRssService;
        
    /*********************************************************
     * This is a short lived dynamic command class.  In parsley Commands are
     * normaly created when a message is dispatched of it's expecting type.
     * Once created the execute method is called and passed the argument.
     * This command injects a service interface and proceeds to call
     * the service methods.
     * Once the command completes it is automatically destroyed unless specifically
     * told not to.
     *
     * For more Parsley and Flex Examples visit artinflex.blogspot.com 
     */
    public class GetRssFeedCommand
    {
        /*********************************
         * The service is injected through an Interface.  This makes it easy
         * to swap out the service with a different class.  Parsley figures 
         * automatically out through reflection wich of it's manage object 
         * should it inject by determining which classes implement this 
         * interface. 
         */        
        [Inject]
        public var service:IRssService;
        
        /*********************************
         * Once Parsley creates this command object and performs it's injections,
         * it proceeds to call the execute method.  You can tell Parsley to call
         * a different method, but this is discouraged.  The execute method
         * can return an AsyncObject.
         * Parsley determines which command to execute by the object
         * type of the parameter of this execute method.
         * 
         * @param message is the message sent.  It's type is used to determine
         * which command to execute. 
         */        
        public function execute (message:GetRSSFeedMessage) : void
         {        
            service.readRssXMLFeed("http://feeds.feedburner.com/ArtsFlexNotes");
         }
    }
}

   This command class is actually pretty simple, and most of them will usually be simple.  In this version of the command, handling the result is taken care of by the service.  Commands may have more complex logic.  For example, they might check if the model already has this data, and not go to a service to get it again (if you know it won’t change), they might also decide where they will go get the data, etc…  Also Commands are not just about getting data, they also save data, process data, etc…  For example you might have complex and dynamic Validators implemented as commands.

Now this command is relying on a service.  Since the command is managed by Parsley it can Inject, as show and it Injects the IRssService, which Parsley fills in with RssXMLHttpService  because it knows that RssXMLHttpService implements IRssService through its inspection/reflection process.

First Let’s take a look at the Interface IRssService.as:

package services
{
    import mx.rpc.AsyncToken;
    
    /*********************************************
     * This interface is used to read RSS Web Services
     * Using Interfaces makes it easy to switch the actual
     * Service classes.
     */
    public interface IRssService
    {
        /**********************************************************
         *  This function will send a request to read an rss xml feed and
         * store the result in the feedModel
         * @param rssURL the url of where the RSS feed can be found.
         * @return The call's AsyncToken in case the command wants
         * to add it's own handlers 
         */
        function readRssXMLFeed(rssURL:String):AsyncToken;
    }
}

   The interface just defines the methods that the Command will need to access.   In this case it has a method named readRssXMLFeed() that expects the URL of the feed.  Notice that the definition specifies that the service returns an AsyncToken.  In this implementation of the Command, the AsyncToken returned is being ignored, but on the following example it will be used.

So let’s look at the real service itself.  Here is RssXMLHttpService.as:

package services
{
    import models.RssFeedModel;    
    import mx.controls.Alert;
    import mx.rpc.AsyncToken;
    import mx.rpc.IResponder;
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.rpc.http.mxml.HTTPService;

    /***********************************************************
     *  This is a simple RSS consumer service class that will read an
     * RSS Feed.  I used the MXML version simply because it has
     * the showBusyCursor property that I like.  It displays a hour
     * glass while it submiting the request.
     * @author Arturo Alvarado
     * For more Flex and Parsley examples visit artinflex.blogspot.com
     */
    public class RssXMLHttpService extends HTTPService implements IRssService,IResponder
    {
        /***********************************
         * This is the model that we will place the feed that we will receive.
         * The view will get the data from the model 
         */
        [Inject]
        public var modelRssFeed:RssFeedModel;
        
        /*********************************************
         * Constructor 
         */
        public function RssXMLHttpService(rootURL:String=null, destination:String=null)
        {
            super(rootURL, destination);
            showBusyCursor = true;
        }
        
        /****************************************
         *  This function will send a request to read an rss xml feed and
         * store the result in the feedModel
         * @param rssURL the url of where the RSS feed can be found.
         * @return The call's AsyncToken in case the command wants
         * to add it's own handlers 
         */
        public function readRssXMLFeed( rssURL:String):AsyncToken
        {
            this.url = rssURL;
            this.resultFormat ="e4x"
            
            var call:AsyncToken = this.send();
            call.addResponder( this);
            return call;
        }
        
        /*************************************
         *  This is the result handler it takes the result from the http
         * request and stores and XMLList of all the nodes taged with <item></item>
         * into the  model
         * @param data is the result object that we will make sure it's a Result Event        
         */
        public function result(data:Object):void
        {
            if (data is ResultEvent)
            {
                var event:ResultEvent = data as ResultEvent;
                modelRssFeed.feedXML = XML( event.result )..item
            }
        }
        
        /******************************************
         *  Fault handler in case the request failed. 
         * @param info object that contains the Fault data. 
         */
        public function fault(info:Object): void
        {
            var event:FaultEvent = info as FaultEvent;
            Alert.show(event.fault.message,event.fault.faultDetail);
        }
    }
}

   This service is a Parsley managed object.  Recall from the Context configuration file that we specified it to be a Dynamic Object, which means that a new instance will be created, used and destroyed each time a Command Injects it.  This has the benefit of using fewer resources while the service isn’t being used.  When using Soap Web Services you might wish to reconsider this approach, and leave either the service or something from it, persistent, that way you don’t have the service request a wsdl file every time you wish to make a request.

   This service handles the result and fault.  Since it does implement IResponder, it can assign itself as a Responder to the AsyncToken returned.  I like this approach better than the addEventListener() / removeEventListener() approach for handling results and faults.

   In this case, being managed by Parsley means that it can Inject the model, which it does, and store the result in the model, which it does.

   Normally, I would have a defined a ValueObject  (in case you are not familiar with the term ValueObject check out: http://blog.tsclausing.com/post/10) with the fields I’m interested in.  I would create an instance of that value object, assign the values obtained from the Feed’s XML to that instance and push that instance to an Array, ArrayList, or ArrayCollection in the Model..

So that’s the backend of our app.  Let’s look at the View.  The view is made up by two components, the Main app, called DynamicCommandExample, and by an Item Renderer named RssFeedItemRenderer.

Let’s take a look at DynamicCommandExample.mxml:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
    xmlns:parsley="http://www.spicefactory.org/parsley"     viewSourceURL="srcview/index.html">

<!---    
    ContextBuilder is how you tell parsley to manage objects that are not Views. 
    In this case I'm instructing Parsley to load the DynamicCommandContextConfig file which
    has the "list" of objects you wish to have managed, including the definition of
    the dynamic command.
-->    
    <parsley:ContextBuilder config="{DynamicCommandContextConfig}" />
    
<!---
   I want Parsley to manage this view, as it will hold the mx:List that will display
   the feed and I wish to pass the models data provider, though Injection.  Normaly
   I would not do this in the main app, but the focus of this example is the Dynamic Command
   and really wanted to keep the view part very simple. 
 -->    
    <parsley:Configure />
    
<!---
   The button that requests the feed.
-->
    <mx:Button x="10" y="10" label="Retrieve RSS Feed" click="requestFeedButtonClickHandler()"/>

<!---
  The list that displays the feed result.  This does not have to be on the same view
  as the requesting part. It binds to a property of the model.
-->
    <mx:List x="20" y="40" width="389" height="321"
         dataProvider="{modelRssFeed.feedXML}"
         itemRenderer="views.RssFeedItemRenderer"></mx:List>
            
    <mx:Script>
        <![CDATA[
            import models.RssFeedModel;
            import commands.GetRssFeedCommand;
            import messages.GetRSSFeedMessage;
            
            /*********************************************************
             * The dispatcher function injected so that we can request the
             * feed and Invoke the command by dispatching a Message.
             */
             [MessageDispatcher]             
            public var dispatcher:Function;
            
            /*******************************************************
            * The model that we will use to set the data provider of the list.
            * The model receives the data from the service invoke by the command.
            */
            [Inject] [Bindable]
            public var modelRssFeed:RssFeedModel;
            
            /*******************************************************
            * This function get's executed when the button is clicked to 
            * request the feed.  Notice that there is no reference to the command
            * nor the model.  This view has no reason to know who or how will get the
            * data.  Is it from a local database, is it from a feed, is it an XML local
            * file.  That is all irrelevant to this view, all it does is say it wants
            * the data and dispatches a message to request it.  Parsley takes over from
            * there.
            */
            public function requestFeedButtonClickHandler():void
            {
                dispatcher(new GetRSSFeedMessage(GetRSSFeedMessage.REQUEST_FEED));
            }
        ]]>
    </mx:Script>    
</mx:Application>

   This view is doing more than usual for being the Main file, but it is fine for this example.  This view holds the Context, it is also configured for this context so that it can participate, so it has a <ContextBuilder> tag and a <Configure> tag.

   The view has a button that when pressed it simply dispatches a new GetRSSFeedMessage of the REQUEST_FEED type.  As you can see, it doesn’t know anything about the Command or the Service.  It just wants data and it dispatches a messages asking for it, no matter where It comes from.

   As this is a very simple view, I have a list that displays the results that is bound directly to the shared model’s feedXML property.  It is notified of data being received through standard Flex binding.  While this is ok in small projects or prototypes, I would suggest using Parsley Messaging to notify the view of the results.  One inherit problem of using this approach is that the view will only get notified if data was changed, but if the request brought an empty result, the view would not know about it and the user could think that the application hung.  At a later time I’ll show a “better” way of doing this.

   Finally, this list uses a custom item renderer to display the data.  Here is RssFeedItemRenderer.mxml:

<?xml version="1.0" encoding="utf-8"?>
<!---
This is the Item Renderer for the List.  It isn't designed to look good.
It is designed to be simple to view the code.  Normally, I would assign
this to a VO and bind the properties to the VO so I can have proper 
compiler checking, but for this example it bound to the xml.  When run 
under debug mode you will get warnings that proper binding was not achieved 
since you can’t bind to XML objects.

For more Flex & Parsley examples visit artinflex.blogspot.com
-->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml"
    verticalGap="0"
    horizontalScrollPolicy="off"
    verticalScrollPolicy="off"    
    >
 <mx:Script>
        <![CDATA[        
            /***************************************************
             * Using namespace makes it a bit easier to parse xml
             * The updated field of the xml uses the atom namespace
             */         
            namespace atom = "http://www.w3.org/2005/Atom";
            use namespace atom;

            /***************************************************
             * This function should really be used to set a VO
             * so that you can bind to known properties.  Here
             * I simply used it to help me view the contents of
             * the xml rss feed to find out the properties.
             * Data tipically receives an Object that you should
             * assing it to a local var of a know Value Object
             * @param value  The data passed by the dataprovider
             * it is one record of the list.
             */
            override public function set data(value:Object):void
            {
                super.data = value;
            }
        ]]>
    </mx:Script>
    
   <mx:Label 
        width="100%"        
        fontWeight="bold"                
        text="{data.title }"
        selectable="false"  />    
    <mx:Label 
        width="100%"
        text="Publish Date: {data.pubDate}"
        selectable="false"  />       
       <mx:Label
           width="100%"
          text="Author: {data.author}"
          selectable="false"  />
    <mx:Label
        width="100%"
        text="Last Updated: {data.updated}"
        selectable="false"  />
    <mx:Label
        width="100%"
        text="Link: {data.link}"
        selectable="true"  />                    
</mx:VBox>

   When it comes to the item renderer, there isn’t anything really special other than the namespace declaration.  As mentioned earlier, normally I would not be passing XML, much less raw XML to an item renderer, just keeping it simple.

   Well that’s it, now let’s look at the other version.

The Command handling the result example:
   Here is the running version of the Command handling the result. View Source is enabled.


   Here is the Structure of this version of the example:

   As you can see, there isn’t any apparent difference between these two.  In fact, there really isn’t a whole lot.  The overall structure is basically the same, although using the interface for the service is a bit less useful.  This is because swapping the service might have an effect on the content of the result, which means that your result handler in the Command must be able to handle the new result format.  You could write code in the command that could check the result, figure out the format and process it accordingly, but I would honestly only consider that in the case that you really were planning on swapping the Service in a regular fashion or at runtime.

   The only two classes that changed are RssXMLHttpService and GetRssFeedCommand, everything else is exactly the same.

   I’ll start off with the service.  Here is RssXMLHttpService.as:

package services
{
    import mx.rpc.AsyncToken;
    import mx.rpc.http.mxml.HTTPService;

    /***********************************************************
     *  This is a simple RSS consumer service class that will read an
     * RSS Feed.  I used the MXML version simply because it has
     * the showBusyCursor property that I like.  It displays a hour
     * glass while it submiting the request.
     * @author Arturo Alvarado
     * For more Flex and Parsley examples visit artinflex.blogspot.com
     */
    public class RssXMLHttpService extends HTTPService implements IRssService
    {        
        /*********************************************
         * Constructor 
         */
        public function RssXMLHttpService(rootURL:String=null, destination:String=null)
        {
            super(rootURL, destination);
            showBusyCursor = true;
        }
        
        /****************************************
         *  This function will send a request to read an rss xml feed and
         * store the result in the feedModel
         * @param rssURL the url of where the RSS feed can be found.
         * @return The call's AsyncToken in case the command wants
         * to add it's own handlers 
         */
        public function readRssXMLFeed( rssURL:String):AsyncToken
        {
            this.url = rssURL;
            this.resultFormat ="e4x"
            
            var call:AsyncToken = this.send();            
            return call;
        }        
    }
}

   The difference between this one and the previous one is that this one doesn’t handle the result or fault.  It simply returns the AsyncToken to the caller.  It also no longer needs to Inject the Model into it.  Since Injection is no longer needed, there is also no need to have this class to be managed by Parsley.  In this example it still is, but there really isn’t a need for it anymore.  The only benefit as it stands, it’s the ease of swapping it, but don’t forget that it could affect your Command.

   Now let’s look at the Command, here is:  GetRssFeedCommand.as:

package commands
{
    import messages.GetRSSFeedMessage;    
    import models.RssFeedModel;    
    import mx.controls.Alert;
    import mx.rpc.AsyncToken;    
    import mx.rpc.events.FaultEvent;    
    import services.IRssService;
        
    /*********************************************************
     * This is a short lived dynamic command class.  In parsley Commands are
     * normaly created when a message is dispatched of it's expecting type.
     * Once created the execute method is called and passed the argument.
     * This command injects a service interface and proceeds to call
     * the service methods.
     * Once the command completes it is automatically destroyed unless specifically
     * told not to.
     *
     * For more Parsley and Flex Examples visit artinflex.blogspot.com 
     */
    public class GetRssFeedCommand 
    {
        /*********************************
         * The service is injected through an Interface.  This makes it easy
         * to swap out the service with a different class.  Parsley figures 
         * automatically out through reflection wich of it's manage object 
         * should it inject by determining which classes implement this 
         * interface. 
         */        
        [Inject]
        public var service:IRssService;
        
        /***********************************
         * This is the model that we will place the feed that we will receive.
         * The view will get the data from the model 
         */        
        [Inject]
        public var modelRssFeed:RssFeedModel;
        
        /*********************************
         * Once Parsley creates this command object and performs it's injections,
         * it proceeds to call the execute method.  You can tell Parsley to call
         * a different method, but this is discouraged.  The execute method
         * can return an AsyncObject.
         * Parsley determines which command to execute by the object
         * type of the parameter of this execute method.
         * 
         * @param message is the message sent.  It's type is used to determine
         * which command to execute. 
         */        
        public function execute (message:GetRSSFeedMessage) : AsyncToken
         {        
            return service.readRssXMLFeed("http://feeds.feedburner.com/ArtsFlexNotes");
         }
        
        /*************************************
         *  This is the result handler it takes the result from the http
         * request and stores and XMLList of all the nodes taged with <item></item>
         * into the  model
         * @param data is the result object that we will make sure it's a Result Event        
         */
        public function result(data:Object):void
        {
            if (data is XML)
            {                
                modelRssFeed.feedXML = XML( data )..item
            }
        }
        
        /******************************************
         *  Fault handler in case the request failed. 
         * @param info object that contains the Fault data. 
         */
        public function error (info:Object): void
        {
            var event:FaultEvent = info as FaultEvent;
            Alert.show(event.fault.message,event.fault.faultDetail);
        }        
    }
}

   Well, the obvious change is that it must handle the result and fault from the service as it is no longer handled by the service and of course you must inject the Model.  But look closely, there are a few more differences.

   First off, the execute method no longer returns a null, it is actually returning an AsyncToken, the same AsyncToken returned from the Service.  Why in the world would I want to do that?  If we didn’t invoke the execute() method directly, what is actually receiving the returned AsyncToken?  Well, that’s a nice little trick up Parsley’s sleeve.   Notice that I didn’t add any responders, nor I added any event listeners?  How does the result() method get called?

   Well, Parsley itself is invoking the execute() method of the command and when it receives an AsynToken it goes ahead and looks in your Command to see if you have a method called result() that is expecting an Object, and it also checks to see if you have a method named error() that is also expecting an Object, and calls them accodingly.  Don’t ask me why Jens (creator of Parsley) decided not to go with the standard fault(), and used error(), no clue.  But if you really want to use anything else and not error(),  you can tell Parsley in the Context Config file to use a different name.

  Now, also notice that the result handler isn’t exactly the same as the result handler in Service from the previous version of this example.  Parsley actually does some cleaning up for you, and it doesn’t actually send a ResultEvent.  It actually sends the ResultEvent’s result property, something like: "ResultEvent(event).result".  This way you don’t actually have to typecast to ResultEvent since that’s actually not what you get as the parameter to your handler, you get the result of the ResultEvent.  Hope I didn’t make something that is simple, confusing.

   The error() handler is basically the same as a standard fault handler, with the exception of the name change.

   Now I mentioned that you can change the name of the methods invoked automatically in the DynamicCommand by Parsley.  It’s actually fairly simple.  In your Context config file, where you declare your DynamicCommand you just specify it.  Here is an example:
<DynamicCommand
    type="{SaveUserCommand}"
    selector="save"
    execute="executeSaveUser"
    result="handleSaveUserResult"
    error="handleFault"
/>

   Parsley also offers a more unique (not very standard) way of doing Commands.  It is called the "Asynchronous Command Methods".  It is based on using tags in front of methods to act as Commands.  The cool factor is that you don’t have to create a Command class.  You can place these tags in any Parsley managed object.  I particularly like the Short-lived Dynamic Command approach better, simply because it is much more organized.  Having Command handlers anywhere, can lead towards massive confusion and a complete pain to follow the code.

   You can read more about the Parsley’s Commands in section 6.9 Asynchronous Command Methods and in section 6.10 Short-lived Command Objects in the docs.

   I’m sure some might wonder which approach is better, the first or second demonstrated here.  “Better” is such a subjective word.  What is better for me is not necessarily better for you.

   I like the first approach over the second one.  As neat as the automatic call to the result handler in the Command might be, it can be confusing to someone familiar with Flex and not familiar with Parsley’s DynamicCommand.  The boilerplate code saving is truly minimal.

   I really like the ability to change my server side technology with little to almost no impact on the client side.  Over the years, we have improved our communication between the client and server side, and I really like having things organized in a way that it makes it really simple to do so.

   Well, I certainly hope that this was useful.  It’s a great feature available in Parsley.

   Next -> Parsley's Automatic Component Wiring examples.

Saturday, October 9, 2010

Quick Dive into Parsley (Decoupled Bindings - Part 7)

This is part of a series of articles that should get you up and started using Spicesfactory's Parsley.
This is part 7.
In Part 3, I showed how to set up Parsley and showed a basic injection example.In Part 4, I showed how to send messages using Parsley that do not extend the Event class.
In Part 5, I showed how to send messages using Flex Events.
In Part 6, I showed nested contexts and object lifecycle methods.

This article builds upon what was covered in the previous examples, so if you haven't seen them, I encourage you to start with at the beginning of this series.  This article has two examples of how to use the Decoupled Bindings feature of Parsley.
 
Decoupled Binding

   Decoupled binding is a Parsley Feature that provides binding in a decoupled way.  It is not exactly like Flex bindings, as you can’t use it in an MXML object declaration, but it does allow you to create bindings between objects on different components.  Essentially, if you update one, the other one is immediately updated in a decoupled way.  That means that the binding is identified by the object type.

   Truth be told, it acts more like a regular injected object than regular bindings.  So what is the difference between “Decoupled Binding” and regular injection?  Well there are a few.  First “Decoupled Binding” does not require that the “shared” object be manage by the framework, which means it takes less resources.  Second, “Decoupled Binding” objects can be added to the context at any time and not limited to be added at context creation time.  Now I won’t go into all the details regarding “Decoupled Binding” since there is a whole section on the docs (http://www.spicefactory.org/parsley/docs/2.3/manual/) regarding this, and it’s pretty detailed.  You can go straight to section 5 here (http://www.spicefactory.org/parsley/docs/2.3/manual/bindings.php#intro) .

   One useful application of decouple bindings is to publish a current selected object to be used in a master/detail scenario.

Ok, so how do they work?

Well, you have three basic tags.  [Publish], [PublishSubscribe] and [Subscribe].
The [Publish] tag is to be used when you only have ONE publisher.  Only one component is going to update the value, all others are going to be subscribers (readers).  This is basically one way binding.
The [Subscribe] tag is for readers of the value.  They want to be updated when the Publishers updates the value, similar to read only.  You can have multiple subscribers to any publisher.
The [PublishSuscribe] tag allows you to have multiple publishers, and that means that a publisher can also be updated by some other publisher.  They are basically both, a publisher and a subscriber.  You can’t combine a [Publish] with a [PublishSubscribe] on the same type object.  If you plan to have more than one publisher on the same type, use [PublishSubscribe] on all of them.

You essentially place the [Publish] tag infront of any variable declaration that you wish to be a publisher.  Something like:

[Publish][Bindable]
public var myBroadcastingVar:SharedValueObjectClass;

When used in Flex, [Publish] and [PublishSubscribe] must also use the [Bindable] tag.

Subscribers work similarly:

[Subscribe]
public var myBroadcastedVar:SharedValueObjectClass;

Subscribers are not required to be tagged with [Bindable].

One of the great things about Decoupled Binding in Parsley is that it also can be set to use a local scope context or global (default), somewhat like messaging as explained in the previous example.  There is one difference though.  In messaging, the scope is decided only by the message handler.  With decoupled bindings the scoped is selected by the publisher and the subscriber.  You can read more about it in the docs.  You would use something like:

In the Publisher :
[Publish(scope="window")][Bindable]
public var selectedContact:Contact;

And in the subscriber:
[Subscribe(scope="window")]
public var selectedContact:Contact;


You can ask the framework to manage the published object; by default it is not managed.  To have the framework manage the object for you, you would use [Publish(managed="true")].  You can read more about this in the docs.

In this case I’m going to do two examples for the price of one.  The fist example used One Publisher, and the second example uses two publishers.

Decoupled Binding example with one Publisher

Here is the working example with view source enabled.



Here is this structure of the project.
This project is fairly simple. It has two view components called PublishView and SubscribeView.  There is also a DecoupledVO class which is the object that is going to be published and subscribed. 
Let's look at the code.  First the Value Object that will be published.

Here is DecoupledVO.as:

package VO
{
    /***************************************************************
     * This is a simple class that will hold a String that will be
     * shared among different views.  The reason to encapsulate the
     * string into a VO is that it makes it possible for Parsley to
     * identify the object by type.  You can also use Ids.  Refer
     * to Parsley docs. 
     * http://www.spicefactory.org/parsley/docs/2.3/manual/bindings.php#intro
     * 
     * For more Parsley examples visit:  artinflex.blogspot.com
     * */ 
    
    public class DecoupledVO
    {
        [Bindable]
        public var sharedString:String;
    }
}

Nothing special here.  A very simple class with a bindable string property.  This is the object that will be Published.  Why not publish just the string? Well, then you would only be able to publish one string, or have to use id's to identify each individual string.  Parsley knows how to match Publishers and Subscribers through the data type.

Ok, let's look at the publisher.

Here is PublishView.mxml:

<?xml version="1.0" encoding="utf-8"?>
<!--  This view will be set to do a decoupled binding and it will Publish the value from 
  a textInput to be able to be read by other components 
  For more examples visit:  artinflex.blogspot.com
-->
 <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="210" height="60" borderStyle="solid" cornerRadius="3" paddingLeft="5" xmlns:parsley="http://www.spicefactory.org/parsley">
    <mx:Label  text="Publish" fontWeight="bold"/>
    <mx:TextInput width="200" id="publishingTextInput" />    
    <!--In Flex 3, for binding to be on output, we must specify it with the binding tag-->
    <mx:Binding source="publishingTextInput.text" destination="decoupledVO.sharedString" />
    
    <!--  Configure is how you tell Parsley that you want this view to become 
    part of the Context and participate in all of Parsley’s features.
    For the Publish / PublishSubscribe / Subscribe tags to be seen by Parsley
    this view must be managed. -->    
    <parsley:Configure />
    
    <mx:Script>
        <![CDATA[
            import VO.DecoupledVO;

            /*********************************************
             *     The object that will be published should have its own type to be
             *     identifiable by Parsley without ambiguity.  Alternatively you 
             *  can use IDs.  On the publishing side, Publish objects MUST also
             *  be tagged with Bindable in Flex apps.
             */ 
             [Publish]
            [Bindable]
            public var decoupledVO:DecoupledVO = new DecoupledVO();
            
        ]]>
    </mx:Script>
    
</mx:VBox>

   This component has a TextInput that is bound to the shared string of our object that we are going to publish.  Note that you must instantiate the object that will be published, most likely with new,  you control the creation, and destruction of the object.  If you wanted to have the framework manage the object you would use [Publish(managed="true")].  Note that having the framework manage the object doesn't relieve you from assigning an instance yourself.  With decoupled bindings the framework will not create the instance for you.  The advantage of having the framework manage the object for you is that the object will be able to participate in other Parsley features, such as injection and messaging.

Ok, now let's look at the subscriber.

Here is SuscribeView.mxml:

<?xml version="1.0" encoding="utf-8"?>
<!--  This view will be set to do a decoupled binding and it will Subscribe the value
  that it receives from other components and set it to a textInput.  Note that it is
  really decoupled, as it doesn't have any reference to the publishing object/view.
  For more examples visit:  artinflex.blogspot.com
-->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="210" height="60" borderStyle="solid" cornerRadius="3" paddingLeft="5" xmlns:parsley="http://www.spicefactory.org/parsley">
    <mx:Label  text="Subscribe" fontWeight="bold"/>
    <mx:TextInput width="200" id="subscribeTextInput" text="{decoupledVO.sharedString}" />
    
    <!--  Configure is how you tell Parsley that you want this view to become 
    part of the Context and participate in all of Parsley’s features.
    For the Publish / PublishSubscribe / Subscribe tags to be seen by Parsley
    this view must be managed. -->    
    <parsley:Configure />
    
    <mx:Script>
        <![CDATA[
            import VO.DecoupledVO;

            /*********************************************
             *     The object that will be subscribed should have its own
             *  type to beidentifiable by Parsley without ambiguity.
             *  Alternatively you can use IDs.  Bindable is not required
             *  on the Subscribe, but since I bound it to the TextInput
             *  I must include Bindable.
             */ 
             [Subscribe]
             [Bindable]
            public var decoupledVO:DecoupledVO;
            
        ]]>
    </mx:Script>
    
</mx:VBox>

   SubcribeView has a TextInput bound to the same property as PublishView.  One thing that is important is that you should not assign an instance to the var that is tagged as the subscriber, as the publisher will pass the reference to it from its own var.  But your code MUST be aware that the subscribed var can have the value of null.  There is no guarantee that the value of that var (in this case decoupledVO) will not be null for some period of time.

The main file just has both views.

Here is ParsleyDecoupledBindingsExample1.mxml:

<?xml version="1.0" encoding="utf-8"?>

<!--
This example demonstrates Parsley's Decoupled Bindings.  
For more examples visit:  http://artinflex.blogspot.com
-->

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
    xmlns:parsley="http://www.spicefactory.org/parsley" 
    xmlns:views="views.*"
    height="144" width="230">
<!--    
    ContextBuilder is how you tell parsley to manage objects that are not Views. 
    In this case I'm instructing Parsley to create a context.  No config file was defined
    because we are not asking Parsley to manage any particular object.  We just need to
    create at least one context.
-->
    <parsley:ContextBuilder />
    <mx:VBox x="10" y="10" height="100%">
        <views:PublishView>
        </views:PublishView>
        <views:SuscribeView>
        </views:SuscribeView>
    </mx:VBox>
    
</mx:Application>


Now let's look at the example with two publishers.

Decoupled Binding example with two Publishers

   The previous example assumes that you only have one potential publisher, and remember that when you use [Publish] you can only have one publisher per datatype within the same scope.

  So what happens if you wish to have two publishers?  Well you use [PublishSubscribe] and in fact your publisher is also a subscriber.

Let's look at the example running (view source is enabled).



Here is the structure of the project:
   This example has three views. One that acts as a Publish only, one that is a Publisher and Subscriber, and a Subscriber only. The keyword here is "acts", since it does use PublishSubscribe, but through my own code it behaves as it was only a Publisher.  Other than that it is basically the same as the above example.
   Let's look a the code. I won't include the code to the DecoupledVO.as as it identical to the example above.

   So what does the PublishView.msml look like?

<?xml version="1.0" encoding="utf-8"?>
<!--  This view will be set to do a decoupled binding and it will Publish the value from 
  a textInput to be able to be read by other components. 
  For more examples visit:  artinflex.blogspot.com
-->
 <mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="210" height="60" borderStyle="solid" cornerRadius="3" paddingLeft="5" xmlns:parsley="http://www.spicefactory.org/parsley">
    <mx:Label  text="Publish" fontWeight="bold"/>
    <mx:TextInput width="200" id="publishingTextInput" />    
    <!--In Flex 3, for binding to be on output, we must specify it with the binding tag-->
    <mx:Binding source="publishingTextInput.text" destination="decoupledVO.sharedString" />
    
    <!--  Configure is how you tell Parsley that you want this view to become 
    part of the Context and participate in all of Parsley’s features.
    For the Publish / PublishSubscribe / Subscribe tags to be seen by Parsley
    this view must be managed. -->    
    <parsley:Configure />
    
    <mx:Script>
        <![CDATA[
            import VO.DecoupledVO;

            /*********************************************
             *     The object that will be published should have its own type to be
             *     identifiable by Parsley without ambiguity.  Alternatively you 
             *  can use IDs.  On the publishing side, Publish objects MUST also
             *  be tagged with Bindable in Flex apps.
             *  In this case, since I wish to have multiple publishers of the same
             *  object type, I can't use Publish.  Only ONE object can be set to
             *  Publish.  Therefore I must use PublishSubscribe.  I limit it to
             *  Publishing only through the binding of the TextInput being one way.
             */ 
             [PublishSubscribe]
            [Bindable]
            public var decoupledVO:DecoupledVO = new DecoupledVO();            
        ]]>
    </mx:Script>    
</mx:VBox>

   Well, not much changed from the example above that had only one publisher.  The only difference (besides the comments) is the [PublishSubscribe] tag that replaced the [Publish] tag.  When you run the example you will notice that the TextInput doesn't get updated in the PublishView.  Technically speaking, when the other PublishSubscribeView updates the DecoupledVO, the local decoupledVO object in this view, does get updated, but the TextInput doesn't, simply because I set the binding from the TextInput to the decoupledVO as a one way road, simple trick (take a look at the <Binding> statement.

  SubscribeView is identical to the previous example, nothing changed there.

  Ok, so now let's look at the PublishSubscribeView.mxml:

<?xml version="1.0" encoding="utf-8"?>
<!--  This view will be set to do a decoupled binding and it will Publish and
  subscribe the value from a textInput to be able to be read by other components
  and receive its value from another component. 
  For more examples visit:  artinflex.blogspot.com
-->
<mx:VBox xmlns:mx="http://www.adobe.com/2006/mxml" width="210" height="60" borderStyle="solid" cornerRadius="3" paddingLeft="5" xmlns:parsley="http://www.spicefactory.org/parsley">
    <mx:Label  text="Publish and Subscribe" fontWeight="bold"/>
    <mx:TextInput width="200" id="publishingSubscribeTextInput" />    
    <!--In Flex 3, for binding to be on output, we must specify it with the binding tag-->
    <mx:Binding source="publishingSubscribeTextInput.text" destination="decoupledVO.sharedString" />
    <mx:Binding destination="publishingSubscribeTextInput.text" source="decoupledVO.sharedString" />
    
    <!--  Configure is how you tell Parsley that you want this view to become 
    part of the Context and participate in all of Parsley’s features.
    For the Publish / PublishSubscribe / Subscribe tags to be seen by Parsley
    this view must be managed. -->    
    <parsley:Configure />
    
    <mx:Script>
        <![CDATA[
            import VO.DecoupledVO;

            /*********************************************
             *     The object that will be published and subscribed should have
             *  its own type to be    identifiable by Parsley without ambiguity.
             *  Alternatively you can use IDs.  On the publishing side,
             *  Publishing objects MUST also be tagged with Bindable in Flex apps.
             */ 
             [PublishSubscribe]
             [Bindable]
            public var decoupledVO:DecoupledVO = new DecoupledVO();
            
        ]]>
    </mx:Script>    
</mx:VBox>

   The PublishSubscribe view is nearly identical to the PublishView, besides the properties being renamed, the main difference is that binding is set to be bi-directional.  This makes the TextInput get updated when the decoupledVO get's updated.

  A very important note:  When you have have one publisher it is pretty obvious which view must instantiate the original object that gets passed by reference to all the subscribers.  When you have multiple PublishSubscribe elements on different views, it is not so obvious.  Technically speaking only one needs to create the instance and all others will receive a reference to that instance, but it is not always obvious which one should be the one with that responsibility, as this example demonstrates.  You can technically figure it out, it should be the last one that joins in, as it will publish it's own instance last and hence it will pass it's reference to all others, and replacing what ever they had.  If you want to be on the safe side you can just assign some instance to all the PublisherSubscribe elements as I did in this example.  Eventually the instances not used will get garbage collected anyways, as there will no longer be a reference to them.

  This is a drawback of using decoupled bindings in comparison with regular Parsley managed objects.  Decoupled bindings does not go through the full sanity checks that regular context created objects do.  If you have a view with a PublishSubscribe tag that joins in at a latter time, it will replace whatever value was already being shared.  I have created an example that shows this behavior.  I have source enabled, but I won't go into the details of the example, it's just so you can play with it.

Here is that example with view source enabled:



Well I certainly hope that these examples were useful, more to come soon.

Next in the series is: Parsley's Dynamic Command and Dynamic Objects.