Parsley 2.2 and Spicelib 2.2 Implementation Details – Facebook Photo Gallery

All flex applications are event driven. With Parsley messaging framework managing events is a lot more easier. You don’t have to manually dispatch and listen for events. Using Parsley defined metadata tags the code becomes cleaner, shorter, more easier to understand and maintain. Add Parsley Inversion of Control (IOC) framework and you have the means to easily create highly decoupled applications. Below steps take AlbumModule as a reference.

1. Configuration.
As a first step, Parsley needs to know which classes it should manage via the IOC Container. For Facebook Photo Gallery this is done via mxml configuration files. Each module has its own configuration file and so does each separate module launcher, including the main launcher from the asabau_cg3_fb_shell project.

For example, for the AlbumModule we have the following mxml configuration files:

  • AlbumModuleLauncherContext.mxml – Used by AlbumModuleLauncher for separate testing of AlbumModule. Contains objects outside AlbumModule needed to initialize the AlbumModule.
  • AlbumContext.mxml – Contains objects needed by AlbumModule.

From AlbumContext.mxml:
<pres:AlbumPM />
<pres:PhotoPM />
<domain:AlbumList />
<domain:PhotoList />
<fb_domain:AlbumData />
<fb_domain:PhotoData />
<app:LoadAlbumListCommand />
<app:LoadPhotoListCommand />
<app:SavePhotoCaptionCommand />

All of the above objects are now part of the IOC Container and will be managed by the Parsley framework. There are presentation models, model objects, command classes. All can now make use of Parsley dependency injection and messaging framework.

2. Initialization
Via mxml tags, in each module top view, we specify the configuration file context location via ContextBuilder and then initialize the IOC Container via Configure.
<parsley:ContextBuilder config="{AlbumContext}" id="context" />
<parsley:Configure />

The IOC Container configuration happens before creationComplete, this is a useful information when you want to dispatch framework registered events from the parent container to the child module. Using the <parsley:Configure /> tag you know for sure that when creationComplete is triggered, IOC container and all its objects have been initialized. It’s now safe to dispatch events in the parent container, they’ll be handled in the child module.

3. Dependency Injection
Each object from the IOC Container can make use of the [Inject] metadata tag and most of them do. From LoadAlbumListCommand:
[Inject]
private var fbSession:FBSession;

This injects a FBSession singleton in the command class. Other classes injecting the same variable type FBSession will get the same singleton instance. This is the default behavior, but you can have non singleton variables if needed. For all Album and Authentication classes, fbSession represents the same Facebook session used in all Facebook calls.

Parsley IOC framework is responsible for adding the singleton behavior to the FBSession class at runtime. FBSession class code doesn’t contain any singleton specific code.

4. Messaging
For Parsley framework to handle app custom events you need to mark them as managed events in the object dispatching them, object that is part of IOC Container. This way sender and receiver objects don’t need to know each other, messaging takes place in a decoupled manner. You don’t have to use any specific Parsley methods to dispatch events, you can do it with the standard actionscript dispatchEvent assuming at some point the sender object extends EventDispatcher. Because of this, we can talk about sender and receiver objects being decoupled from the framework as well.

From AlbumPM, presentation model for the view displaying the end user photo albums:
[Event(name="albumSelect", type="com.asabau.facebook.album.AlbumEvent")]
[ManagedEvents("albumSelect")]
public class AlbumPM extends EventDispatcher

From its selectAlbum function

public function selectAlbum(album:AlbumData):void {
	....
	dispatchEvent(AlbumEvent.newSelectEvent(album));
	...
}

All event handling is done in asynchronous Command classes via Command, CommandResult, CommandError tags. Intercept tag is being used to override the Command classes and “fake” CommandResult data. This can be useful when launching standalone modules that rely on other modules for some features. Like AlbumModule requiring AuthenticationModule to establish a Facebook connection before getting the album list. Via Intercept, we can supply a static album list data set to AlbumModule and not rely on AuthenticationModule.

From LoadPhotoListCommand, command triggered when above AlbumEvent.newSelectEvent gets dispatched:

[Command(selector="albumSelect")]
public function execute(event:AlbumEvent):Task {
	...
	return Task;
}

CommandResult and CommandError are invoked automatically by the Parsley framework when the async call represented by the Task object has completed.

[CommandResult(selector="albumSelect")]
public function resultHandler(task:FBCallTask, event:AlbumEvent):void

[CommandError(selector="albumSelect")]
public function faultHandler(
	faultEvent:FaultEvent,
	trigger:AlbumEvent):void

5. Spicelib Task Framework
With Parsley 2.2 Command classes like the one above can now make use of both AsyncToken and Task objects to identify asynchronous calls. This makes a lot of sense because only a few flex async operations are capable of returning AsyncToken objects like, for example, HTTPService.send method.

The Facebook actionscript API doesn’t contain any methods returning AsyncTokens when doing asynchronous server calls. The Task object helps tremenduously here, we get to have the same AsyncToken functionality for any custom async operation.

From FBCallTask
import org.spicefactory.lib.task.Task;
public class FBCallTask extends Task

private function parentCallComplete(event:FacebookEvent):void {
	if (event.success) {
		...
		complete();
	}
	else {
		error(...)
	}
}

First we override the default doStart Task method, defining how the async operation starts and adding event complete handlers to it. The doStart command gets invoked automatically by the Parsley framework responsible for handling the Command class. When the async operation has completed, we either call Spicelib Task complete or error methods responsible for dispatching the corresponding events. These events are managed by the Parsley Command class where the Task object in question is being used. Based on event type either CommandResult or CommandError gets triggered.

This post is part of Facebook Photo Gallery.

2 thoughts on “Parsley 2.2 and Spicelib 2.2 Implementation Details – Facebook Photo Gallery”

  1. Im having and issue using modules every time I move the module window to a new screen or minimize I get this error

    TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at org.spicefactory.parsley.tag.messaging::DynamicCommandTag/contextDestroyed()[I:SpicefactoryParsleyparsley-configorgspicefactoryparsleytagmessagingDynamicCommandTag.as:170]
    at flash.events::EventDispatcher/dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at org.spicefactory.parsley.core.context.impl::DefaultContext/destroy()[I:SpicefactoryParsleyparsley-coreorgspicefactoryparsleycorecontextimplDefaultContext.as:297]
    at org.spicefactory.parsley.core.view.impl::DefaultViewManager/removeViewRoot()[I:SpicefactoryParsleyparsley-coreorgspicefactoryparsleycoreviewimplDefaultViewManager.as:156]
    at org.spicefactory.parsley.core.view.impl::DefaultViewManager/viewRootRemoved()[I:SpicefactoryParsleyparsley-coreorgspicefactoryparsleycoreviewimplDefaultViewManager.as:141]
    at flash.display::DisplayObjectContainer/addChild()
    at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::createContentPane()[C:autobuild3.5.0frameworksprojectsframeworksrcmxcoreContainer.as:4708]
    at mx.core::Container/createOrDestroyScrollbars()[C:autobuild3.5.0frameworksprojectsframeworksrcmxcoreContainer.as:4453]
    at mx.core::Container/createScrollbarsIfNeeded()[C:autobuild3.5.0frameworksprojectsframeworksrcmxcoreContainer.as:4402]
    at mx.core::Container/createContentPaneAndScrollbarsIfNeeded()[C:autobuild3.5.0frameworksprojectsframeworksrcmxcoreContainer.as:4218]
    at mx.core::Container/validateDisplayList()[C:autobuild3.5.0frameworksprojectsframeworksrcmxcoreContainer.as:2734]
    at mx.core::Window/validateDisplayList()[C:autobuild3.5.0frameworksprojectsairframeworksrcmxcoreWindow.as:2177]
    at mx.managers::LayoutManager/validateClient()[C:autobuild3.5.0frameworksprojectsframeworksrcmxmanagersLayoutManager.as:880]
    at mx.core::UIComponent/validateNow()[C:autobuild3.5.0frameworksprojectsframeworksrcmxcoreUIComponent.as:5690]
    at mx.core::Window/window_resizeHandler()[C:autobuild3.5.0frameworksprojectsairframeworksrcmxcoreWindow.as:3122]

    1. I get no errors/warnings when launching the sample facebook app shown here… Are you taking about your own custom code? If so, what does exactly “move the module window” mean? Once I can replicate it, I can start fixing it.

Leave a Reply

Your email address will not be published. Required fields are marked *