Announcement Announcement Module
Collapse
No announcement yet.
FlexXMLApplicationContext.dispose() disposes too much? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • FlexXMLApplicationContext.dispose() disposes too much?

    Hi list,

    I have some problems using the dispose() method of the FlexXMLApplicationContext.

    My scenario is:
    I have a master-context with global services. If I load a module, the module has it's own module-context and the master-context is set as parent. So I the global services are available in the module.
    Before I unload the module I call the dispose() method so the module can be garbage-collected after unloading. After that the next module can be loaded.

    This works fine BUT I can't use services from the master-context in my master application after calling the dispose() method.

    Example:
    My master application opens a popUp which contains a presentationModel which uses the demoService (is a global service). Opening the popUp runs well.
    I load a module in which has an own module-context, the master-context is merged in and I can use the demoService. This runs well.
    I load another module which means I unload the loaded module and call the dispatch() method.
    After calling the dispatch() method the demoService is no more available in the popUp.
    If I reload the module using the demoService the demo data is shown.

    Is there any solution my usecase works? Maybe I'm able to provide the complete demo application.

    Regards,
    Christoph

  • #2
    demo

    Hey Christoph,

    this indeed sounds like unwanted behavior. Browsing through the sources I can't immediately tell where this could be a bug, so if you could indeed post a demo app that showcases the behavior I'll probably be able to trace the problem and provide a fix.

    thanks a lot for bringing this one up!

    cheers,

    Roland

    Comment


    • #3
      Hi Roland,

      thanks for your reply.

      You can find a running demo application in http://www.flexguse.de/moduleUnloader.
      After loading, please press the "open PopUp" button. A popUp with a filled datagrid comes up.
      Load one of the first three modules. Now you can click the "open PopUp" button again and the datagrid is still filled.
      After that unload the module (dispose() method is called). If you again use the "open PopUp" button, the datagrid is empty.

      The sourcecode for the demo application is provided in https://svn.origo.ethz.ch/flex-playg...moduleUnloader (should be plublic).

      It is a standard multi-project maven project, "mvn install" and "mvn flexmojos:flexbuilder" in the root folder should do the job.

      There is some issue with embedding module context configuration using
      Code:
      [Bindable]
      [Embed(source="/injected-module-context.xml", mimeType="application/octet-stream")]
      private var myContextConfig:Class;
      using flexmojos (and Flashbuilder -> project -> export release build), so if you run "mvn package" the result is not working as expected.
      (If you know a solution for this, please help

      Maybe the dispose() problem is caused by my implementation or it is a bug in SpringActionscript.

      Regards,
      Christoph

      Comment


      • #4
        bug indeed

        Hey Christoph,

        well, this turned out to be a Spring Actionscript bug indeed. When disposing a FlexXMLApplicationContext with an assigned module the stage processors belonging to the application wide context were disposed as well.
        Turned out to be a slight oversight in the inheritance chain of the dispose() methods.
        Good catch! Thank you for taking the time to post your demo app, this made things very easy for me to debug!

        Fix is available in the trunk.

        cheers,

        Roland

        Comment


        • #5
          Hi Roland,

          thank you for your quick help!

          I checked out the trunk, ran
          Code:
          mvn clean install
          in the root folder (as suggested in the readme.txt) and got a Buil Error:
          Code:
          [WARNING] Unit test org.springextensions.actionscript.cairngorm.control.CairngormFrontControllerTest failed.
          [INFO] ------------------------------------------------------------------------
          [INFO] Tests run: 36, Failures: 1, Errors: 0, Time Elapsed: 0 sec
          [INFO] ------------------------------------------------------------------------
          [ERROR] BUILD ERROR
          [INFO] ------------------------------------------------------------------------
          [INFO] Some tests fail
          [INFO] ------------------------------------------------------------------------
          But the demo application worked.

          Unfortunately my real life application is more complex than the demo application was and in my real life application there is still a bug with dispose() and autowire.

          I decided to update the demo application (same URL, same SVN) so you can see yourself. The effect I have in my real life application is now in the demo application.

          How to reproduce the unexpected behaviour
          • run the application
          • choose one of the module containers
          • click "load new module" button
          • select one of the first three modules
          • click the "unload" button
          • click "load new module" again
          • see empty list

          If you choos the other Module Container and try to load a module, the list is filled again until a module is unloaded.
          I expect the list to be always filled.

          Is this behaviour again a bug in SAS or do I use SAS in a way it is not made for?

          Regards,
          Christoph

          Comment


          • #6
            Hi Roland,

            I found the problem in my code. To be able to load any UIComponent I set
            Code:
            FlexStageProcessorRegistry.getInstance().modulePolicy=ModulePolicy.AUTOWIRE;
            to
            Code:
            FlexStageProcessorRegistry.getInstance().modulePolicy=ModulePolicy.IGNORE;
            before loading a module. Somehow the property was not set back to AUTOWIRE properly, so the popUp was not autowired.

            I updated the SVN sourcecode and the demo application.

            Regards,
            Christoph

            Comment


            • #7
              Hey Christoph,

              really glad you got everything working! The default for Spring Actionscript is indeed ModulePolicy.AUTOWIRE, maybe I should add some extra emphasis on this in the documentation.

              cheers,

              Roland

              Comment


              • #8
                Hi Roland,

                I'm glad, too, having the thing running

                I enhanced my ModuleLoader a little bit, so there is no problem loading several modules at one time. A SASModuleLoaderRegistry handles that.
                Every time a module is loaded, the modulePolicy is set to IGNORE and the loader registers itself in the loaderRegistry.
                If the module is loaded and the spring context is injected, the loader unregisters itself from the loaderRegistry.
                If the loader is the last one and no else loader is loading, the modulePolicy is reset to the original value which is in most cases AUTOWIRE.

                Maybe this is useful to someone.

                Regards,
                Christoph

                Comment


                • #9
                  Hi Roland,

                  yes, it's me again and yes, I still have problems with my application

                  Yesterday I added a SASModuleLoaderRegistry that prevented my ModuleLoader from setting the ModulePolicy to AUTOWIRED too early. That works if you load modules one by one in a not too fast sequence.

                  Then I modified my example so modules are loaded initially and I got lots of trouble.
                  I solved some problems by enhancing the LoaderRegistry so the modules are loaded one after another. Now I'm able to load two modules initially without any error message.

                  You can see the demo application again in http://www.http://flexguse.de/moduleUnloader/. Click on the left side on "Twin Module Container" and see the result.

                  BUT if I load the SingleContainer after the twin module container and choos a module, I get "Can't find an autowired candidate:" error messages. If I ignore the exception, the module is loaded correctly.
                  You can reproduce this behaviour by clicking on "Single Module Container" -> "load new module" -> "Module with Injection"

                  At the moment I'm totally lost. For me it seems I have some timing problems and I'm not listening for the correct Events. But I have no more Idea where to look and what to do. I'm desperate because the module loading is the main concept of my real life application.

                  Could you give me a helping hand and have a look at my code? The sources are updated in the SVN.

                  Thank you in advance and have a nice weekend,
                  Christoph

                  Comment


                  • #10
                    hmmmm

                    Hey Christoph,

                    for some reason my local webserver is bugging out on me at the moment so I couldn't verify this. But, from looking at your code I'm not sure why you're changing the modulePolicy back and forth between AUTOWIRE and IGNORE.
                    I think there might be a misunderstanding about this setting. Setting the module policy to AUTOWIRE means that the *main* applicationContext, so the one that *doesn't* have an ownerModule property assigned to it, will not try to autowire any module or its children that are added to the stage. Instead, should this module be assigned to its own applicationContext, that particular context will autowire the module.
                    So, setting the ModulePolicy.IGNORE on the FlexStageProcessorRegistry needs only to be done once, right before you create your main application context for example. So, like this:

                    Code:
                    private function creationCompleteHandler(event:FlexEvent):void {
                    	FlexStageProcessorRegistry.getInstance().modulePolicy = ModulePolicy.IGNORE;
                    	_appContext.addConfigLocation("application-context.xml");
                    	_appContext.addEventListener(Event.COMPLETE, handleComplete);
                    	_appContext.load();
                    }
                    And after that remove the modulePolicy assignments from your SASModuleLoaderRegistry.
                    That *should* end your problems, but like I said, I haven't been able to verify.

                    I'll try and update the documentation and API docs to more clearly explain the inner workings of the module policy.

                    let me know how you fare,

                    cheers,

                    Roland

                    Comment


                    • #11
                      Looks like I'm running in the same little problems Christoph is encountering, so I'll add my thoughts (for what they are worth).

                      When you set ModulePolicy.IGNORE, everything will work fine in modules that load their own context and define their own AutowiringStageProcessor. You can perfectly autowire objects from both the application and module's contexts.

                      In a module that only needs objects from the application's context and doesn't define its own module context, you will not be able to autowire because the application's AutowiringStageProcessor is ignoring modules. To make this work you have to define a context for the module that only contains an AutowiringStageProcessor and load that.

                      Nothing wrong here, just a bit hard to get your head around when you're just starting with modules. An extra ModulePolicy might help, but I don't have a patch ready

                      Comment


                      • #12
                        Hi Roland,

                        thanks for your help! I did what you suggested and changed the autowiring policy to ignore for the main application. After that it started to work, I only had to fix some bugs in my SASModuleLoader and the UnloadableSASModule.

                        But finally it worked. I updated my demo application in the SVN and on my webserver.

                        @Glenn: in my implementation of ModuleLoader / Module the module always has a own context. If no context is defined by the developer, a default empty context is created.

                        In general I'm still not sure if I really understood what ModulePolicy.IGNORE and ModulePolicy.AUTOWIRE really means and I would agree Glenn that it is not intuitive to use modules in combination with SpringActionscript.
                        But I have no good idea how to teach a StageProcessor which object has to be autowired and which not.

                        I wish you a merry Christmas and a happy new year!
                        Christoph

                        Comment


                        • #13
                          Hey guys,

                          indeed the module policies need some work apparently. I'm gonna have to think hard about this one though.
                          Maybe the flexStageProcessorRegistry first needs to check if a context has been registered for a specific module, and if so, let the module's context go about its business. If there is no context registered it should just try to wire it, if the specified module is in a separate application domain it'll just fail silently.

                          I'll try and come up with a better solution, any help or suggestions are always appreciated.

                          cheers,

                          Roland

                          Comment

                          Working...
                          X