Granularity is a well-known topic in software development. Another common concept is encapsulation. There’s books, magazine articles, and blog posts about these topics going back decades (well, not the blog posts).
One challenge we’ve had recently is trying to apply these concepts to a Flex application that uses modules. We want a global data model that modules can access, but have no way to access its internal mechanisms (i.e. no public variables).
The core idea is that we want a common data model loaded into a basic Flex app – the Shell – which has no functionality, in and of itself, other than to load and unload modules that contain the business functionality.
This common data would then need to be accessible to every module that got loaded into the Shell – regardless of whether the module needed it or not.

First thing we need is establish an interface that each module can use to identify itself so that when the Shell loads it, the Shell recognizes that it should send its global data model to the module.
People and places have had their names changed to protect their identity…
package com.widget.common.interfaces
{
public interface ICoolModule
{
function getModuleController():Class
function setGlobalModel(model:Class):void
}
}
The key method defined for this mechanism is the setGlobalModel() method. This is the method that it called by the Shell (shown below) when it loads a module to ensure that each module has a reference to the global data model.
I then extended the basic Flex Module class, so that I could implement the ICoolModule interface and provide basic functionality for accessing the global data model
package com.widget.common.components
{
import com.widget.common.interfaces.ICoolModule;
import mx.core.Singleton;
import mx.modules.Module;
public class CoolModule extends Module implements ICoolModule
{
[Bindable] public var _globalModel:*;
public function CoolModule()
{
super();
}
public function getModuleController():Class
{
return null;
}
public function setGlobalModel(globalModelLocator:Class):void
{
_globalModel = Singleton.getInstance("IModelLocator") as globalModelLocator;
}
}
}
Now when I create a new module, it’s a CoolModule instead of the base Module.
<component:CoolModule xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:component="com.widget.common.components.*">
So now that we’ve set up things on the Module end, let’s see how the Shell actually injects its model into each Module. I’ve got a command that handles loading modules with a commandSuccess() method that handles the coupling (significantly stripped down version here just to show the relevent code).
package com.widget.thisApp.business.commands
{
import com.widget.thisApp.model.ModelLocator;
public class ModuleLoaderCommand extends AbstractCommand implements ICustomCommand
{
...
public function commandSuccess(event:Event):void
{
if(_component is ICoolModule)
{
var coolModule:ICoolModule = _component as ICoolModule;
...
coolModule.setGlobalModel(ModelLocator);
}
}
...
}
}
Now, for those who were paying attention, you may have figured out the key to all of this is that the ModelLocator is a singleton. As long as the module gets loaded into the current application and security domain…
module.load(ApplicationDomain.currentDomain, SecurityDomain.currentDomain);
…then it can access the Model singleton.
We’ve found that while module-parent, and module-module, communication is certainly not elegantly built into the Flex framework, it is possible with a little bit of grunt work. I’m hoping that as the Flex SDK matures and becomes more feature-rich that this feature become more robust.
5 Responses for "Cairngorm: Sharing a common ModelLocator with modules"
Hi,
Nice article, nice approach – what I’m doing is something similar where I can inject model objects into my module. The problem is getting the modules to fully unload. It seems that when I populate a datagrid (which has custom item renderers in them, the module will not unload. Also it seems that loading modules into the root ApplicationDomain will prevent them from unloading. Interested to see if you’ve dealt with this.
Jeff
Hi,
I’m having serious problems with loading modules into the same application domain.
could you share that code pleeeeeze? I’m banging my head agains the wall here ;-)
i tried:
NB the module loader doesnt have a securityDomain prop as it should default to the current one… again from the docs…
no luck. It gets placed in it’s own ApplicationDomain (which according to the docs should not happen)
I tried many other things but i’m at a loss now….
thanx in advance,
Arnoud
ihmm some code disappeared…
here it is:
<mx:ModuleLoader id=”ml” url=”ModuleA.swf” width=”100%” height=”100%” applicationDomain=”{ApplicationDomain.currentDomain}”>
Arnoud, not sure what I can do. The code I use is at the end of my article and appears to be doing the same as what you are trying to do. It should work, and if it isn’t, I don’t know why. Sorry.
Thanks for this.
Any idea why I’d get the following error?
Error: No class registered for interface ‘IModelLocator’.
I’m probably missing something that needs to be done in the actual ModelLocator itself. I’m just doing the normal Cairngorm routine right now.
Leave a reply