Building a Flex Application with the Parsley Framework

Building a Flex Application with the Parsley Framework

After my recent explorations of “Swiz”, and “Spring ActionScript” (1,2,3), I decided to take the new version of the Parsley framework for a test drive, and build the Parsley version of inSync: the simple Contact Management application I often use to try out and demonstrate different features and techniques in Flex and Adobe AIR.

Parsley is primarily a Dependency Injection framework. It also offers a very interesting messaging infrastructure. I won’t get into the details of dependency injection here: My previous Swiz and Spring ActionScript articles provide some background information, and there are also plenty of detailed resources out there.

If you just want to run the application and dive into the code, here are the links:

  • Click here to run the application.
  • Click here to view the source code.

Object Configuration

Parsley allows you to configure the core objects of your application (the objects other components depend on) in MXML (like Swiz), in XML (like Spring ActionScript), in ActionScript, or using any combination of these approaches. You can also extend the framework and create your own configuration mechanism.

For the inSync application, I used a simple MXML configuration (Config.mxml) defined as follows:

<?xml version="1.0" encoding="utf-8"?>
<Object xmlns="*" xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:services="insync.parsley.services.*">

    <mx:RemoteObject
            id="contactRO"
            destination="contacts"
            endpoint="http://localhost:8400/samples/messagebroker/amf"
            showBusyCursor="true" />

    <services:ContactService />

</Object>

Note: In a real life application, you would not want to hardcode the endpoints of your services in your source code. You could use the XML configuration option to configure your endpoints in a more “externalized” fashion. More on this topic here.

Framework Initialization

You initialize the Parsley framework using the ContextBuilder class corresponding to the configuration approach you chose. Here is the main application file for the inSync application. Parsley is initialized in the preinitialize event of the application.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:views="insync.parsley.views.*"
	paddingTop="0" paddingLeft="0" paddingRight="0" paddingBottom="0"
	preinitialize="FlexContextBuilder.build(Config)">

	<mx:Script>
		<![CDATA[
			import org.spicefactory.parsley.flex.FlexContextBuilder;
		]]>
	</mx:Script>

	<mx:Style source="styles.css" />

	<views:MainView />

</mx:Application>

Dependency Injection

Parsley supports constructor injection, method injection, and property injection (by type or by id).

In the following example (ContactForm.mxml), the framework will inject a specific implementation of the IContactService interface. In this case, the ContactService instance created in Config.mxml will be injected. This is an example of injection by type. Coding to the interface allows us to keep the view decoupled from a specific implementation of IContactService.

Note: Parsley doesn’t force you to use any specific design pattern. For simplicity in this sample application, I inject a service directly into the view. The use of an interface provides some level of decoupling, but you can of course use other patterns (like the Presentation Model) to achieve a greater level of abstraction. The Dependency Injection and Messaging infrastructure of Parsley will make the implementation of these patterns easier.

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml"
	addedToStage="dispatchEvent(new Event('configureIOC', true))">

	<mx:Script>
		<![CDATA[

		import insync.parsley.model.Contact;
		import insync.parsley.services.IContactService;

		[Inject]
		public var service:IContactService;

		[Bindable]
		public var contact:Contact;

		private function save():void
		{
			contact.firstName = firstName.text;
			contact.lastName = lastName.text;
			contact.email = email.text;
			service.save(contact);
		}

		private function remove():void
		{
			service.remove(contact);
		}

		]]>
	</mx:Script>

	<mx:Form>
		<mx:FormItem label="Id">
			<mx:TextInput text="{contact.id}" enabled="false"/>
		</mx:FormItem>
		<mx:FormItem label="First Name">
			<mx:TextInput id="firstName" text="{contact.firstName}"/>
		</mx:FormItem>
		<mx:FormItem label="Last Name">
			<mx:TextInput id="lastName" text="{contact.lastName}"/>
		</mx:FormItem>
		<mx:FormItem label="Email">
			<mx:TextInput id="email" text="{contact.email}"/>
		</mx:FormItem>
	</mx:Form>

	<mx:HBox left="12" bottom="12">
		<mx:Button label="Save" click="save()"/>
		<mx:Button label="Delete" click="remove()"/>
	</mx:HBox>

</mx:Canvas>

Note that in order to get its dependencies injected when it’s added to the stage, a view has to dispatch the “configureIOC” event.

Messaging

Parsley provides a generic Messaging infrastructure that allows you to exchange messages between objects in a decoupled, flexible, and easy-to-use manner:

  • The event dispatcher and the event handler don’t know about each other.
  • The event dispatcher and the event handler are decoupled from the framework: You dispatch events the Flex way.

Let’s look at the Search feature inSync as an example:

  • The Toolbar class includes a simple TextInput that allows the user to specify a search criterion.
  • The ContactList class displays the Search Results in a DataGrid.

The Toolbar class is defined as follows (non essential code removed for clarity):

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%"
	addedToStage="dispatchEvent(new Event('configureIOC', true))">

	<mx:Metadata>
		[ManagedEvents("search")]
	</mx:Metadata>

	<mx:Script>
		<![CDATA[
			import insync.parsley.events.SearchEvent;
		]]>
	</mx:Script>

	<mx:Label text="Search:" top="18" right="164"/>

	<mx:TextInput id="searchBox" right="0" top="16"
		change="dispatchEvent(new SearchEvent(SearchEvent.SEARCH, searchBox.text))"/>

</mx:Canvas>

Note that it dispatches a SearchEvent when the content of the search input field changes.

That event is defined as a managed event (using the ManagedEvents annotation), meaning that the framework will make sure that all the parties interested in that event will receive it.

How do you register as a listener for a managed event? You simply annotate a function with [MessageHandler], and it automatically becomes an event handler for that event, regardless of the display object hierarchy or whether the event bubbles or not.

Here is how it’s done in ContactList (non essential code removed for clarity):

<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="100%" height="100%"
	addedToStage="dispatchEvent(new Event('configureIOC', true))">

	<mx:Script>
		<![CDATA[

			import mx.controls.Alert;
			import mx.collections.ArrayCollection;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.AsyncToken;
			import mx.rpc.AsyncResponder;
			import mx.rpc.events.ResultEvent;

			import insync.parsley.events.SearchEvent;
			import insync.parsley.services.IContactService;			

			[Inject]
			[Bindable]
			public var service:IContactService;

			[Bindable]
			public var contacts:ArrayCollection;

			[MessageHandler]
			public function searchHanlder(event:SearchEvent):void
			{
				service.getContactsByName(searchStr).addResponder(new AsyncResponder(getContacts_result, faultHandler));
			}

			private function getContacts_result(event:ResultEvent, token:AsyncToken):void
			{
				contacts = event.result as ArrayCollection;
			}	

			private function faultHandler(event:FaultEvent):void
			{
				Alert.show(event.fault.faultString);
			}		

		]]>
	</mx:Script>

	<mx:DataGrid id="dg" dataProvider="{contacts}" width="100%" top="0" left="0" right="0" bottom="0"/>

</mx:Canvas>

With the simple [MessageHandler] annotation, the handler will be invoked every time an event of the function argument’s data type is dispatched in the application. If you need finer control, you can use the selector notation to specify the event type. For example in MainView.mxml, we register the contactDeleted function as a handler for the ContactEvent.DELETED event as follows.

[MessageHandler(selector="contactDeleted")]
public function contactDeletedHandler(event:ContactEvent):void
{
}

There is more to the Messaging capabilities of the Parsley framework. For example, you can use [MessageBinding] to bind a property of an object to the property of an event.

[MessageBinding(messageProperty="result",type=" mx.rpc.events.ResultEvent")]
public var contacts:ArrayCollection;

Installation Instructions

  1. Download the project here
  2. Import it in Flex Builder
  3. Run the application. The application is configured to use the MockService (ContactServiceMock) by default, so it will run without any back-end.

If you want to use the Remoting service instead of the MockService:

  1. Replace <services:ContactServiceMock/> with <services:ContactServiceRemote/> in Config.mxml
  2. Install the BlazeDS turnkey server.
  3. Download insync-parsley-java.zip, and unzip it on your local file system.
  4. Copy classes/insync to blazeds/tomcat/webapps/samples/WEB-INF/classes/insync.
  5. Add the following destination to blazeds/tomcat/webapps/samples/WEB-INF/flex/remoting-config.xml:
  6. <destination id="contacts">
            <properties>
                <source>insync.dao.ContactDAO</source>
                <scope>application</scope>
            </properties>
    </destination>
    

  7. Copy insync/sampledb/insync to blazeds/sampledb/insync
  8. Edit server.properties in blazeds/sampledb, and modify the file as follows to add the insync database to the startup procedure.

    server.database.0=file:flexdemodb/flexdemodb
    server.dbname.0=flexdemodb
    server.database.1=file:insync/insync
    server.dbname.1=insync
    server.port=9002
    server.silent=true
    server.trace=false
    

  9. Start the database (startdb.bat or startdb.sh)
  10. Start BlazeDS
  11. Run the application
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • LinkedIn
  • StumbleUpon
  • Twitter
This entry was posted in Flex, Frameworks, Parsley. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

16 Comments

  1. sitron
    Posted July 17, 2009 at 4:17 am | Permalink

    nice!
    any reason it doesn’t include a “summary” section?
    i got used to this little piece of subjective appreciation :)

  2. Posted July 18, 2009 at 10:25 am | Permalink

    supper flex examples mysql db

  3. Posted July 19, 2009 at 9:11 pm | Permalink

    I like this function ver much

    “Parsley provides a generic Messaging infrastructure that allows you to exchange messages between objects in a decoupled, flexible, and easy-to-use manner”

  4. Posted July 21, 2009 at 4:04 am | Permalink

    Very easy to learn with your example!

    Thanks a lot :)

  5. Posted July 28, 2009 at 4:02 am | Permalink

    thanx very much

  6. Jeffrey Mason
    Posted August 2, 2009 at 12:28 pm | Permalink

    Having a bit of trouble importing to Flash Builder 4. I’ve tried several import methods to no avail.

    Any suggestions, please.

  7. Posted September 3, 2009 at 2:24 am | Permalink

    I cant understand Parsley much, when will you use [inject],messageHandler and manageevents? im so confused..

  8. Posted September 16, 2009 at 10:31 am | Permalink

    Спасибо. было очень интересно.

  9. Lee
    Posted September 22, 2009 at 6:51 pm | Permalink

    Nice icons in the app. Would you mind if I ask where you got the icons? I guess I already asked.

    I need a few good sources for free icons, as my design skills are not up to par.

    Thanks,

    Lee

  10. Lee
    Posted September 22, 2009 at 8:00 pm | Permalink

    Sorry for the last message. Let me answer my own question:
    Those nice icons are available from:
    http://www.famfamfam.com/

    I realize now why the icons looked so familiar.

    Lee

  11. Posted October 8, 2009 at 6:25 am | Permalink

    awesome example. really glad to finally read through it. Now I am looking forward to giving the framework a try. I really like the ManagedEvents and MangeHandler. This model is really close to a setup that I have used for a while on my own. I like the fact that it removes the need to write the addEventListener stuff in the class that needs to handle the event. Nice!

    Hope you plan on more examples in the near term.

    Rock On!
    -Matthew

  12. Posted October 10, 2009 at 8:56 pm | Permalink

    Very interesting site. Hope it will always be alive!,

  13. Posted October 14, 2009 at 9:01 pm | Permalink

    Very nice example – just one suggestion to bring it up to date: Pam Beesly is now Pam Halpert :)

  14. Posted November 10, 2009 at 10:23 am | Permalink

    Thank you admin goood

  15. Posted November 26, 2009 at 8:48 am | Permalink

    [url=http://fyfk.ru/]анальное порно[/url]

  16. Priyank Namdeo
    Posted April 18, 2010 at 6:36 am | Permalink

    This is excellent example to learn Parsley in seconds. Well done! Keep posting new (simple) threads!

4 Trackbacks

  1. By 20/07/2009 « Robertopriz’s Weblog on July 20, 2009 at 4:34 am

    [...] 20/07/2009 Posted in 5584 by robertopriz on July 20, 2009 framwork  http://coenraets.org/blog/2009/07/building-a-flex-application-with-the-parsley-framework/ [...]

  2. [...] for an example of building a Parsley based Flex application, have a look at this blog post by Christophe Coenraets alternatively have a look the documentation, Parsley is comprehensively documented: Parsley [...]

  3. By AS3常用类库 | RIA飞鹰工作室 on December 27, 2009 at 9:36 am

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>