My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
UsingModules  
Using modules with Fabrication
Featured
Updated Jul 14, 2010 by rafael.s...@gmail.com


Introduction

Fabrication provides a very simple way of communicating between modules. It uses the pipes utility as the base layer for communication. This inter-module piping is done automatically and module communication is simplified into standard PureMVC notifications.

Requirements

This feature uses the Flash Player's reflection api and when using modular applications needs an additional getClassByName method in your application's main class. This method is needed to workaround the sandboxing of getDefinitionByName.

The following code must be present along with your getStartupCommand method for reflection to work.

override public function getClassByName(path:String):Class {
	return getDefinitionByName(path) as Class;	
}

Loading Modules

The approach to loading modules differs based on its environment. For loading Flex based modules, Flex specific classes need to be used. Whereas for Flash based modules plain Loader objects are sufficient.

Using Flex Module Loader for Flex Modules

Fabrication provides a FlexModuleLoader for loading flex modules. This class should be used when the child module extends the FlexModule fabrication class. FlexModuleLoader extends the native ModuleLoader class so the loading api and events are the same.

Loads the module, my_module.swf using the FlexModuleLoader

var moduleLoader:FlexModuleLoader = new FlexModuleLoader();

moduleLoader.url = "my_module.swf";
moduleLoader.loadModule();

Using Module Manager for Flex Modules

Flex modules can also be loaded using the ModuleManager. The ModuleManager only loads the module swf. It does not instantiate the loaded swf. That needs to be done manually after the loading has completed by invoking create on the module's factory.

Loads the module, my_module.swf using ModuleManager.

var module:IModuleInfo = ModuleManager.getModule("my_module.swf");
module.addEventListener(ModuleEvent.READY, moduleReadyListener);
module.load();

private function moduleReadyListener(event:ModuleEvent):void {
	var moduleInstance:Object = event.module.factory.create();
}

Using Fabrication module loader and Fabrication AIR module loader

You can use FabricationModuleLoader and FabricationAirModuleLoader to load module in browser or in desktop application. Both classes works similar to ModuleManager instances, but hides less important functionality from programmer. Only thing you need to do is register for ModuleEvent.READY event and retrieve module instance ( as flexModule getter ) in event handler. See example at the end of page.

Using plain Loader for Flash

Important Note

The distinction between Applications and Modules is specific to Flex. Fabrication does not make any distinction between applications and modules for Flash based applications. Any application swf that extends FlashApplication can be loaded into another FlashApplication application.

Loading a flash application module can be done using the native Loader class.

Loads the flash appliction module, my_module.swf using a Loader object.

loader = new Loader();
loader.load(new URLRequest("my_module.swf"));

Module Configuration

Modules must be configured before communication between modules can be performed. This is done by setting the router property on the module loader object. For Flex based modules this should be before loading by setting the property on the FlexModuleLoader instance. For flash based module, the property should be set on the Loader content after it has finished loading.

The router for an application can be obtained by the applicationRouter property. This property is available throughout the Fabrication base classes like FabricationMediator, SimpleFabricationCommand, etc.

By default a module is configured to communicate to all modules within a shell application. This behaviour can be overridden by setting the defaultRouteAddress of a module to the current application's module address. Doing so configures the module to send messages to the shell application that loaded it.

For Flex modules,

moduleLoader.router = applicationRouter;
moduleLoader.defaultRouteAddress = applicationAddress;

For Flash application based modules this needs to be done in the complete handler of the loader object used to load the module swf.

private function completeListener(event:Event):void {
	var content:FlashApplication = loader.content as FlashApplication;
	content.router = applicationRouter;
	content.defaultRouteAddress = applicationAddress;
}

Sending notification between modules

Communication between modules is done with the routeNotification method. This method is available in all the fabrication base classes like, FlexMediator, SimpleFabricationCommand, FabricationFacade, etc. The routeNotification is similar to the sendNotification method of PureMVC. However unlike sendNotification, routeNotification transports the notification across modules.

The syntax of routeNotification is,

routeNotification(noteName:Object, noteBody:Object, noteType:String, to:Object):void

To send a notification to the default module address use,

routeNotification("myNote");

Like sendNotification you can specify optional noteBody, and noteType arguments.

routeNotification("myNote", new Object(), "myType");

To send notification to a module you use the to argument. The to argument supports the following formats.

  1. * - Sends the notification to all modules
  2. ModuleName/* - Sends the notification to all instances of the module, ModuleName
  3. ModuleName/ModuleInstance - Sends the notification to the ModuleInstance instance of the module, ModuleName.
routeNotification("myNote", null, null, "*"); // to everyone
routeNotification("myNote", null, null, "A/*); // to instances of the module A
routeNotification("myNote", null, null, "A/A0"); // to instance A0 of the module A

Handling notifications from modules

The notifications sends using routeNotification are converted to plain PureMVC notifications in the destination module. They can be mapped to commands or used with respondTo handlers, or plain handleNotification methods.

Sends a messageFromModule notification to all modules

routeNotification("messageFromModule", null, null, "*");

Handles the messageFromModule notification that originated in another module.

public function respondToMessageFromModule(note:INotification):void {

}

Sending custom notification objects between modules

You can also send custom typed notification object between modules. This is done by specifying the custom notification object as the first and only parameter of routeNotification. Handling the notification in destination module is same as with a dynamic notification.

Sends a custom ModuleNotification to all modules

routeNotification(new ModuleNotification(ModuleNotification.MESSAGE_FROM_MODULE));

Handles the custom ModuleNotification as a custom PureMVC notification.

public function respondToMessageFromModule(note:ModuleNotification):void {

}

Examples

  1. Simple Routing [Browse] [SVN]
  2. Using Flash based modules [Browse] [SVN]
  3. Using FabricationModuleLoader and FabricationAirModuleLoader Demo Source
Comment by deepshar...@gmail.com, May 16, 2009

Hey Darshan, Thanks for creating the gr8 utility! I am a newbie at PureMVC(mostly been playing with cairngorm) .With respect to modular sample you have ,I would want to seperate out the module as a seperate project just to keep things a little cleaner.Do you think it could pose any issues?

Comment by natwa...@gmail.com, Mar 17, 2010

IMPORTANT It seems like you need to set router and defaultRouteAddress properties on the module before adding it to the display list.

Comment by lukasz.m...@gmail.com, May 11, 2010

You can set router and defaultRouteAddress proprties after adding it ot the display list. Simple solution:

content.initializeFabricator(); content.router = applicationRouter; content.defaultRouteAddress = applicationAddress; content.dispatchEvent( new Event( Event.ADDED_TO_STAGE ) );

Comment by zhaozixu...@gmail.com, Jul 22, 2010

I saw a line of code in the simple_routing example:

routeNotification(FabricationRoutingDemoConstants?.RECEIVE_MESSAGE, "Message From Module", null, "SimpleModule?/#");

what does "SimpleModule?/#" here mean and how is it different from "SimpleModule?/"? Thank you.

Comment by project member rafael.s...@gmail.com, Jul 22, 2010

Hi, belive me or not - that is mistake. Of course, it should be "SimpleModule?/`". thanks for spotting it, I should fix the example now :)

Comment by grimmwe...@gmail.com, Mar 13, 2011

Raf -

I'm having a hell of a time trying to get modules to work properly with PopupManager?? -- can you tell me what I might be doing wrong or give an example?

I've got the main application mediator attempting to load in the widget (which is the mxml called OrderSubmit?? and a mediator of OrderSubmitMediator??):


private function loadOrderSubmitWidget():void{
			if(DEBUG){Log.info(NAME + ' Load OrderSubmit module')};
			var u:String = "com/investlab/mix/widgets/OrderSubmit/OrderSubmit.swf";
			//loadWidget(u, orderPlaceCallback);
			
			
			module = ModuleManager.getModule(u);
			Log.debug("ALMOST");
			module.addEventListener(ModuleEvent.READY, function(e:Event):void{
				Log.debug("popup after");
				ord = module.factory.create() as OrderSubmit;
				ord.width = 400; ord.height=300;
				PopUpManager.addPopUp(ord, FlexGlobals.topLevelApplication.stage, true);
				registerMediator(new OrderSubmitMediator(ord));
				PopUpManager.centerPopUp(ord);
Comment by grimmwe...@gmail.com, Mar 13, 2011

The above doesn't seem to thrown an error -- but nothing is shown, so I'm definitely doing something wrong.

Usually I throw the string (u above) to a function with a callback (as above OrderPlaceCallback?


private function loadWidget(u:String, f:Function):void{
			var m:FlexModuleLoader = new FlexModuleLoader();
			m.router = applicationRouter;
			m.defaultRouteAddress = applicationAddress;
			m.url = u;
			m.addEventListener(ModuleEvent.READY, f);
			m.addEventListener( ModuleEvent.ERROR, loggerModuleErrorHandler );
			application.addElement(m);
			m.loadModule(u);
		}

the above works but I can't use it as a popup.


Sign in to add a comment
Powered by Google Project Hosting