How to prevent injections into module (Loader with new ApplicationDomain) that is added to the shell's contextView?
In my case I load modules (SWFs, built with RL) into shell (built with RL) via Loader and new ApplicationDomain. I'm adding those modules to the shell's contextView, therefore shell's injector tries to inject something into them and fails (those classes have same names in terms of package, but actually they should be separated because of different application domains):
Exception fault: TypeError: Error #1034: Type Coercion failed: cannot convert mvcs::SignalBus @1a665ae1 to mvcs.SignalBus.
at org.swiftsuspenders.injectionpoints::PropertyInjectionPoint/applyInjection()[/Users/tschneidereit/dev/swiftsuspenders/swiftsuspenders/src/org/swiftsuspenders/injectionpoints/PropertyInjectionPoint.as:46]
at org.swiftsuspenders::Injector/injectInto()[/Users/tschneidereit/dev/swiftsuspenders/swiftsuspenders/src/org/swiftsuspenders/Injector.as:120]
at org.robotlegs.base::ViewMap/injectInto()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/ViewMap.as:200]
at org.robotlegs.base::ViewMap/onViewAdded()[/Development/Projects/Robotlegs/robotlegs-framework/src/org/robotlegs/base/ViewMap.as:191]
at flash.display::DisplayObjectContainer/addChild()
....etc
As soon as I add module not to the contextView, but somewhere higher like stage — it works just fine. So the question is it possible to add modules to contextView but prevent injections into them? Or this will only work if I change all class names definition to unique (like "moduleName.mvcs.SignalBus", etc...)? Thanks!
Comments are currently closed for this discussion. You can start a new one.
Support Staff 2 Posted by Stray on 25 May, 2011 08:10 AM
Hi Pavel,
did you get this figured out?
One option would be to use the old-fashioned original version of the modular utilities - these don't use the child injectors, and don't inject from the shell to the loaded modules.
Stray
3 Posted by pavel.fljot on 25 May, 2011 10:11 AM
Nope, haven't figured out. I don't think modular utilities is something for me since I just load external SWFs in a new ApplicationDomain (it's not modules in RL concept, but just external RL-powered SWFs that should not be affected by shell's injector). So it's seems more like SwiftSuspenders question again.
Support Staff 4 Posted by Stray on 25 May, 2011 10:39 AM
Hi Pavel,
if you add something to this contextView then the mediatorMap within that contextView will respond, and use the local injector, with the original appDomain, to try to fulfil the injections.
Is there some way you can separate the contextViews? for example:
By container I just mean a sprite - doesn't have to be flex.
Stray
5 Posted by pavel.fljot on 25 May, 2011 10:44 AM
Yea, that's how I do now (as mentioned in the last paragraph of the original question), but doesn't seems like a perfect way.
Support Staff 6 Posted by Stray on 25 May, 2011 10:49 AM
Hi Pavel,
well, you do have a multi-context app - and there are 3 solutions for that - one is the new modular utils, another is the old modular utils, and the 3rd is to keep your contexts totally separate - you've gone for the 3rd.
I'll see if Till has any more thoughts about it, but I don't see a problem with what you're doing. The concept of 'contextView' means 'the view used for this context' - not just 'main view'. So it does have implications - which you've got a good work around for.
Stray
7 Posted by pavel.fljot on 25 May, 2011 11:45 AM
Stray, I still think it's an issue. Because I could really need to put my external swf somewhere into shell's context view, but still preserve it as a completely separate piece (not having any injections into it). So some (SOME!) sort of injector.preventFromInjection(view:DisplayObject) could make the trick... So unlike most "modular" topics I want to get non-modular behavior when loading the module =)
Or maybe I miss something regarding modular utilities?
8 Posted by Stray on 25 May, 2011 12:00 PM
I'm hoping Till will wade in here - he's much more aware of these kinds of intricacies than I am.
The issue I think though is that you must have the same view class mapped in your shell as in your child views, yes? In the mediator?
So - you have something like this in both the parent context and the loaded-swf context:
mediatorMap.mapView(SomeView, SomeViewMediator); (or view map equivalent)
The mediatorMap waits for ADDED_TO_STAGE events on the contextView - so if your child views are inside your contextView, and you add something to the stage, ALL context views that this element is inside of will try to create a mediator for it - because all those contextViews will fire the ADDED_TO_STAGE event. Perhaps? Unless I'm wrong about the way this event works in this scenario.
If it is that the event is being fired in every parent in the chain, I'm not really sure there is anything that can be done about that in terms of the robotlegs side - there's no way for it interrogate the whole container (parent) chain to check for nested contextViews, because each mediatorMap is ignorant of the others, and a contextView is only an instance of DisplayObjectContainer, it has no special properties in terms of extending a class etc.
So - how could any one contextView/mediatorMap know that it's not really supposed to mediate/map this class? Injection will only happen on mediators, commands and items marked for injection - so the example you cite (with the swf not having injections) wouldn't be a problem.
Did I miss something? If I've got it wrong that you've got a view of the same type mapped to the mediatorMap in both your shell and your loaded swf then I could be way off here!
Stray
Support Staff 9 Posted by Till Schneidereit on 25 May, 2011 01:09 PM
Nope, you didn't miss anything: Your description of what's going on
and why is spot on.
The only thing I might add is that not only is this behavior hard to
change from a technical point of view, it's also desirable in some
cases.
I've been thinking about how to optimize the case of nested
contextViews for quite some time now and one idea I've had is to let
mediatorMaps try to combine their ADDED_TO_STAGE/ REMOVED_FROM_STAGE
listeners in the outermost contextView. That would allow for the
creation of more complex behavior such as the innermost mediatorMap
declaring a view as "handled" and thus stopping outer contexts from
trying to map the view, too. I'm not sure if the advantages are worth
the increased complexity, though.
10 Posted by pavel.fljot on 28 May, 2011 11:14 PM
OK, here's proof of concept that actually worked as desired:
ShellContext extends Context/SignalContext:
ShellViewMap extends ViewMap:
Not the most optimal & flexible code, but just to make an example. This allows me to add external RL module (loaded swf into new ApplicationDomain) into main contextView WITHOUT injecting anything into it, so two RL contexts becomes completely independent... well looks like =) haven't tested in all the possible ways. Now. Questions is — is it worth to add something into ModularUtilities (which is the last and popular one?) to implement this workflow?
Support Staff 11 Posted by Till Schneidereit on 29 May, 2011 02:46 PM
At least in the implementation you give, this is bound to be
excessively slow: The loop in isValidView will be invoked for each and
every DisplayObject hitting the display list anywhere below the
contextView. What you could do instead is to at least check if the
ShellViewMap itself is even interested in the DisplayObject being
added. If that is not the case, then you don't need to invoke
isValidView at all.
Other than that: Sure, this approach works. I'd be hesitant to add it
to the ModularUtilities, though, as it is very specialized and only
works for exactly you use-case, while disabling other use-cases such
as views that should be handled by both the outer as well as the inner
context.
Adding flexible support for several nested contexts-scenarios is high
on my list of priorities for RL 2, though.
Stray closed this discussion on 10 Jun, 2011 03:54 PM.