Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: [1]
Print
Author Topic: loading modules dynamically  (Read 12256 times)
ricardokirkner
Jr. Member
**
Posts: 18


View Profile Email
« on: June 03, 2008, 12:25:33 »

Hi,

I am writing some code to load modules dynamically. Each module is implemented as a standalone application (meaning it has it's own Facade, Model, View and Controller). I am using (in my shell application)  a ModuleProxy, which loads and unloads modules. While they are loaded, the proxy keeps a reference in an ArrayCollection.

The strange thing is, I can load a module perfectly the first time, then unload it without any problems, and if I want to load it again afterwards, I get an error in the module's main mxml (which has the Module tag), saying that it "cannot access a property or method of a null object reference". This happens in the creationComplete event handler which looks like

<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml"
    verticalGap="0"
    horizontalGap="0"
    creationComplete="facade.startup(this);">
    <mx:Script>
        <![CDATA[
        import my.name.space.ApplicationFacade;
        public static const NAME:String = 'MyModule';
        protected var facade:ApplicationFacade = ApplicationFacade.getInstance(NAME);
        ]]>
    </mx:Script>
...
</mx:Module>

so that means, the null object reference is the facade object, right?

Now, what does this exactly mean? Why is it null the second time I try to load the module, but not the first time?
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #1 on: June 03, 2008, 04:57:49 »

I would have to see more of your code to know. How are you doing the loading and unloading?

-=Cliff>
Logged
ricardokirkner
Jr. Member
**
Posts: 18


View Profile Email
« Reply #2 on: June 04, 2008, 06:53:09 »

ok Cliff,

the methods I am using belong to a ModuleProxy class.

data is an ArrayCollection.

-------------------------------------------------------------------------------------

        public function loadModule(module:ModuleVO):void
        {
            var index:Number = getLoaderIndex(module);
            if (index == -1)
            {
                var loader:ModuleLoader = new ModuleLoader();
                loader.url = module.url;
                loader.addEventListener(ModuleEvent.READY, onModuleLoaded);
                data.addItem(loader);
                loader.loadModule();
            }
        }

        private function getLoaderIndex(module:ModuleVO):Number
        {
            // find loader
            var index:Number = -1;
            var tmp:ModuleLoader;
            for (var i:Number = 0 ; i < loaders.length; i++)
            {
                tmp = loaders.getItemAt(i) as ModuleLoader;
                if (tmp.url == module.url)
                {
                    index = i;
                    break;
                }
            }

            // return index found
            return index;
        }

        public function unloadModule(module:ModuleVO):void
        {
            // find loader
            var index:Number = getLoaderIndex(module);
            // loader was found
            if (index != -1)
            {
                var loader:ModuleLoader = loaders.removeItemAt(index) as ModuleLoader;
                loader.addEventListener(ModuleEvent.UNLOAD, onModuleUnloaded);
                loader.addEventListener(ModuleEvent.ERROR, onModuleError);
                loader.unloadModule();
            }
        }

        private function onModuleLoaded(event:ModuleEvent):void
        {
            if (event.module)
            {
                sendNotification(ApplicationFacade.MODULE_LOADED);
            }
        }

        private function onModuleUnloaded(event:ModuleEvent):void
        {
            if (event.module)
            {
                sendNotification(ApplicationFacade.MODULE_UNLOADED);
            }
        }

        public function get loaders():ArrayCollection
        {
            return data as ArrayCollection;
        }
    }

--------------------------------------------------------------------------

the ModuleVO object, basically has an url, a name and a description.

I hope this code is enough for you to understand how it works. If it's not, then I can send you the whole source code as an attachment.

the items are getting correctly added and removed from the ArrayCollection.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #3 on: June 04, 2008, 07:13:13 »

Have you tried setting a breakpoint on the creationComplete and step return the first time and step into the second in order to see where its failing?
Logged
ricardokirkner
Jr. Member
**
Posts: 18


View Profile Email
« Reply #4 on: June 04, 2008, 07:16:28 »

no, I haven't, because I am not using FlexDeveloper, but just vim. Either way, that shouldn't work (I think), since according to the error message, the problem is that the facade object didn't get created at all, the second time. I will try to put a trace or Alert message in order to debug this.
Logged
ghess
Courseware Beta
Jr. Member
***
Posts: 12


View Profile Email
« Reply #5 on: June 04, 2008, 05:30:09 »

I had this error too. I modeled the multicore demo app and altered it to work with modules.

When I debugged it I found that the method I was using to generate the multiton key was doing:

return MODULE_URI+this.id;

In my case this.id was null. I updated my impl to:

return MODULE_URI+this;

And the issue was resolved.

It seemed that 'this' was providing a unique Id. To be honest not sure of the impact with multicore, but as far as a unique id I seem to have one.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #6 on: June 04, 2008, 10:19:30 »

Every module instance is a unique Core and therefore needs it's own set of MVCF actors. This requires a unique Multiton Key, which is what you discovered.

-=Cliff>
Logged
c64
Newbie
*
Posts: 3


View Profile Email
« Reply #7 on: June 10, 2008, 02:00:03 »

Also you can try loading module in ApplicationDomain.currentDomain (loaded in child domain by default causing the conflict).
Logged
ricardokirkner
Jr. Member
**
Posts: 18


View Profile Email
« Reply #8 on: June 23, 2008, 12:35:25 »

just for the record..

the issue here was not calling facade.removeCore() before unloading the module (which generated the issues when re-loading the module).

anyway, all the answers where helpful and insightful, so thank you all

this is really a community with a great feeling about it . keep on!! :-)

ricardo
Logged
Pages: [1]
Print