1 Overview

Parsley is an Application Framework for Flex and Flash Applications built upon an IOC Container and Messaging Framework that can be used to create highly decoupled architectures. It allows you to configure objects to be managed by the container with Metadata, MXML, XML or ActionScript and is easily extensible.

While many other Application Frameworks for the Flash Platform are either a pure Flex Framework that cannot be used without the Flex SDK or are a classic Flash Framework without any deeper integration with Flex, Parsley is both. The core of the framework (the IOC Container and the Messaging Subsystem) does not depend on the Flex SDK at all, but there are several additional modules that are specifically designed for Flex, providing support for MXML Configuration, View Wiring and Flex Modules.

1.1 Features List

This section gives a quick overview over the available features linking to the other chapters of the manual where appropiate. There is also a 2 Getting Started chapter containing a few sample use cases for the impatient.

IOC Container

Parsley is a classic IOC Container. It provides support for Dependency Injection, Object Lifecycle Management and Messaging. The key differentiator is the scope of the framework: While still being as easy to use as many smaller IOC frameworks for simple applications, it also provides many features which are essential for building large, complex and modular applications and numerous extension points.

Dependency Injection

The core feature of any IOC Container. Now with Parsley 2 dependencies can be conveniently declared using AS3 Metadata Tags ([Inject]) on properties, methods or constructors or alternatively with MXML or XML. See 4 Dependency Injection for details.

Messaging

Parsley contains a Messaging Framework that allows for objects to send and receive messages in a fully decoupled way. You can declare events on sending objects with the [ManagedEvents] tags, so that they will be routed through Parsley to all registered handlers. The receiving objects can declare interest in particular message types with several metadata tags like [MessageHandler]. Message selection happens based on the type (class) of the message and optionally based on additional selectors like event type, instead of being purely String based like regular event handlers. This eases development of large applications where you don't have to care for event type constants being unique for the whole system. Furthermore messaging can happen in different scopes, globally or just in a particular region (like an AIR window for example). See 5 Messaging for details.

Object Lifecycle

6.3 Object Lifecycle Methods: Objects can have methods marked with [Init] (which will be invoked after the object has been instantiated and configured) or [Destroy] which will be invoked when the container gets destroyed.

6.2 Asynchronous Object Initialization: Configuration option for asynchronously initializing objects (e.g. objects that need to load data before they can operate). In this case the container will defer the initialization of other objects until those configured to be asynchronous are ready.

Dynamic View Wiring

This module is particularly useful for Flex and solves the problem that you usually wouldn't want to declare Flex Components in IOC Container configuration files, but instead inside your MXML view hierarchy like always. Parsley 2 now allows to connect these components to the IOC Container on-the-fly when they are added to the stage. Also solves the more complicated issues with wiring components in Flex Popups or Native AIR Windows. See 7 Dynamic View Wiring for details.

Support for Modular Applications

For modular applications it's essential that you can create configuration sub-contexts and dynamically load and undload them as needed. Seamlessly integrates with Flex Modules, but can also be used without. See 8 Building Modular Applications for details.

Localization

Allows to bind properties to resources with the [ResourceBinding] tag. Integrates with the Flex ResourceManager for Flex Applications and contains its own Localization Module for Flash Applications. See 10 Localization for details.

Extensibility

Parsley can serve as the base for building higher-level frameworks on top of. Or you may just want to create some additional configuration tags for use cases which are frequent for a particular application. Parsley is easy to extend. A single implementation of an extension interface can be used to create a custom configuration tag that can be used as a Metadata, MXML or XML tag. Furthermore basically all central services of the IOC kernel can be swapped out easily. See 11 Extending the Framework for details.

1.2 What's new in Parsley 2.1

This section just lists the parts of the manual which have been modified or added. It does not list sections which only saw minor modifications.

5 Messaging

6 Object Lifecycle

7 Dynamic View Wiring

8 Building Modular Applications

11 Extending the Framework

14 Configuration Tag Reference

1.3 Migrating from 2.0 to 2.1

This is a list of instructions how you adjust existing applications for the changes that are not backwards-compatible. Even for large and complex applications it should be no big deal. Many sections in this migration guide only affect you when you have built extensions for the framework like custom configuration tags. If you don't have a clue what a particular section is referring to, it is very likely that you can safely ignore it.

Adjust static entry point methods

For all Context instances you want to use view wiring with, you now have to add a second parameter specifying the view root for the Context:

FlexContextBuilder.build(MyConfig, this);

or:

XmlContextBuilder.build("config.xml", this, parentContext);

When building the Context from within a Component you can simply pass this to the builder in most cases.

Switch to addedToStage event for Context creation

The ContextBuilder now looks for parent Context and ApplicationDomain in the view hierarchy if you specify a view root for the builder. To be able to dispatch a bubbling event the specified view root must have been added to the stage:

<mx:Panel
    addedToStage="FlexContextBuilder.build(MyConfig, this)"
    ...
>

CompositeContextBuilder is now an interface

Simply switch from

var builder:CompositeContextBuilder = new CompositeContextBuilder();

to

var viewRoot:DisplayObject = ...;
var builder:CompositeContextBuilder = new DefaultCompositeContextBuilder(viewRoot);

Of course using a view root is optional.

New MXML tag for inline object defintions

Simply switch from

<Object type="{FooClass}">
    <Property name="dependency">
        <Object type="{BarClass}"/>
    </Property>
</Object>

to

<Object type="{FooClass}">
    <Property name="dependency">
        <NestedObject type="{BarClass}"/>
    </Property>
</Object>

The new <NestedObject> tag was necessary since the framework has to distinguish them from root object definitons. The mxmlc compiler adds nested tags which contain bindings as a public property to the class, so the framework could mix them up with root level tags causing additonal unwanted object registrations. This special tag is not required for XML configuration. You can continue to use the simple <object> tag for root and inline definitions.

Remove custom viewTrigger event types

Those are no longer needed and no longer supported (in case you used them at all). Such a custom event type could be specified for the static methods of the FlexContextBuilder and for the Configure tag:

<parsley:Configure triggerEvent="myCustomEventType"/>

Simply remove all references to custom event types.

Attach Flex Popups to the Context they belong to

Flex popups now require an extra step to explicitly attach them to the Context that components in that popup should be wired to:

[Inject]
public var context:Context;

private function showPopup () : void {
    var win:TitleWindow = new TitleWindow();
    // set properties
    context.viewManager.addViewRoot(win);
    PopUpManager.addPopup(win, this);
}

Attach native AIR windows to the Context they belong to

This is basically the same mechanism like how you now have to deal with Flex Popups:

[Inject]
public var context:Context;

private function openWindow () : void {
    var win:Window = new Window();
    // set properties
    context.viewManager.addViewRoot(win);
    win.open();
}

Remove Parsley's ContextModule and ModuleLoader tags

They are no longer needed. Simply replace them with the default mx:Module and mx:ModuleLoader components. There is no longer a need to specify the parent Context for a ModuleLoader, it will be auto-detected in the view hierarchy.

2.0

<parsley:ContextModule
    configClass="{MyModuleConfig}"
    ...
>

2.1

<mx:Module
    addedToStage="FlexContextBuilder.build(MyModuleConfig, this)"
    ...
>

Organize imports for Parsley's internal APIs

If you are talking to the internal API you simply have to organize most imports. There was a huge refactoring and cleaning up for the internal API and several packages and classes have been moved. If your IDE supports a project-wide "Organize imports" that's the fastest way to migrate.

Adjust any custom configuration tags for the Messaging Framework

If you talked to the MessageRouter API directly, in a custom configuration tag or elsewhere in your application code, you have to adjust the code for the new API. In 2.0 a MessageHandler registration looked like this:

context.messageRouter.registerMessageHandler(target, "execute", MyMessage);

In 2.1 there is now a convenient base class that handles a lot of low-level details for you. For example it registers a proxy for non-lazy singletons, so that it does not miss messages even if they are dispatched during Context initialization before the receiver is actually instantiated. Therefor it is recommended to simply overwrite the createReceiver and removeReceiver methods of the AbstractMessageReceiverDecorator base class and not implement the decorate method yourself. You can examine the builtin receiver tag implementations in the package org.spicefactory.parsley.tag.messaging if you want to see how the default messaging tags are implemented. For example the [MessageInterceptor] tag implementation looks like this:

protected override function createReceiver 
        (provider:ObjectProvider, scopeManager:ScopeManager) : MessageReceiver {
    var ic:MessageInterceptor 
            = new DefaultMessageInterceptor(provider, method, type, selector);
    scopeManager.getScope(scope).messageReceivers.addInterceptor(ic);
    return ic;
}
	
protected override function removeReceiver 
        (receiver:MessageReceiver, scopeManager:ScopeManager) : void {
    var ic:MessageInterceptor = MessageInterceptor(receiver);
    scopeManager.getScope(scope).messageReceivers.removeInterceptor(ic);
}

In the createReceiver method you can see that the framework passes a prebuilt ObjectProvider instance to the method. This may either be a wrapper for an existing instance or a proxy where the instance is fetched from the Context in case a matching message is heard.

Change code that programmatically dispatches messages

This change is straightforward. Version 2.1 introduces scopes. Therefor the messageRouter property has been replaced by the new scopeManager property.

2.0

context.messageRouter.dispatchMessage(new MyMessage());

2.1

context.scopeManager.dispatchMessage(new MyMessage());

The ScopeManager dispatches through all scopes available in that Context. This way the receivers can decide which scope they want to listen to. You can alternatively dispatch to a single scope only:

context.scopeManager.getScope(ScopeName.LOCAL).dispatchMessage(new MyMessage());

Adjust configuration tags that register lifecycle listeners on an ObjectDefinition

The lifecycle mechanism has been expanded, there are now five events for the lifecycle of each object: preConfigure, preInit, postInit, preDestroy and postDestroy. Therefor the old ObjectLifecycleListener interface has been removed and you can register a function reference directly:

2.0

definition.lifecycleListeners.addLifecycleListener(this);

2.1

definition.objectLifecycle.addListener(ObjectLifecycle.PRE_INIT, preInit);

In the example for 2.0 this would refer to a tag that additionally implements ObjectLifecycleListener. In the example for 2.1 preInit references a function. The signature for the function is the same as in 2.0, the framework passes the instance itself and the Context. But the method could now be private as it is no longer required to implement an interface.

1.4 Parsley and Spicelib Module SWCs

Parsley and the underlying Spicelib are very modular, so you are able to only select the SWCs actually required for your application. The release folder in the download contains SWCs for Parsley and Spicelib which combine all the modules into a single large SWC (for both frameworks one SWC for Flex and one for Flash).

Alternatively the module folder contains smaller SWCs only containing a single framework module which can be combined to add only the feature set required by your application to the classpath. To use these smaller module SWCs it's essential to know the dependencies and the content of each SWC.

The following diagram shows the dependencies between the various SWCs. The names correspond to the names of the SWCs minus version number and suffix. Several optional dependencies were left out to keep the diagram clear. Most of them are obvious (e.g. several modules include custom XML configuration tags and in case you use those the module will also depend on parsley-xml). The Flex3 and Flex4 SWCs have been combined into a single Flex box for the diagram.

The following table summarizes the content for each of these SWCs:

spicelib-core Core utilities, errors and events.
spicelib-reflect The Spicelib Reflection API. See 17 Reflection for details.
spicelib-xml The XML-to-Object Mapper. See 18 XML to Object Mapper for details.
spicelib-task The Task Framework for asynchronous operations. See 19 The Task Framework for details.
spicelib-flash The Flash Logging Framework. See 20 Logging for Flash Applications for details.
parsley-core The core IOC Container - Dependency Injection, Messaging, Configuration with Metadata or ActionScript.
parsley-flex Flex Integration Features: 3.2 MXML Configuration, 7 Dynamic View Wiring, 8 Building Modular Applications.
parsley-xml Support for configuration with XML files. See 3.3 XML Configuration Files for details.
parsley-flash Flash Integration Features: 10.3 Localized Flash Applications, 13.2 Logging Configuration for Flash.
parsley-pimento Configuration Tags for Pimento and Cinnamon. See 12.2 Pimento Data Services and 12.3 Cinnamon Remoting.

1.5 Other resources

In addition to the material presented in this manual there are also some articles and sample applications available which have been created by other users. If you have created something that you want to see listed here just post a link in the Forum.