eventDispatcher return null an a Actor Extends class

karmafr's Avatar

karmafr

18 May, 2012 02:17 PM

Hi,
First of all congrtulations for all this work and well done support section :)

I've looked all the discussions (i think) here to try to solve my problem but I didn't figure it out.
I've this error TypeError: Error #1009: Cannot access a property or method of a null object reference. when I try to compile my project I and still don't know where I'm wrong. I just know where it is the pb.
Note that in the class below I only override the function dispatch the trace the value of eventDispatcher
Is that normal that it is nul ?

Here how I do my injections :
public class MainContext extends Context

{
    public function MainContext(contextView:DisplayObjectContainer=null, autoStartup:Boolean=true)
    {
        super(contextView, autoStartup);
    }

    override public function startup():void
    {
        //Services
        injector.mapSingletonOf(IOrxService, LoaderOrxService);

        //Models
        ...

        // Controllers
        commandMap.mapEvent(OrxEvent.STARTUP, StartupCommand, OrxEvent);            
        ...

        //Views
        ...
    }
}

and here is my Extended class
public class XMLLoaderService extends Actor

{
    private var _xml:XML;

    public function load(url:String):void
    {
        var urlLoader:URLLoader = new URLLoader();
        urlLoader.addEventListener(Event.COMPLETE, completeHandler);
        urlLoader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);

        urlLoader.load(new URLRequest(url));
    }

    public function getXMLList(id:String, listName:String="file"):XMLList
    {
        var list:XMLList = null;
        if(_xml.files.(@id= id).length()>0) {
            if(_xml.files.(@id == id)[listName]) _xml.files.(@id == id)[listName];
        }
        return list;
    }

    protected function completeHandler(event:Event):void
    {
        _xml = new XML(URLLoader(event.target).data);
        trace("XMLLoaderService completeHandler - "+"event:"+event);
        dispatch(new LoaderServiceEvent(LoaderServiceEvent.LOADER_SERVICE_COMPLETED));
    }

    protected function ioErrorHandler(event:IOErrorEvent):void
    {
        dispatch(new LoaderServiceEvent(LoaderServiceEvent.ERROR_LOADER_SERVICE));
    }

    override protected function dispatch(event:Event):Boolean
    {
        trace("XMLLoaderService dispatch - "+"event:"+event);
        trace("XMLLoaderService dispatch - "+"event.type:"+event.type);
        trace("XMLLoaderService eventDispatcher - "+"eventDispatcher:"+eventDispatcher);
        if(eventDispatcher && eventDispatcher.hasEventListener(event.type)) 
            return eventDispatcher.dispatchEvent(event);
        return false;
    }   
}

I'll be greatful if anyone could help me a little

n.b: sorry for my custom English, my native language is French

  1. Support Staff 1 Posted by Ondina D.F. on 18 May, 2012 03:29 PM

    Ondina D.F.'s Avatar

    Hey karmafr,

    Let’s start at the beginning of possible causes:

    • Compiler arguments when linking against the rl source:
    https://github.com/robotlegs/robotlegs-framework/wiki/Common-Proble...

    • Make sure the context doesn’t get garbage collected:
    https://github.com/robotlegs/robotlegs-framework/wiki/Common-Proble...

    • Make sure to override the clone() method of your custom event class. Events can not be re-dispatched without doing so – even non-bubbling events. It is considered best practice when creating custom events to override clone().

    • Where are you mapping XMLLoaderService ? In your code snippet there is only :

    injector.mapSingletonOf(IOrxService, LoaderOrxService);

    After mapping XMLLoaderService, are you sure it is the same instance of XMLLoaderService that you are trying to call?
    Can you show us the mapping for that XMLLoaderService and the way you are calling the service ( from a command?)

    n.b: sorry for my custom English, my native language is French

    Don’t worry about it:)

    Ondina

  2. 2 Posted by Paul Robertson on 18 May, 2012 03:40 PM

    Paul Robertson's Avatar

    Are you mapping the XMLLoaderService class as a singleton, or in some other
    way instantiating it via Robotlegs?

    If you're just creating it yourself (e.g. by calling "new
    XMLLoaderService()") then Robotlegs won't inject the IEventDispatcher.

    The reason I wondered is because your snippet from your context shows this
    mapping:
    injector.mapSingletonOf(IOrxService, LoaderOrxService);

    However, it doesn't show any mapping for the XMLLoaderService class.

    Paul

  3. 3 Posted by karmafr on 21 May, 2012 08:06 AM

    karmafr's Avatar

    Hi Ondina,
    Many thanks to answer so quickly, infortnunatly I couldn't check all your request until today because I didn't have access to them on w-e.
    So I did the n°1 point (I forgot it)
    Point 2 is OK, I do the instatation of the context into a application (see Main.mxml)
    Point 3 is also OK (see LoaderServiceEvent class)
    Point 4 and @Paul I modified my Context class (see below) but the problem is still there, maybe I didn't well understood the mapping concept ?

    // Application Main.mxml:

    <?xml version="1.0" encoding="utf-8"?>
    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"

               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               xmlns:views="aw.orx.views*" 
               creationComplete="creationCompleteHandler(event)">
    
    <fx:Script>
        <![CDATA[
            import mx.controls.Alert;
            import mx.events.FlexEvent;
    
            private var _context:MainContext;
    
            public function showError(message:String):void
            {
                Alert.show(message, "Erreur");
            }
    
            protected function creationCompleteHandler(event:FlexEvent):void
            {
                _context = new MainContext( this );
            }   
    
        ]]>
    </fx:Script>
    

    </s:Application>

    // LoaderServiceEvent class:

    package aw.orx.models.events
    {

    import flash.events.Event;
    
    public class LoaderServiceEvent extends Event
    {
        public static const LOADER_SERVICE_COMPLETED:String = "LoaderServiceCompleted";
    
        public static const ERROR_LOADER_SERVICE:String = "errorLoaderService";
    
        public function LoaderServiceEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
        {
            super(type, bubbles, cancelable);
        }
    
        public override function clone():Event
        { 
            return new LoaderServiceEvent( type );
        } 
    }
    

    }

    // InitializeCommand class:

    package aw.orx.controllers.commands
    {

    import aw.orx.controllers.events.LoadWorkAreaEvent;
    import aw.orx.models.services.ILoaderService;
    import aw.orx.models.services.IOrxService;
    import aw.orx.models.services.LoaderService;
    import aw.orx.models.services.XMLLoaderService;
    import aw.orx.models.vo.XmlUrlVO;
    
    import org.robotlegs.mvcs.Command;
    
    public class InitializeCommand extends Command
    {
        [Inject]
        public var xmlLoaderService:ILoaderService;
    
        [Inject]
        public var _loaderService:IOrxService;
    
        private var _menusUrls:XMLList;
        private var _sectionsUrls:XMLList;
    
        public function get menusUrls():XMLList
        {
            return _menusUrls;
        }
    
        public function get sectionsUrls():XMLList
        {
            return _sectionsUrls;
        }
    
        override public function execute() : void
        {
            if(_loaderService is LoaderService) {
                collectUrls(_loaderService as LoaderService, "menuUrls");
            }
    
            //run();
        }
    
        public function collectUrls(loaderService:LoaderService, id:String):void
        {
            //_menusUrls = _loader.getXMLList("menus");
            //_sectionsUrls = _loader.getXMLList("sections");
    
            var list:XMLList = xmlLoaderService.getXMLList("menus") as XMLList;
            var listArr:Vector.<XmlUrlVO>;
            for each (var item:Object in list) 
            { 
                listArr.push(item as XmlUrlVO);
            }
            loaderService.loaderObject.menusUrls = listArr;
        }
    
        private function collectDatas():void
        {
    
        }
    
        protected function run():void
        {
            dispatch(new LoadWorkAreaEvent(LoadWorkAreaEvent.LOAD_WORK_AREA));
        }
    }
    

    }

    // MainContext class:

    package
    {

    import aw.orx.controllers.commands.*;
    import aw.orx.controllers.events.*;
    import aw.orx.models.*;
    import aw.orx.models.services.*;
    ...
    
    import flash.display.DisplayObjectContainer;
    
    import org.robotlegs.mvcs.Context;
    
    public class MainContext extends Context
    {
        public function MainContext(contextView:DisplayObjectContainer=null, autoStartup:Boolean=true)
        {
            super(contextView, autoStartup);
        }
    
        override public function startup():void
        {
            //Services
            injector.mapSingletonOf(IOrxService, LoaderOrxService);
            //var myClassInstance:XMLLoaderService = new XMLLoaderService();
            //injector.mapValue(XMLLoaderService, myClassInstance);
            injector.mapSingletonOf(ILoaderService, XMLLoaderService);
    
            //Models
            ...
    
            // Controllers
            ...
    
            //Views
            mediatorMap.mapView(Main, MainMediator);
            mediatorMap.mapView(EditionView, EditionMediator);
    
            ...
        }
    }
    

    }

  4. Support Staff 4 Posted by Ondina D.F. on 21 May, 2012 08:42 AM

    Ondina D.F.'s Avatar

    Hi :)
    I need to see the service classes as well.

    Could you attach the entire application (as zip or fxp) ? I’ll take a look at it.

  5. 5 Posted by karmafr on 21 May, 2012 08:50 AM

    karmafr's Avatar

    OK, I've done few modification on InitializeCommand class

    Thanks

  6. Support Staff 6 Posted by Ondina D.F. on 21 May, 2012 08:55 AM

    Ondina D.F.'s Avatar

    Taking a look at your app....I'll be back with answer, hopefully;)

  7. Support Staff 7 Posted by Ondina D.F. on 21 May, 2012 09:13 AM

    Ondina D.F.'s Avatar

    I found the culprits:) Be right back.

  8. 8 Posted by karmafr on 21 May, 2012 09:23 AM

    karmafr's Avatar

    Ok thx

  9. Support Staff 9 Posted by Ondina D.F. on 21 May, 2012 09:35 AM

    Ondina D.F.'s Avatar

    -You forgot the „implements“ statement: public class XMLLoaderService extends Actor
    has to be:
    public class XMLLoaderService extends Actor implements ILoaderService

    -Your ILoaderService doesn’t contain all the methods your are implementing in XMLLoaderService and, vice versa, XMLLoaderService doesn’t implement all ILoaderService’s methods.

    -StartupCommand:

    --You had a little typo: the loader var has to be public for the injection to work.

    --You have to inject the interface, since your mapping was like this:

    injector.mapSingletonOf(ILoaderService, XMLLoaderService);

    --You were creating a new instance of XMLLoaderService in your constructor. So, even if you would have mapped the service like so: injector.mapSingleton(XMLLoaderService);

    the loader inside of the execute() wouldn’t be the same instance as the one injected. Don’t do anything in your commands’ constructor.

    public class StartupCommand extends Command
    {

    [Inject] public var loader:ILoaderService;

    //private var loader:XMLLoaderService;<=bad

    public function StartupCommand()
    {

    //loader = new XMLLoaderService;<=bad }

    override public function execute() : void
    {

    loader.load("assets/xml/datasUrls.xml");
    

    }

    }

    -LoaderOrxService

    Don’t do anything inside the class’ constructor!

    I would need more time to investigate all the classes. But for now, you should try to make the changes mentioned above, and in case you encounter other problems just let us know.

    Ondina

  10. 10 Posted by karmafr on 21 May, 2012 10:18 AM

    karmafr's Avatar

    OK many thanks
    That what I thought, I figure that I still have some problems to manage the architecture...
    By the way I discovered RL By reading this article :
    http://blog.jeromefath.com/2011/07/11/conception-et-developpement-d...
    (It's in French, but I've joined the project in attach)

    And try to do something similar, but my main dificulty is to adapt his services classes that are made to work with Zend in classes that work with Xml files...
    I did this because I have not much time, but maybe I'll choose the wrong way and I'll better to do something more simple (without services)

    By the way, i've done the changes, and it fixe the main issue (eventDispather), I still have other, especially with the LoaderOrxService you mentionned. I think I doesn't accept my instructions in the constructor...
    I will try to fix that, thanks again for your time

  11. Support Staff 11 Posted by Ondina D.F. on 21 May, 2012 11:25 AM

    Ondina D.F.'s Avatar

    You’re welcome!
    I’m glad you made a few steps forward :)
    I’ll read the article and take a look at the app, thanks for the link.
    Unfortunately, I don’t have much time right now, because I have to finish some work before going on vacation in a few days. Your application is pretty complex, so, I can’t promise that I’ll be able to help you with your application step by step. I’m sure there will be others who will assist you, if need be.

    As for the LoaderOrxService, where are you calling it? I only see the mapping.
    What is loaderObject? You’re attaching event listeners to it or actually to functions that are implemented from the interface..? What do you want LoaderOrxService to do? Is it actually a service?
    InitializeCommand is kind of confusing ;) If xmlLoaderService and _loaderService are both services, then it’s not a good idea to call them both in there. One issue you might run into, is due to the asynchronous nature of services.

    But, as you said, maybe it’s better to find a solution without services first, and then, later, when you’ll have more time, to refactor the application.

  12. Ondina D.F. closed this discussion on 16 Jul, 2012 08:25 AM.

Comments are currently closed for this discussion. You can start a new one.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac