PureMVC Architects Lounge

Announcements and General Discussion => Fabrication => Topic started by: Darshan Sawardekar on October 17, 2008, 08:50:52



Title: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 17, 2008, 08:50:52
Hi All,

I have released Fabrication 0.4. And its now on Google Code[1]. This is an important step forward in PureMVC application development. You can read about it here[2]. Enjoy.

peace,
darshan

[1] : http://fabrication.googlecode.com
[2] : http://www.codedrunks.com/index.php/2008/10/17/fabrication-04-released/


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 17, 2008, 09:43:44
Awesome news! Thanks, Darshan!


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 17, 2008, 11:11:22
With the elimination of the ApplicationFacade, does one register all their commands in the StartupCommand now? So essentially the old ApplicationFacade has moved to the StartupCommand? I haven't tested yet, but I wonder how well the StartupManager utility will play with Fabrication. I think it should be fine.

Just trying to wrap my head around building large apps (many commands) using Flash with Fabrication. I assume only our old "JunctionMediator" mediator extends FlashMediator. The rest of our mediators still extend PMVC's Mediator unless we need the routing of Fabrication?

Just want to make sure I understand correctly.


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 18, 2008, 07:26:59
With the elimination of the ApplicationFacade, does one register all their commands in the StartupCommand now? So essentially the old ApplicationFacade has moved to the StartupCommand? I haven't tested yet, but I wonder how well the StartupManager utility will play with Fabrication. I think it should be fine.
Yes the registration of commands needs to happen in the StartupCommand with Fabrication. The StartupManager utility works fine with it, I am using it as well. PureMVC is a very extensible framework with such aspects. Fabrication only adds behaviours at the typical extension points like, FlexApplication/FlashApplication, FlexMediator, SimpleFabricationCommand, etc.

Just trying to wrap my head around building large apps (many commands) using Flash with Fabrication. I assume only our old "JunctionMediator" mediator extends FlashMediator. The rest of our mediators still extend PMVC's Mediator unless we need the routing of Fabrication?

There is no need for the JunctionMediator at all. The routing of pipe messages happens entirely underneath the system. You indicate interest in a notification implicitly by writing a respondToNotificationName method in your mediator(for your environment). When you do a routeNotification the respondTo method will be called automatically. You can find more information here[1].

Btw, If you are familiar with Flex also check out the link I mentioned[1]. Fabrication 0.4 added Reflexive mediator registration for Flex deferred component instantiation. I am looking for feedback for applying this to Flash projects. Flash components do not seem to have support for deferred instantiation, but I am not very familar with the those components, so i may be wrong. I am thinking more on the lines of something to support the MovieClips hierarchy of Flash.

Let's say you have MovieClip assets that are placed on the stage. This may be deep and possibly design driven. And additionally not explicitly given top level instance names. I should be able to mediate components/display objects in this hierarchy in an easy way.

I am just thinking out loud here. It would be great if you can share your thoughts on the workflow with flash projects with PureMVC.

peace,
darshan

[1] : http://www.codedrunks.com/index.php/2008/10/17/fabrication-04-released/


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 18, 2008, 11:21:07
There is no need for the JunctionMediator at all. The routing of pipe messages happens entirely underneath the system.

Sorry I may have mislead you with that statement. What I meant was the that we are replacing our old JunctionMediator with the Fabrication style mediator, but my other Mediators could remain the same (extending just Mediator) unless they needed the functionality of routing. Since my project is already well underway, I'm trying to add fabrication into my existing code and was just "speaking out load" about where I could avoid changing old code.


Title: Re: Fabrication 0.4 released
Post by: freakinruben on October 20, 2008, 05:43:59
Hi Darshan,

I've just started to implement this new version. First thing I've noticed is the direct relation with the FlexModuleLoader in FlexModuleFabricator. Because of this relation it is now impossible to load modules without the ModuleLoader (I always used the ModuleManager). In the previous version I could just manually call setDefaultRouter and acceptRouter... Is there any way I could still use the ModuleManager to load my modules (I don't like the overhead of the ModuleLoader...)?

Thanks it advance, and I will give more feedback as soon as I got better knowledge of all the changes  ;).

Ruben


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 20, 2008, 06:12:57
Jason,

You are right if you just need the message routing, you do not need to extend the FlashMediator/FlexMeditaor. However, If you intend to use Reflexive notification interests, you will need to extend FlashMediator/FlexMediator. Moving forward this is going to the key integration point for new Mediator specific features.

Ruben,

I didn't realize you were using ModuleManager. Serve's me right for developing in the dark, I guess. ;-) In 0.4 the FlexModuleFabricator looks up the router from the parent ModuleLoader so its linked for the moment. I will try to fix this soon. Can you post some sample code, It would help clarify the usage?

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 20, 2008, 06:16:44
Jason,
However, If you intend to use Reflexive notification interests, you will need to extend FlashMediator/FlexMediator. Moving forward this is going to the key integration point for new Mediator specific features.

I'm using Pure AS3 for the moment so the Reflexive Notes aren't much use to me. But I'll keep in mind that future features will be added to the mediator and update my files accordingly. Thanks for the input.


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 20, 2008, 06:19:32
Jason,

Reflexive notification is supported with AS3 also. The reflexive mediator registration is Flex specific because only Flex components support deferred instantiation.

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: freakinruben on October 20, 2008, 06:49:39
Darshan,

Thanks for your quick response. Here is some code of when I used the old fabrication, so I hope this clarify's it a bit.

Quick description:
My application call's the loadPlugin method for every "plugin" it want's to use. When the application is started, there can be many instances of every "plugin" so when the user wants a new instance, it calls PluginManager.getModule(...) which then returns a new instance of the requested plugin.

The PluginManagerMediator listens to the events of the PluginManager and connects every instance of the plugin that's created.

PluginManager:
:
public function loadPlugin(pluginVO:PluginVO) : void
{
var module:IModuleInfo = ModuleManager.getModule(pluginVO.filename);
module.data = pluginVO;
module.addEventListener(ModuleEvent.READY, onModuleLoaded, false, 0, true);
module.addEventListener(ModuleEvent.ERROR, onModuleFailedLoading, false, 0, true);

//add module to the loading queue
modules.push(module);

//dispatch an event that the module is getting loaded
dispatchEvent( new PipeEvent(PipeEvent.PLUGIN_IN_QUEU, pluginVO) );

module.load(ApplicationDomain.currentDomain);
}


protected function onModuleLoaded(e:ModuleEvent) : void
{
var module:IModuleInfo = e.module;
var pluginVO:PluginVO = module.data as PluginVO;

//remove module from loading queue
removeModuleFromQueue( module );

//add module to available modulesList
components[ pluginVO.title ] = module;
pluginVO.loaded = true;
}


/**
* ComponentFactory.
*
* @param name name of the component which should be instantiated
* @return instance of the requested component
*/
public static function getModule (data:ModuleVO):FlexModule
{
var module:IModuleInfo = components[ data.type ] as IModuleInfo;
var component:FlexModule = module.factory.create() as FlexModule;

instance.dispatchEvent( new PluginEvent( component, PluginEvent.CREATED ) );
component.addEventListener(FlexEvent.INITIALIZE, instance.onPluginReady, false, 0, true);

return component;
}

PluginManagerMediator:
:
protected function onPluginCreated (event:PluginEvent) : void
{
event.plugin.setDefaultRoute( applicationModuleAddress.getInputName() );
}


protected function onPluginInitialized (event:PluginEvent) : void
{
event.plugin.acceptRouter( applicationRouter );
}


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 20, 2008, 07:19:06
One more minor question/curiosity.

Is there a reason FlashApplication extends MovieClip rather than Sprite? MovieClip tends to carry a lot of extra code that isn't needed. Just curious. I can change my local copy to extend Sprite instead of MovieClip but was curious if there was a specific reasoning for it.


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 20, 2008, 07:26:45
Btw, If you are familiar with Flex also check out the link I mentioned[1]. Fabrication 0.4 added Reflexive mediator registration for Flex deferred component instantiation. I am looking for feedback for applying this to Flash projects. Flash components do not seem to have support for deferred instantiation, but I am not very familar with the those components, so i may be wrong. I am thinking more on the lines of something to support the MovieClips hierarchy of Flash.

Let's say you have MovieClip assets that are placed on the stage. This may be deep and possibly design driven. And additionally not explicitly given top level instance names. I should be able to mediate components/display objects in this hierarchy in an easy way.

I am just thinking out loud here. It would be great if you can share your thoughts on the workflow with flash projects with PureMVC.

peace,
darshan

[1] : http://www.codedrunks.com/index.php/2008/10/17/fabrication-04-released/

I meant to respond to this earlier, sorry it slipped my mind.

I think the largest problem you'll encounter is the fact that, unlike Flex, there is no Adobe endorsed component framework for Flash that supports deferred instantiation - at least not in the same way Flex does since Flash components do delay rendering but only frame by frame to avoid rendering every time a style changes, instead it defers rending until the next enter_frame event. So any Component Framework that does allow this would be user made and subject to any number of implementations that would be hard to predict. I think to do this in Flash would require also building the skeletal structure of a Flash Component Frame for people to then build visual components off of that would have deferred instantiation inherent in the framework.

There might be a way of doing by manipulating the addChild method, but I'm not sure off the top opf my head. Flash components use a two stage approach to rendering. The first part calls ConfigUI when the component is first created, this allows you to set-up listeners and do any other prerendering set-up. The second part comes when the Stage becomes available to the component (through either addChild or some other method which triggers the ADDED_TO_STAGE event) which then triggers the Draw() method and rendering completes. If you could find a way of adding a listener between the ConfigUI state and Draw() call you might be able to accomplish what you want (adding a mediator at render time but not creation time?) Though to me this isn't really the same thing as deferred instantiation.


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 20, 2008, 07:36:26
Ruben,

Ok, I think I got it. You need to set the defaultRoute and the router on the module. I think you will need a FabricatorEvent.FABRICATION_CREATING event where you do something like,

:
// for setting the module's default route to the shell
event.plugin.defaultRoute = "*"; or event.plugin.defaultRouteAddress = applicationAddress;
event.plugin.router = applicationRouter;

The current FABRICATION_COMPLETE event is fired after the fabrication is created. I will change the FlexModuleFabricator to fix this by tomorrow.

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 20, 2008, 08:03:23
Jason,

Thanks for your comments. Regarding extending MovieClip, I have kept it for people who might need to extend MovieClip. Extending Sprite would otherwise require 2 sets of fabricators. There is a slight performance hit which should probably be reasonable as long as the internals use Sprite in animations and drawing stuff.

Your points about the lack of deferred instantiation in CS3 components are valid. And it would be difficult to support all the different variations. I am thinking of sticking to Flash designer specific stuff. The link up between the graphic assets into behaviour from CS3 pov is with the instanceName. I am thinking of trying to target this.

So for instance if the graphic designer placed 2 buttons at different points of time on the timeline. Lets say both these buttons are for the same action, to toggle full screen mode. Now suppose I have a FullScreenButtonMediator which adds a listener to the buttons and provides the full screen toggle behaviour. I want to be able to code something like,

:
registerMediator(new FullScreenButtonMediator(resolver(app).re("fullScreenButton.*")));

So the designer has basically indicated behaviour of the button by giving it an instance name like fullScreenButton1, etc. Your thoughts?

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 20, 2008, 10:05:58
My understanding of the "resolver" aspect of your code is pretty limited atm. I'll have a look at how it works in Flex and see if there's something that could be done. My guess is you need some way of being alerted that a new instance of a button has been created, and I'm not sure the facilities exists out-of-box for this in Flash. If you had a way to injection this behavior into the UIComponent Class (base for all visual components in Flash) then you could certainly do it, but I don't believe Flash components fire off any global events by default. So I'm not sure how you would find out about new instances unobtrusively.


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 21, 2008, 05:24:19
Ruben,

I have fixed the FlexModule to allow loading of modules directly using the ModuleManager. The fix is available from the google code page[1] version 0.4.1. I ended up not requiring the custom event because the ModuleEvent.READY does the job nicely.

In your code's ready handler you will need to do something like,

:
protected function onPluginCreated (event:PluginEvent) : void {
   event.plugin.defaultRouteAddress = applicationAddress;
   event.plugin.router = applicationRouter;
}

The accept router call won't be needed. The new fabricator takes care of that. I duplicated the simple_routing example to simple_routing_with_module_manager[2]. You can refer to this example for further details. The key changes are in ModulesContainerMediator#moduleReadyListener. The rest are minor changes to remove the cast to ModuleLoader.

peace,
darshan

[1] : http://code.google.com/p/fabrication/downloads/list
[2] : http://fabrication.googlecode.com/svn/examples/simple_routing_with_module_manager


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 21, 2008, 10:48:36
Quick question about the TO: field on routeNotification. I'm getting some weird behavior. I have a module called DataService, which has an instance name of DataService0 according to moduleAddres.getInstance(). However when I ask the shell to send a route to DataService/DataService0 the module never gets it. However if I use DataService/* _OR_ DataService/DataService0/INPUT I recieve the message. Any ideas? I've tried tracing it all the way to the junction call and can't see anying that would cause this.

Should there be entries in the junction.inputPipes array for more than Shell/Shell0/INPUT and DataService/DataService0/INPUT?


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 21, 2008, 11:27:50
Well spotted. Some of the internal piping is showing there. I think I need to add a check in the RouteNotificationCommand. Something like,

:
if (to != "*" && !(new RegExp("\/INPUT").test(to)) {
   to += "/INPUT";
}

I will verify everything works and check this in tomorrow. Please use the explicit /INPUT for the moment.

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 21, 2008, 11:57:18
Well spotted. Some of the internal piping is showing there. I think I need to add a check in the RouteNotificationCommand. Something like,

:
if (to != "*" && !(new RegExp("\/INPUT").test(to)) {
   to += "/INPUT";
}

I will verify everything works and check this in tomorrow. Please use the explicit /INPUT for the moment.

peace,
darshan

No problem, glad to help. For now I'm just using MyMOdule.moduleAddress.getInputName() to send to a specific instance.

Again, I have to say great job! It's taking a bit to learn, but it's a very powerful utility and I thank you for sharing it. It's going to save me a lot of time once I get it fully implemented into my project.


Title: Re: Fabrication 0.4 released
Post by: freakinruben on October 21, 2008, 02:10:54
Wow that's quick Darshan! Thanks. You've really done a great job with 0.4  ;D.

I've been busy refactoring some of my own code and finally everything is working again with 0.41 so that's quite a relief.

One question I have so far is about the new FabricationProxy.
I have several modules who's proxy extend the same base proxy, named "DataProxy". When they extend "DataProxy", they don't change the ProxyName because I wanted them to share a couple of Commands which fill the "DataProxy".

So in my situation you have "Module1Proxy" and "Module2Proxy", which both extend "DataProxy" and therefore are both registered as "DataProxy" (within their own core). When one of them get's filled they send a notification "DATA_SET", but because the registered name ("DataProxy") is not the same as the classname ("Module1Proxy"), the fabricationproxy class changes the notificationname to "DataProxy/DATA_SET". So the notification never reaches my mediator...

So my question is, why does the notificationname get changed when the registered proxyname is not same as the classname?


Here are some other small comments, but nothing really big so far.
A small addition to the FlexModule class is to add some event metadata
:
[Event(type="org.puremvc.as3.multicore.utilities.fabrication.events.FabricatorEvent", name="fabricationCreated")]
[Event(type="org.puremvc.as3.multicore.utilities.fabrication.events.FabricatorEvent", name="fabricationRemoved")]

Although I've seen a "removeEventListener" for every "addEventlistener", another addition I've made myself is to add "false, 0, true" to every addEventListener call to make sure those references won't cause any memoryproblems... (yes I know, not really necessary)

Tnx,
Ruben


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 21, 2008, 10:24:04
Hey Ruben,

I've been busy refactoring some of my own code and finally everything is working again with 0.41 so that's quite a relief.
Its a relief for me too that you got it working. I was afraid I had gone a little overboard with some of the features. ;-)

One question I have so far is about the new FabricationProxy.
I have several modules who's proxy extend the same base proxy, named "DataProxy". When they extend "DataProxy", they don't change the ProxyName because I wanted them to share a couple of Commands which fill the "DataProxy".

...
So my question is, why does the notificationname get changed when the registered proxyname is not same as the classname?

Good point. This is by design, and works well with the Reflexive Notification interests. I am using some of my Proxies in a similar manner,i.e.:- Multiple instances of the same proxy with a different proxy name. However since the Proxy is the same the notification name is common between them. This is a conflict with the PureMVC's notification system, where each notification name must be unique. Hence the 2 part notification name expansion.

There are 2 ways to handle such notifications. The first and easiest is using respondToProxyName. If you name your handler like respondToMyProxy, Whenever the proxy named MyProxy, dispatches a notification this handler will be called automatically. The fabrication mediator picks this notification interest up using reflection. So in your case the code would be,

:
public function respondToModule1Proxy(note:INotification):void {

}

// and

public function respondToModule2Proxy(note:INotification):void {

}

The convention is to have your proxy named something like MyCustom<Proxy>. Any respondTo method with a Proxy in its name is interpreted as a notification interest in that proxy.

The second way is a little involved. In this approach you need to qualify the notification explicitly using qualifyNotificationInterests in a mediator. So in your case if you need to do something like,

:
override public function qualifyNotificationInterests():Object {
   return {dataSet : "Module1Proxy"};
}

public function respondToDataSet(note:INotification):void {

}

This does the expansion of the DATA_SET notification from Module1Proxy to Module1Proxy/dataSet. So you can use respondToDataSet. Hope this clarifies things a bit. I haven't figured yet out how to qualify the same note name with different Proxies without method overloading. So if you might have to stick to the first approach.

If this is something you would like to avoid you can use,

:
override public function getNotificationName(note:String):String {
   return note;
};

Should I add a flag like expansion:Boolean to turn this behaviour on or off?

Here are some other small comments, but nothing really big so far.
A small addition to the FlexModule class is to add some event metadata
Sure, I will do the same.

Although I've seen a "removeEventListener" for every "addEventlistener", another addition I've made myself is to add "false, 0, true" to every addEventListener call to make sure those references won't cause any memoryproblems... (yes I know, not really necessary)
Can you tell me where you would like to add this? In general most of the classes in Fabrication implement the IDisposable interface to clean up before they are deleted. My preference is towards explicit removeEventListener and overall cleanup. If an object is no longer used I tend to delete it and any references to it in the dispose method.

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 22, 2008, 12:55:02
Jason,

I have fixed the routeNotification issue you encountered earlier. You can now use module.moduleAddress directly in the to, or ModuleName/InstanceName without the /INPUT.

Ruben,

I added the expansion property to FabricationProxy, that i mentioned earlier.

The version is updated to 0.4.2[1].

peace,
darshan

[1] : http://code.google.com/p/fabrication/downloads/list


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 22, 2008, 06:06:56
Jason,

I have fixed the routeNotification issue you encountered earlier. You can now use module.moduleAddress directly in the to, or ModuleName/InstanceName without the /INPUT.

Awesome, thanks.

BTW, I know Ruben mentioned listener clean-up a bit... do you happen to have any examples on how to ensure a module loaded using Fabrication is properly removed. Like what methods need to be called prior to deleting. I had a quick scan of the examples and didn't see anything.


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 22, 2008, 06:24:56
I haven't got an example of this yet, but its mostly one call. You need to call module.dispose() to cleanup a module. That call does disposal of all the internals like the facade, controller, view, commands, etc. I am also dispatching a SHUTDOWN notification prior to the module's disposable. If you wish to perform any custom cleanup in the module before disposable, you can register a command with this notification.

As a general practice most of the classes implement the IDisposable interface. So when you extend any class you should override the dispose method, implement any custom cleanup if needed and then call super.dispose().

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on October 24, 2008, 07:14:31
I hope I'm not driving you nuts with all the questions... but I'm not sure if this is intentional or something I'm missing. Right now I have a Shell App and two modules, Logger and DataService. Everything is working as it should except that messages sent from DataService can only be listened for by Shell and not by Logger. Is there a method I'm missing somewhere to lay pipes Module-to-module? I was under the impression that because they all use the same Router that it wasn't necessary but it seems it I don't give a TO: in the routeMessage then messages from DataService are always routed to Shell/Shell0/INPUT where I was hoping it was sending globally.


UPDATE: Looks like I may have found another bug. In RouteNotificationCommand's execute if the to: is set to "*" the if/else statements end up converting "*" to "*/INPUT" which then gets ignored by everything. When I change these if/else statements to skip doing anything to "*" everything seems to work and my modules all get notified.

It's the line below that converts "*" to "*/INPUT":
:
else if (to is String && !allInstanceRegExp.test(to as String)  && !ModuleAddress.inputSuffixRegExp.test(to as String)) {
to = (to as String) + ModuleAddress.INPUT_SUFFIX;

I just added && to != "*" to the end of that and everything works
:
} else if (to is String && !allInstanceRegExp.test(to as String)  && !ModuleAddress.inputSuffixRegExp.test(to as String) && to != "*") {


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 24, 2008, 09:24:08
Hey Jason,

This is great feedback. And your diagnosis and fix is correct. I will check this into the repo tomorrow.

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on October 29, 2008, 07:27:43
Hey Jason,

I have committed this fix to the svn and updated to 0.4.3. Sorry it took so long.

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on November 04, 2008, 07:21:32
A little more to add. Ive being working on cleaning up my "modules" for removal and noticed that calling the FabricationFacades.dispose() method on a module does a nice job chaining calls for removal of references. One thing I found interesting was that it checks whether the view implements an IDisposable interface, but Fabrication uses the base PMVC view. I found this to be a great idea since I have been trying to find a way to dispose of a number of dynamic mediators but can't get a reference to the views mediatorMap since it's a protected property of the View. So I went ahead and added a FabricationView to implement the dispose method on so I could be sure to dispose of all currently referenced mediators. I'll leave it up to you if you want to add it or not, but here it is. I'm debating doing the same for the Model since I really want to clear EVERYTHING before unloading a module, including any stray StartupManager references. This seems to give a nice clean way to run the dispose() and onRemove() methods for all for proxies, mediators and commands. Plus I still have the option of using a shutdown command based on the notification to do any other clean-up.

Here's the code for the view.


FabricationView
:
/**
 * Copyright (C) 2008 Darshan Sawardekar.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 package org.puremvc.as3.multicore.utilities.fabrication.core {
import org.puremvc.as3.multicore.core.View;
import org.puremvc.as3.multicore.interfaces.IMediator;
import org.puremvc.as3.multicore.utilities.fabrication.interfaces.IDisposable;

/**
* FabricationView is the custom view used by fabrication.
* It allows for the disposal of all currently registered mediators
* at once.
* @author Jason MacDonald (Jason.MacDonald@vfmii.com)
*/
public class FabricationView extends View implements IDisposable {

/**
* Creates and returns the multiton instance of the view for
* the specified multiton key.
*
* @param key The multiton key whose view is to be retrieved.
*/
static public function getInstance(key:String):FabricationView {
trace(instanceMap[key]);
if (instanceMap[key] == null) {
instanceMap[key] = new FabricationView(key);
}

return instanceMap[key] as FabricationView;
}

public function FabricationView(key:String) {
super(key);
}

/**
* @see org.puremvc.as3.multicore.utilities.fabrication.interfaces.IDisposable#dispose()
*/
public function dispose():void {

for each(var mediator:IMediator in mediatorMap) {

if (mediator is IDisposable) {
IDisposable(mediator).dispose();
}
// check if mediator still exists or it was removed in the dispose call
if (hasMediator(mediator.getMediatorName())) {
// removing the mediator also removes it's observerMap references, good to call
removeMediator(mediator.getMediatorName());
}
}

instanceMap[multitonKey] = null;
}

}
}


Addition to FabricationController to override parent initialize call of view
:
    override protected function initializeController():void {
           view = FabricationView.getInstance( multitonKey );
     }

On a side note, thanks to fabrication I've successfully created a mutli-tiered Flash application (modules within modules loaded at run time) that can be then loaded inside a Flex application for debugging and hook into all the routing and notifications sent within the Flash app for logging. Simply awesome work, thanks Darshan! Not sure I could have accomplished the same thing without your hard work.


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on November 04, 2008, 01:13:54
Well after diving even further into unloading of modules I've discovered that regardless of cleanup, modules loaded into a Flex Fabrication shell will never be GC'd. I haven't figured out why but using a basic Flex application loading a Fabrication swf file (just a basic Flash file with the document class as FlashApplication and a 1MB image on the stage) won't ever get GC'd after removing. If you put the loaded swf in it's own ApplicationDomain or exclude Fabrication from the Flex shell, the SWF file will get GC'd when unloaded.

All I can figure is there is something somewhere in Fabrication holding a reference between the loaded SWF and Flex. Keep in mind this is with no custom code anywhere other than the Flex loading and unloading functions. So there's no extra stuff being loaded in the SWF file (I don't even give a startup command so I could halt further execution).

I'm using Google's Chrome browser to track the memory usage. Repeated loading/unloading drives the memory up, almost doubling every time load/unload is run. But either setting the loaderContext to it's own ApplicationDomain, or setting the Flex shell to extend something other than Fabrication, the loaded swf is unloaded and memory is released. Hopefully we can track this down as this puts a huge damper on my usage of Fabrication:(

The files can be found here (http://www.allairis.com/test.rar)

Change the MemoryTest.mxml file to extend Fabrication instead of MX:Application to see the memory increase. Sorry it's a pretty simple test but unless I'm missing something it proves the inability for GC to remove the swf completely if both the loader and loadee use Fabrication. I'm thinking it might be something in the routing somewhere. Using dispose() on the swf before unloading doesn't seem to help.


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on November 05, 2008, 06:58:09
Hey Jason,

I had left out the concrete Model and View for later. Your example seems to be a good time to implement this. I am currently doing the units test for Fabrication. And I did discover some of the clean up issues also. A few important classes like DynamicJunction had not implemented IDisposable among others. Things are slightly broken at the moment because I am doing the unit tests after the implementation. I have to be careful about not breaking anything in stuff that is not yet tested.

Fundamentally I do not see any reason that things would not get gc'd correctly. There is extensive implementation of IDisposable throughout the framework. I will get back in a day or so with a fix.

peace,
darshan




Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on November 05, 2008, 07:29:43
Thanks Darshan, I really appreciate the help. I had a rather sleepless night last night fearing my project just went up in smoke with this problem :)

I'll continue to dig through things and see what I can find. Until I can resolve the issue I'm not comfortable moving forward in my project, so I'll try to help as much as I can. One thing that is frustrating me, and I think this is a Flex problem, is when I'm debugging I often can't inspect things like ModuleAddress and many other properties in the debugger. They show a folder to open, but when I click to expand it's empty. Again, I think this is a weird Flex thing since I don't get the same issue when using the Flash debugger.


Title: Re: Fabrication 0.4 released
Post by: Anty on November 05, 2008, 04:33:21
Hey guys,

I wanted to thank you both for the awesome job on Fabrication. I understand the concept of pipes and all but it was just too complicated to implement with several modules. Then I stumbled upon your framework and it helped a lot.

In regards to the problems of GC modules, maybe you haven't seen that already but there is a bug with Flash Player 9 : it doesn't really GC when it should do so upon dynamically loaded SWFs. Basically, the unload() method destroys the reference to the SWF but lets it run anyway. Without reference, it is very likely that the GC will miss sweeping the SWF.

The good news, well sort of, is that Adobe added a new method called unloadAndStop() that attempts to resolve (http://www.gskinner.com/blog/archives/2008/07/additional_info.html) some of the problems described by Grant Skinner (http://www.gskinner.com/blog/archives/2008/04/failure_to_unlo.html). It is only available with Flash Player 10.

This problem may end up being a huge one for my project as I'm building a mid-sized Flash web site and I thought I'd break it into several swfs, one for each section. Well now I'm wondering if I should revert back to single core...What a pain.

I hope it helped and wasn't totally out of line. :D


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on November 05, 2008, 05:50:33
A lot of the problems concerning the loading/unloading of SWF's in FP9 have to do with Time line based code, which our project has none of (it's basically pure AS3 just a document class). In the case of Fabrication, as long as all the references are cleared from both the parent and loaded swf it should get GC'd. Of course you also need to ensure any other code in the swf gets cleared. One thing that can catch people up is that a loaded swf's STAGE property is actually the parent containers stage (there's only one stage in flash, regardless of the depth of loaded swf's) and adding listeners to stage can cause issues for GC.

They have done a great job in fix this and other issues related to unloading swf's in FP10. The only problem is that Flash 10 won't be out for some time yet and most developers won't be able to target Flash 10 until a reasonable adoption level is reached. Typically for our company it's one year AFTER the release of a new Player. I know, it sounds excessive but our apps, and clients, require that everyone be able to access them without having to upgrade or be diverted in any way. Our media player alone is displayed on over 30,000 websites and receives millions of hits a day... and it's still FP6 compatible :( Convincing them to let me move to 9 for our new media player was hard enough, I'll never get them to allow moving to FP10 right away.

I've read most of Grant's posts concerning GC issues. I'm glad adobe listen to him and made changes, I just wish they would have implemented those changes in 9 instead of putting them in 10.


Title: Re: Fabrication 0.4 released
Post by: Anty on November 05, 2008, 06:58:10
My thoughts exactly, though I do not have a player delivered to thousands of websites. :p

There is a solution that is likely to work (but it's still random) : you wait till your module is supposedly clear of any reference and then force a GC upon the application. Found on Simon Bailey's blog (http://www.nutrixinteractive.com/blog/?p=136).

I read on the blog of Skinner that "You can load content SWFs from a subdomain. This will place it into a security sandbox implicitly". Though I wonder if it could affect communication between the app and the modules...


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on November 05, 2008, 10:07:50
Hey Anty,

While I agree that the player 9 does not have means to gc. However as Jason used in his example, doing 2 local variable LocalConnection's back to back seems to force the player to do an immediate gc. Jason was doing it in his example and without Fabrication it shows the drop. Google chrome shows this quite clearly.

So I wouldn't give up on the multi-modular approach just yet. ;-) Solid garbage collection is a hugely important feature for Fabrication moving forward. Like I mentioned earlier nearly every class cleans up after itself. The gc issue is almost fixed, look out for a new release soon. And I am working on modifications to the simple_routing example to show that it actually does work!

Jason,

Regarding the debugger are you using it against the source version or the swc? With the source version I haven't seen this issue.

peace,
darshan


Title: Re: Fabrication 0.4 released
Post by: puremvc on November 06, 2008, 05:33:26
Hey folks, definitelry check Simon's blog. http://newtriks.com

He and I worked together (well he's the one that actually got exausted, I just provided moral and technical support :)

Anyway, he has a good MultiCore GC demo.

@jasonmac, the deal on your debugger and inspection of vars is you need to go to the little 'down arrow menu' on the right hand side of your variables view, and do Flex->Show inaccessible member variables

-=Cliff>


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on November 06, 2008, 05:57:35

@jasonmac, the deal on your debugger and inspection of vars is you need to go to the little 'down arrow menu' on the right hand side of your variables view, and do Flex->Show inaccessible member variables

-=Cliff>

Ah, thanks Cliff... that did the trick. I'm still getting used to Flex builder.


Title: Re: Fabrication 0.4 released
Post by: Anty on November 06, 2008, 08:07:23
You talking about something Simon hasn't posted yet Cliff ?

I've got another question : if there's a FlexModule, why isn't there a FlashModule ? I bet I missed something but I don't want to have to subclass anything related to Flex since my front end is AS3 only. Should I create a FlashModule class inspired by the FlexModule ? Any idea ?


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on November 06, 2008, 08:59:38
Anty,

FlashModule is not needed when using flash. The FlashApplication is your entry point throughout. FlexModule is a flex specific fabrication because Flex makes a distinction between Applications and Modules. In the flash/pure as3 world there is no such distinction. A swf is a swf is a swf. ;-)

Checkout the hello_flash_with_module demo[1]. The navigation is a module loaded with a plain loader and extends FlashApplication.

peace,
darshan

[1] : http://fabrication.googlecode.com/svn/examples/hello_flash_with_module/


Title: Re: Fabrication 0.4 released
Post by: Anty on November 07, 2008, 11:25:29
Thanks Darshan, that's quite logical and simple indeed.


Title: Re: Fabrication 0.4 released
Post by: Jason MacDonald on November 10, 2008, 08:56:00
Just checking in to see how things are going. Any luck on the unloading?


Title: Re: Fabrication 0.4 released
Post by: Darshan Sawardekar on November 11, 2008, 11:41:38
Hey Jason,

I have fixed the garbage collection issues. You need to grab 0.5 sources to get the fixes. Regarding your example, I have emailed you a modified version of your file with the fixes. The file is too big to post here and my blog's upload limit is only 2mb...

peace,
darshan