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

47 Responses to Building a Flex Application with the Parsley Framework

  1. sitron July 17, 2009 at 4:17 am #

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

  2. evden eve July 18, 2009 at 10:25 am #

    supper flex examples mysql db

  3. Favor Biz July 19, 2009 at 9:11 pm #

    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. PaSCuaLiN July 21, 2009 at 4:04 am #

    Very easy to learn with your example!

    Thanks a lot :)

  5. bedava film izle July 28, 2009 at 4:02 am #

    thanx very much

  6. Jeffrey Mason August 2, 2009 at 12:28 pm #

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

    Any suggestions, please.

  7. Hunter September 3, 2009 at 2:24 am #

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

  8. PC игры September 16, 2009 at 10:31 am #

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

  9. Lee September 22, 2009 at 6:51 pm #

    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 September 22, 2009 at 8:00 pm #

    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. Matthew Wallace October 8, 2009 at 6:25 am #

    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. Kaenna October 10, 2009 at 8:56 pm #

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

  13. Scot October 14, 2009 at 9:01 pm #

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

  14. Program Yükle November 10, 2009 at 10:23 am #

    Thank you admin goood

  15. порно сын November 26, 2009 at 8:48 am #

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

  16. Priyank Namdeo April 18, 2010 at 6:36 am #

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

  17. Agish August 16, 2010 at 10:24 am #

    Thanks ..

  18. Vardan September 24, 2010 at 9:13 am #

    Hi Christophe,

    Great tutorial.
    A question.
    What is the url/context to run it from the browser if I use ?

    Thanks again for your fantastic tutorial.

  19. Rakesh Sivan October 5, 2010 at 10:51 pm #

    Thanks for sharing your knowledge in Parsley framework and also the demo application. Its a pleasure to watch your lectures in Adobe Developer Connection, since there will be something quite innovative, kind of out-of-box-thinking stuff in your videos.. Keep up the good work.

  20. Jeremy Flowers October 6, 2010 at 3:38 pm #

    Why didn’t you go the whole hog and integrate Pimento with Parsley? If you haven’t done that yet, I may have a go at adapting this example to use that rather than a straight JDBC style server-side.

  21. Rinos October 12, 2010 at 12:41 am #

    Hi,

    I have configured and installed as instruct above but the application is running but when i register a new user it says sending failed msg and not saving data in to db. and i cant get any data to datgrid from database. can any body help me to get data from database. i am new to this environment.

  22. Jason Phimosis October 26, 2010 at 5:53 pm #

    Can these flex applications maybe work with wordpress? just a thought…

  23. Wyne November 4, 2010 at 4:23 am #

    http://automobileinsurancetexas.net/

    The Savings You Want. Save with our competitive rates and extensive discount options. Compare multiple quotes from independent agents who represent many companies – not just one.

  24. Roger November 11, 2010 at 8:49 pm #

    Thanks, I’ve been looking for something like this.
    Maybe it will help as a natural remedies for hemroids.

  25. Calavero November 21, 2010 at 3:09 pm #

    Hi,

    I get the .zip and import it in flex this work correctly.

    When I run this with an ANT task, this build successfully but when I run the Application throught firefox I get two errors:

    1)
    ReferenceError: Error #1065: La variable org.spicefactory.parsley.flex::FlexContextBuilder n’est pas définie.
    at main/preinitHandler()[C:\env\myworkspace\glm-flex\src\main.mxml:22]
    at main/___main_Application1_preinitialize()[C:\env\myworkspace\glm-flex\src\main.mxml:4]
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at mx.core::UIComponent/dispatchEvent()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:9298]
    at mx.core::UIComponent/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5367]
    at mx.core::Container/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2526]
    at mx.core::Application/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Application.as:846]
    at main/initialize()[C:\env\myworkspace\glm-flex\src\main.mxml:0]
    at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:2009]
    at mx.managers::SystemManager/initializeTopLevelWindow()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:3234]
    at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::docFrameHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:3064]
    at mx.managers::SystemManager/docFrameListener()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:2916]

    2)

    VerifyError: Error #1014: La classe flexlib.containers::SuperTabNavigator est introuvable.

    at global$init()
    at ()[C:\env\myworkspace\glm-flex\src\main.mxml:0]
    at Function/http://adobe.com/AS3/2006/builtin::call()
    at mx.core::ComponentDescriptor/get properties()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\ComponentDescriptor.as:241]
    at mx.core::Container/createComponentFromDescriptor()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:3557]
    at mx.core::Container/createComponentsFromDescriptors()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:3493]
    at mx.core::Container/createChildren()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2589]
    at mx.core::UIComponent/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5370]
    at mx.core::Container/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2526]
    at mx.core::UIComponent/http://www.adobe.com/2006/flex/mx/internal::childAdded()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5267]
    at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::childAdded()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:3305]
    at mx.core::Container/addChildAt()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2217]
    at mx.core::Container/addChild()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2140]
    at mx.core::Container/createComponentFromDescriptor()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:3681]
    at mx.core::Container/createComponentsFromDescriptors()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:3493]
    at mx.core::Container/createChildren()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2589]
    at mx.core::UIComponent/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\UIComponent.as:5370]
    at mx.core::Container/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:2526]
    at mx.core::Application/initialize()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Application.as:846]
    at main/initialize()[C:\env\myworkspace\glm-flex\src\main.mxml:0]
    at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::childAdded()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:2009]
    at mx.managers::SystemManager/initializeTopLevelWindow()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:3234]
    at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::docFrameHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:3064]
    at mx.managers::SystemManager/docFrameListener()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:2916]

    Here is my build.xml:

    Deleting some flex’s files from flex project

    Deleting some flex’s files from ${glm-deploy.home}

    <!–
    en_US
    locale/{locale}
    mainBundle
    anotherBundle
    bin-debug/Resources_en_US.swf
    –>

    Compiling the Flex code

    Creating the HTML template

    Thanks in advance for your help.

    Calavero

  26. sai December 7, 2010 at 8:10 pm #

    Helped!!

  27. subba December 9, 2010 at 2:13 am #

    Thanks, for great example

  28. Scott Schafer January 15, 2011 at 3:19 pm #

    Thanks for this tutorial.

    It all looks good, except that this line bugs me: [ManagedEvents("addContact,search")]

    It seems wrong to me to define the event names as a constant and then hard code them in this file. I’d like to do something like the following instead, but I can’t seem to get it to work.

    Any ideas?

  29. Manasa February 4, 2011 at 1:42 am #

    Nice Tutorial. Goes really well with the manual in Parsley’s documentation.

    I just started learning Parsley. Im having difficult getting Message Handlers. So in the given Contact Management application, ToolBar view dispatches the event “search” and ContactList view has a message handler for it. This part is clear.

    I defines a message handler for the same “Search” event in main.mxml. But this method did not get invoked :(
    are there any restrictions on which objects can have message handlers for events?

    thanks in advance ..

  30. Ashish April 19, 2011 at 4:50 am #

    Thanks for such a nice example.
    But “Managed event” part of it kinda looks little vulnerable, especially when multiple objects of a class containing resultHandler are active in the same scope… In that case every object will respond to the event for which the handler is written and unnecessary updates will be made to the unintended object…. I hope I am making sense here…

  31. a April 29, 2011 at 6:08 am #

    cxcsf

  32. vikash agarwal September 23, 2011 at 7:33 am #

    Hi,
    Thanks for the example. I have a small doubt.
    In the example, config.mxml you have added ContactServiceMock and in views you have
    [Inject]
    [Bindable]
    public var service:IContactService

    I guess it means service in views will be intialized to ContactServiceMock Object.

    In case I want to intialize service object with ContactServiceRemote, then i replace ContactServiceMock with ContactServiceRemote in Config.mxml.

    Now, If I have two different views where one needs ContactServiceRemote and one needs ContactServiceMock then how can we add both services in Config.mxml.

    Thanks a ton in advance for the reply.

  33. vikash agarwal September 26, 2011 at 2:34 am #

    Hi,

    I got the answer for my previous question. Looked into Parsley Docs.

    Thanks

  34. eq October 29, 2011 at 2:04 pm #

    How to load data on application startup, let say in your example above when the application starts/display, i want to display list of contacts without typing in anything in search field.

    I tried few things but no success yet.
    I tried putting code in creationComplete=”search(….
    but i noticed that the service is null.

    When i type % in search field it DOES display contacts, which means that during preinitialize, service was not initialized, right? or am i missing something

    A good coded example would be very helpfull or is this even possible with parsley?

    thanks

  35. eq November 1, 2011 at 10:04 pm #

    Never mind, i figured it out,
    1) dispatched an event in application complete
    2) added event listener in the constructor
    3) handle that event in the controller
    4) executeservicecall to call the server

  36. Action November 17, 2011 at 6:58 pm #

    Great Article, Christopher. I have also found this very interesting article about Silent errors in Parsley http://stageaction.wordpress.com/2011/11/17/flex-parsley-silent-failure/

  37. Marksion October 14, 2012 at 12:18 pm #

    Just start up learning Parsley, seems to be a good fw!

  38. Kurt April 19, 2014 at 3:36 am #

    Wow that was strange. I just wrote an incredibly long comment
    but after I clicked submit my comment didn’t show
    up. Grrrr… well I’m not writing all that over again. Anyways,
    just wanted to say fantastic blog!

  39. Serena April 20, 2014 at 7:47 am #

    Wow, this paragraph is nice, my sister is analyzing such things, thus I am going to let know her.

  40. 27 April 20, 2014 at 7:53 am #

    Wow, amazing blog layout! How long have you been blogging
    for? you make blogging look easy.The overall look of your web site is excellent,
    let alone the content!

Trackbacks/Pingbacks

  1. 20/07/2009 « Robertopriz’s Weblog - July 20, 2009

    [...] 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. jexchen » Blog Archive » Flash、Flex资源收集之十全大补 - September 28, 2009

    [...] http://coenraets.org/blog/2009/07/building-a-flex-application-with-the-parsley-framework/ [...]

  3. Borre Wessel – Flex in the enterprise » Presenting at the Adobe RIA user group London - October 27, 2009

    [...] 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 [...]

  4. AS3常用类库 | RIA飞鹰工作室 - December 27, 2009

    [...] http://coenraets.org/blog/2009/07/building-a-flex-application-with-the-parsley-framework/ [...]

  5. Parsley Framework good examples | RIA Developer - September 25, 2010

    [...] http://coenraets.org/blog/2009/07/building-a-flex-application-with-the-parsley-framework/(Adobe Evangelist Christophe Coenraets) [...]

  6. A first take on Flex SpiceFactory projects Pimento and Parsley « All things Grails and RIA - October 7, 2010

    [...] you want to see a sample project, Christophe Coenraet has a handy blog post here. Unfortunately, he didn’t go the extra mile and demonstrate integration with Pimento too. [...]

  7. Flash、Flex资源收集之十全大补 | Wang Jun's Blog - November 14, 2010

    [...] http://coenraets.org/blog/2009/07/building-a-flex-application-with-the-parsley-framework/ [...]

Leave a Reply