Announcement Announcement Module
No announcement yet.
Prevent Stage autowiring on Modules Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Prevent Stage autowiring on Modules

    Is there a way I can prevent the autowiring of stage components beyond a certain scope? I have a huge application that loads a ton of Modules and many of the classes within the modules are not compiled in the main application, saving filesize.

    When I use this with a FlexXMLApplicationContext, the context does a great job of autowiring things on the stage in my main application, but starts throwing errors whenever I load a module, since it is trying to autowire components which do not have a definition in the main ApplicationDomain. What can I do to work around this?

  • #2
    I found a workaround, it's not the best, but it works.

    By forcing the ModuleLoader to load class definitions into the main ApplicationDomain (<mx:ModuleLoader applicationDomain="flash.system.ApplicationDomain. currentDomain"/>), I was able to bypass the class-not-found errors. This seems like a good bet. Yes, all of the class definitions get loaded into the main ApplicationDomain, but I still don't have to compile those classes in.


    • #3
      this is a bug

      Hey there,

      this is quite obviously a bug, your workaround is indeed a valid one but I can imagine there is plenty of situations where its undesirable to load a module into the same application domain.
      Please file a bug in the issue tracker, that way someone will be assigned to look into the problem:

      thanks a lot,



      • #4
        Alright, it's been posted there.

        This would be a non-issue for me, as I can load everything into my main ApplicationDomain. However, as I'm quickly finding out, this springs a huge (massive, potentially limitless) memory leak, as Module classes are stacked when loaded into memory. It only takes a few steps to get FP memory usage up to 200+ mb.

        There's a way to autowire the stage without running into this error. The important thing is to use each stage child's loaderInfo to access their ApplicationDomains, eg:

        //rather than doing this
        //do this
        Type.forClass(stageItemClass, stageItem.loaderContext.applicationDomain);
        Unfortunately, this would mean a few changes in the as3commons-reflect package as well as in Spring Actionscript internally.


        • #5
          tough one

          Hey there,

          Thanks for your suggestions, seeing the memory leaks that loading modules into the same application domain yields I guess its important to resolve this issue a.s.a.p.
          I've been experimenting a little with loading modules and stagewiring them. The ClassUtils in as3commmons lang actually give you the opportunity to pass an applicationdomain when retrieving a Class instance for an objectdefinition.
          So, what I basically do in the stagewiring is this:

          var appDomain:ApplicationDomain  = (object is DisplayObject) ? (object as DisplayObject).loaderInfo.applicationDomain : null;
          var cls:Class = ClassUtils.forInstance(object,appDomain);
          Too bad this still came up with an error, then I dropped Spring Actionscript alltogether, just loaded a module into a test application and ran this code in the Module instance:

          ('this' is the Module instance)
          var appDomain:ApplicationDomain  = this.loaderInfo.applicationDomain;
          var className:String = getQualifiedClassName(this);
          var b:Boolean = appDomain.hasDefinition(className);
          Guess what, b == false!

          I'm rather stumped to be honest...

          Any suggestions are more than welcome.




          • #6
            Well, we've got two options here. Find a way to make stage autowiring work in separate ApplicationDomains or prevent Module autowiring altogether.

            Here's an interesting test you could run:
            var module:Module = moduleLoader.child as Module;
            var currentAppDomain:ApplicationDomain = flash.system.ApplicationDomain.currentDomain;
            var moduleAppDomain:ApplicationDomain = module.loaderContext.applicationDomain;
            trace("same application domain? " + (currentAppDomain == moduleAppDomain));
            trace("identical application domain? " + (currentAppDomain === moduleAppDomain));
            If you get a chance to run something like that, let me know. I'm curious as to what's going on here. I'm also curious as to how ApplicationDomains work.

            I know they 'physically' form a hierarchy, with the system (eg: flash.*) classes in the uppermost domain, but do subdomains inherit definitions from parent domains? I would assume so, but who knows?

            If they don't inherit, then we'll have a lot of weird crap to deal with. Especially since Modules typically use a link report to avoid double-compiling class definitions already in the parent SWF. We'd basically have to join multiple application domains and check all of them if they own the class definition.

            Like I've said before, the easiest way to handle this would be to just prevent Spring Actionscript from crawling into Modules or anything under a separate ApplicationDomain:

            if (newItem.loaderContext.applicationDomain != ApplicationDomain.currentDomain) {
               // don't autowire!!!!!
            But of course a real fix would be awesome too!


            • #7

              Well, from what I understand from the documentation a sub-applicationdomain can always access the class definitions of the parent domain.

              gleaned this from:

              If the parent domain want to access class information from a subdomain (so a module for example that is NOT loaded into the current domain) it can do so via the applicationDomain.hasDefinition() and applicationDomain.getDefinition() methods.

              That's why I don't understand why my module test comes up with 'false', unless the applicationdomain of the LOADER is not the same as the application domain of the loaded CONTENT (the module).

              This is going to be an interesting journey, I'm sure I really hope to get this working, not being able to autowire modules would be kind of a shame... A workaround for it would be to create an extra applicationcontext in every module that gets loaded and have them take care of their own wiring. But this could get messy quite quickly, so I hope to get it working the 'normal' way.

              Thanks a lot for your input so far.

              Last edited by 666shooter; Jul 24th, 2009, 04:18 AM. Reason: added doc link


              • #8

                Oh, and I ran your code inside my module, this is the trace I got:

                same application domain? false
                identical application domain? false
                At least that's what I expected it to be, doesn't solve my conundrum yet, but at least this is expected behavior...
                I'll dig deeper later, for now, I have to get back to my regular work, I'll keep you posted.
                If you find out anything else on your own, I'd love to hear it naturally.




                • #9
                  Try using the actual Module instance's loaderContext (or its applicationDomain property ) and see if that yields different results. Something weird is going on here...


                  • #10

                    I'd love to do that, there's two problems with your suggestion.

                    One, Module doesn't have a loaderContext property, only a loaderInfo property. (loaderContext only exists on the Loader class actually).

                    Two, Module doesn't have an applicationDomain property.

                    So, I guess we're back to square one. I'm convinced I'm doing something very fundamentally wrong here... I guess its Friday hehe

                    I'll experiment some more when I find the time, for now, I gotta cook dinner




                    • #11
                      You should still be able to get the module's applicationdomain through "myModule.loaderInfo.applicationDomain".

                      Is there any simple way for us to just disable autowiring of Modules? I think this would be the simplest fix, avoiding all of the nasty memory problems I'm dealing with right now. Alternatively, we could just fail silently with an error trace to the console, without throwing the error.

                      I know that this problem is fixable in a no-compromise manner, I just lack the time to dedicate thought to the solution


                      • #12
                        that still doesn't work

                        You should still be able to get the module's applicationdomain through "myModule.loaderInfo.applicationDomain".

                        well, that is exactly my frustration, if I do this inside the module:
                        var clsName:String = getQualifiedClassName(this);
                        var b:Boolean = this.loaderInfo.applicationDomain.hasDefinition(clsName);
                        Its comes up with 'false'. That's why I'm still stumped...

                        But for now I've changed the FlexStageDefaultObjectSelector slightly so it rejects stage components for which it is unable to retrieve type information. That'll at least take care of the exceptions for now, until we can come up with a better solution.

                        Changes have been committed to the trunk.




                        • #13
                          Thanks for committing that change to the trunk, it'll stifle our problems for now at least. When I get some time to look into this crazy mess, believe me, I will. Our current application depends on it, so when we come to a point where we can spend some time on it, I'll do my best to investigate it and figure this out.

                          Till then, thanks so much for at least giving us a fix that will prevent the error from being thrown!


                          • #14

                            Glad to help, let me know if you stumble upon any more trouble, we'll try and get things working a.s.a.p.


                            • #15
                              Thanks a lot, we're all really grateful for your hard work on this project.