Announcement Announcement Module
Collapse
No announcement yet.
Flex modules and application context loading Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #31
    hmmmm....

    Ok i'll keep it short...

    I do understand the ide issue and you don't have to convince me that is there. I recognized that a few times already. What i'm trying to say is that there is a way more fundamental problem. So:
    • did you try my app and the steps that i provided to proof that the main problem lies in reflection / applicationDomain lookup?
    • do you recognise that in your app the custom class is never autowired to a view model? And testing that in your app breaks it also in flex builder 3?
    • that my app exactly does that testing for you?

    I really try to help here, but somehow get the feeling you somehow don't want it. If so please let me know and i'll stop bothering you. Otherwise please answer the 3 questions above. Because if you don't want to run my test it is useless and a waste of my time.

    Really don't want to sound too harsh but we both are busy people right?

    cheers, and really no offense,

    Arnoud

    Comment


    • #32
      yez

      Hey Arnoud,

      I was already in agreement with you that its a reflection problem, and yes, your sample app demonstrates this.
      So, for your first question, yes, I agree.
      Second question, in my app I can't test autowiring a custom class yet because I stumbled upon a new problem, which will probably lead me to the core of the problem. Which is indeed a reflection/appdomain issue.

      So, I thought we were already in agreement about the issue, I was just still completely stumped why the exact same source code crashes in flashbuilder and works in flexbuilder 3. I still don't have an answer for this.

      And I do appreciate your help very much, sorry if I don't sound like it always I just had the feeling that we were talking on different wavelengths or something.

      What I have to figure out now is if the problem still lies in SAS or that its deeper and is a bug in as3commons-reflect, my quest continues this evening...

      Comment


      • #33
        Ok Cool!

        Ok great!

        i think we are on the same wavelength

        just let me know if i can do anything to help further. This thing intrigues me. Especially because i'm buiding my own mvcs on top of SAS that relies heavy on the inner workings of applicationDomains.

        cheers,

        Arnoud

        Comment


        • #34
          cool

          I'm going to try and create a sample app this evening that can demonstrate a little better in which scenario's the errors start throwing, if I have something ready I'll be sure to send it to you.

          cheers,

          Roland

          Comment


          • #35
            my sincere apologies

            Hey Arnoud,

            this is where I bow my head in shame and admit that I was wrong, it turned out to be a reflection issue indeed. I really still do not understand why my original project worked flawlessly and the others didn't.
            But I managed to recreate the error in flasbuilder and came to the conclusion that it was as3commons-reflect where the problem lay. The ClassUtils methods allow for an ApplicationDomain instance to be passed in, but the Type methods don't, and that's exactly where things screwed up.
            The exact reason how it screwed up is still very weird, I don't fully understand what and why it went wrong there. But after I added an optional ApplicationDomain argument to the necessary Type methods the problem went away.
            So now there is one central method in as3commons that is used to retrieve a Class definition, never is there a call directly to getDefinitionByName() but always through the ApplicationDomain.getDefinition(). Granted that the application domains are created in the right way and have the proper parents, this should work properly now.

            I tried it out in Flashbuilder both with the 4.0 SDK and 3.4 SDK, both gave me no errors...

            But, of course I now don't trust my own test results for a second any more, so if you could find the time to do your own test then I'd greatly appreciate this.

            You will need to checkout the latest trunk of as3commons-reflect and the latest trunk of Spring Actionscript. I've also slightly changed the multi-modules sample app and added an autowired property in one of the modules that will be wired with a custom class that is only compiled into the specified module, thus only available in that application domain.

            So, get all the latest trunks and give it another whirl, I really, really hope we finally have this solved.

            Again, sorry for all the confusion and seeming hostility, it wasn't meant in that way, I hope you'll feel like helping out more in the future. Spring Actionscript needs nitpickers to pick up on these issues, so please stay with us

            cheers,

            Roland

            Comment


            • #36
              Sure, i'll give it a try!

              Hi Roland,

              I'm glad that you found the issue! And no apology needed, really. You guys are always very responsive and determined to solve issues. Sometimes it just takes a bit longer to nail the problem, especially if it's a bit of an exotic one. And on the other hand i could have be more clearer if i found the specific error myself instead of pointing to a problem direction. So that's that

              I'm going to play with your test project and let you know my findings. I'm seriously going to try to break it! haha

              have a good weekend,

              Arnoud

              Comment


              • #37
                close....

                Hi Roland,

                You are very close to completely solve the issue. Great!

                But... The only problem i have is if i use [Autowired] (or byType)
                In that case it doesn't work.

                Still a minor (i hope) issue with reflection.

                Code:
                Sat Oct 31 01:58:24 GMT+0100 2009 WARN - org.as3commons.reflect.Type - The class with the name 'classes::ModuleClass' could not be found in the application domain '[object ApplicationDomain]'
                TypeError: Error #1009: Cannot access a property or method of a null object reference.
                	at org.springextensions.actionscript.ioc.autowire::DefaultAutowireProcessor/autoWireFieldByType()[/Users/arnoudbos/Desktop/development/flex frameworks svn/spring-actionscript/trunk/spring-actionscript-core/src/main/actionscript/org/springextensions/actionscript/ioc/autowire/DefaultAutowireProcessor.as:276]
                	at org.springextensions.actionscript.ioc.autowire::DefaultFlexAutowireProcessor/autoWireField()[/Users/arnoudbos/Desktop/development/flex frameworks svn/spring-actionscript/trunk/spring-actionscript-core/src/main/actionscript/org/springextensions/actionscript/ioc/autowire/DefaultFlexAutowireProcessor.as:74]
                	at org.springextensions.actionscript.ioc.autowire::DefaultAutowireProcessor/autoWire()[/Users/arnoudbos/Desktop/development/flex frameworks svn/spring-actionscript/trunk/spring-actionscript-core/src/main/actionscript/org/springextensions/actionscript/ioc/autowire/DefaultAutowireProcessor.as:163]
                	at org.springextensions.actionscript.ioc.factory.support::AbstractObjectFactory/wire()[/Users/arnoudbos/Desktop/development/flex frameworks svn/spring-actionscript/trunk/spring-actionscript-core/src/main/actionscript/org/springextensions/actionscript/ioc/factory/support/AbstractObjectFactory.as:401]
                	at org.springextensions.actionscript.stage::DefaultAutowiringStageProcessor/process()[/Users/arnoudbos/Desktop/development/flex frameworks svn/spring-actionscript/trunk/spring-actionscript-core/src/main/actionscript/org/springextensions/actionscript/stage/DefaultAutowiringStageProcessor.as:151]
                	at org.springextensions.actionscript.stage::FlexStageProcessorRegistry/processStageComponentWithRelevantProcessors()[/Users/arnoudbos/Desktop/development/flex frameworks svn/spring-actionscript/trunk/spring-actionscript-core/src/main/actionscript/org/springextensions/actionscript/stage/FlexStageProcessorRegistry.as:294]
                	at org.springextensions.actionscript.stage::FlexStageProcessorRegistry/processUIComponent()[/Users/arnoudbos/Desktop/development/flex frameworks svn/spring-actionscript/trunk/spring-actionscript-core/src/main/actionscript/org/springextensions/actionscript/stage/FlexStageProcessorRegistry.as:261]
                	at org.springextensions.actionscript.stage::FlexStageProcessorRegistry/processStage()[/Users/arnoudbos/Desktop/development/flex frameworks svn/spring-actionscript/trunk/spring-actionscript-core/src/main/actionscript/org/springextensions/actionscript/stage/FlexStageProcessorRegistry.as:447]
                	at org.springextensions.actionscript.context.support::FlexXMLApplicationContext/completeHandler()[/Users/arnoudbos/Desktop/development/flex frameworks svn/spring-actionscript/trunk/spring-actionscript-core/src/main/actionscript/org/springextensions/actionscript/context/support/FlexXMLApplicationContext.as:278]
                	at flash.events::EventDispatcher/dispatchEventFunction()
                	at flash.events::EventDispatcher/dispatchEvent()

                Code:
                /**
                		 * Tries to retrieve an autowire candidate based on the type of the specified field, and when found
                		 * injects the candidate into the specified field.
                		 * @param object The object being autowired
                		 * @param field The field that will be injected.
                		 * @param metadata The autowiring metadata
                		 * @param objectName The name of the object in the objectFactory
                		 */
                		protected function autoWireFieldByType(object:Object, field:Field, metadata:MetaData, objectName:String):void {
                			var candidateName:String = findAutowireCandidateName(field.type.clazz);

                field.type = null in which case field.type.clazz gives a null pointer.

                Hope i'm not driving you mad...

                cheers,

                Arnoud

                Comment


                • #38
                  no, not mad yet

                  Hey Arnoud,

                  nopes, you're most certainly not driving me mad, the bugs in my code might drive me mad, but you pointing them out are a great help
                  Its indeed a bug in as3commons-reflect again, the AbstractMember class has a type property, in the getter of this property there's this code:

                  Code:
                  public function get type():Type {
                      return Type.forName(_type);
                  }
                  No direct reference to the type property is held because this lead to a circular reference, hence a memory leak, in the past.
                  Now what this call needs is the extra applicationDomain argument, all I have to figure out now is where to store this, and how to store this.
                  I'm afraid that if I just add an applicationdomain member to the type property this will again lead to memory leaks. This is because all Type instances are cached.
                  So, should somebody unload a module it would probably stay in memory since the reflected Types are keeping a reference to the application domain.
                  I wish actionscript had soft references... I'll try and fake one with a dictionary with weak keys, I suppose.

                  So, I kind of know what the problem is right now, just mulling over the right solution I'll get back to you a.s.a.p.
                  If you have any suggestions I'd love to hear about them as well of course!

                  cheers,

                  Roland

                  Comment


                  • #39
                    Careful with the dictionaries....

                    Hi Roland,

                    probably you already know, but i see so many people doing it wrong.
                    If you want to use a dictionary to make a weak reference, make sure you make the applicationDomain the key and not the value.

                    ok:
                    Code:
                    var d:Dictionary = new Dictionary(true);
                    d[applicationDomain] = true;
                    not ok (will still leak memory) which i see way to often:
                    Code:
                    var d:Dictionary = new Dictionary(true);
                    d["domain"] = applicationDomain;
                    Maybe an open door...

                    I'm afraid that i don't have a good architectural idea for how to best incorporate the applicationdomain in the reflection libs. It's because i'm not deep enough into the framework source. I'm getting into it though, but i'm not close to the understanding of it as you guys have.

                    good luck with solving the bug. I'm really happy that this is being addressed cause it touches some of the the fundamentals of the system.

                    Arnoud

                    Comment


                    • #40
                      i think,hope,pray its fixed now

                      Hey Arnoud,

                      yea, I was aware of the weakKeys difference in usage, 'been there, done that' hehe. But it can't hurt that you repeat the matter here in the forum, I'm sure there's people reading here that weren't aware of it, so I'm sure you're enlightening people.

                      What I've done is I've added a small class called 'SoftReference' to the as3commons-lang library, which looks like this:
                      Code:
                      public class SoftReference {
                      	private var _dict:Dictionary;
                      
                      	public function SoftReference(value:Object=null) {
                      		super();
                      		if (value != null) {
                      			this.value = value;
                      		}
                      	}
                      
                      	public function get value():Object {
                      		if (_dict != null){
                      			for(var obj:Object in _dict){
                      				return obj;
                      			}
                      		}
                      		return null;
                      	}
                      	public function set value(value:Object):void {
                      		_dict = new Dictionary(true);
                      		_dict[value] = true;
                      	}
                      }
                      After that I've added an applicationDomain property to the Type class that uses this SoftReference class to hold its reference to the ApplicationDomain.

                      Then in the AbstractMember class I changed the code like this:

                      Code:
                      public function get type():Type {
                          return Type.forName(_type, declaringType.applicationDomain);
                      }
                      That way the member type will be looked up using the applicationdomain of the declaring type.

                      I changed the multi-module sample app so that in SASDemoModule1 the customClass property is autowired byType, this crashed at first, but after I added the above mentioned fixes it works like a charm.

                      So, as usual, hehe, I would kindly ask you to run some tests as well and confirm correct behavior (hopefully).

                      One issue remains still, I'd like to find a proper way of unit testing this behavior without having to load modules in my testproject.
                      Would you, or anyone else, know how to simulate this?
                      What would be needed is basically creating an applicationdomain on the fly and adding definitions to it, but as far as I know this is not possible.

                      any ideas?

                      cheers,

                      Roland

                      P.S. So, when trying out the new code make sure to update both as3commons and Spring Actionscript again.
                      Last edited by 666shooter; Oct 31st, 2009, 07:25 AM.

                      Comment


                      • #41
                        Whooptiewhoo!

                        Nice!

                        It all works now as far as i can see. I also like the abstraction into a class in lang of the SoftReference.

                        I am afraid that applicationDomains are read-only... So you'll have to load a module to test. But i understand you want a unit test and not an integration test. I was recently looking at mocking and unit testing in flex. The next stuff looks good:

                        http://bitbucket.org/loomis/mockito-flex/wiki/Home
                        http://www.compactcode.com/index.php...-flex-mocking/

                        I wonder if you can Mock an applicationDomain... On the other hand, why not? Anyway this doesn't look like a usual case and i personally would go for the integration test... Looks easier.

                        Have a good weekend and thank u very much!

                        Arnoud

                        Comment


                        • #42
                          phew, so its done...

                          Hey Arnoud,

                          you can't believe how relieved I am that things seem to be working now The multi-module/applicationdomain support was a very important feature to me and now that things seem to be running in order I am pretty damned excited Thanks a lot for your time, patience and understanding
                          I will look into the mocking solutions you posted, but I agree with you that the integration tests would probably be easier to implement.

                          cheers!

                          Roland

                          Comment


                          • #43
                            not entirely done.... but close!

                            Hi Roland,

                            I've been testing the module wiring intensively but there seems to be a few things not working entirely right, yet.
                            But i understand you didn't notice because it's a specific case:

                            There are 3 issues:
                            1. In some places the ClassUtils doesn't use application domain in for example the AbstractObjectFactory. This didn't give me direct issues but i think that in the AbstractObjectFactory always should use that second parameter when using ClassUtils.forInstance etc. For example:
                              Code:
                              // arnoud: added _applicationDomain
                              public function getClassForName(className:String):Class {
                              	return ClassUtils.forName(className, _applicationDomain);
                              }
                              	
                              // arnoud: added _applicationDomain
                              public function getClassForInstance(object:Object):Class {
                              	return ClassUtils.forInstance(object, _applicationDomain);
                              }
                            2. When autowiring singleton models into other objects also defined into application context i get null pointers
                            3. The autowiring of stage components does behave a bit unpredictable in some cases

                            I made a proof of concept (modification of your module example) in which the last 2 cases cases appear. See picture:

                            http://www.artim-interactive.nl/arno..._sas_error.png

                            explanation of the picture:
                            • the autowiring stage component in the empty box right under the application doesn't work (even without the null pointer)
                            • the null pointer speaks for itself. It only happens sometimes though. If you build the application sometimes it works, sometimes not. I think it's a timing issue. In my bigger application it happens all the time. If the application works for you reload the application a few times (fast) in you browser and the null pointer should show up. It happens in the wire method in which a Property instance of a context object has a type that is null. So property.type.clazz gives a null pointer exception. The funny thing is is that the rest of that property is correctly filled, it's just the type that is null. I have a test application (flash builder 4 project) on the next url for you to try out (it's the same of the picture above): http://www.artim-interactive.nl/arno...module_sas.fxp.
                              The issue occurs if:
                              • in the context objects are wired together
                              • the context wiring is byType
                              • the scope of the objects to wire together is singleton
                              • if the main application and the modules use a context. So if the the same module is loaded in an application and that application doesn't have an own context the problem doesn't seem to occur.

                            I hope this gives you enough detail about the problems!

                            I really hope you can give it another look. Although i'm getting pretty deep into the framework it's still a bit daunting and you probably know better what happens under the hood.

                            Another question completely off topic. Do you know how to compare 2 application domains? ApplicationDomain.currrentDomain == ApplicationDomain.currentDomain returns false
                            It's not that hi have to directly compare them but i need to identify them uniquely. I cannot find a way to do this. The don't have a unique id etc...

                            I alreaddy filed a bug but i cannot find an alternative solution in google, and i did search for a long time...

                            Cheers!

                            Arnoud, the demolisher
                            Last edited by arnoudb; Nov 15th, 2009, 04:31 PM. Reason: typo, cleaning up

                            Comment


                            • #44
                              hm, this is getting murky now...

                              Hey Arnoud,

                              thanks a million for doing these tests, too bad some more bugs have crept up
                              You're actually right that the two getClass* methods in AbstractObjectFactory need to pass their applicationDomain as well. These two methods are overridden in the FlexXMLObjectFactory where they do receieve an applicationDomain though, so I'm pretty confident that the problem lies somewhere else, I'm gonna try anyway of course, just to be certain.

                              You also point out that some null pointers only happen once in a while, this leads me to suspect the soft-reference to the applicationdomain in the Type class. I have no idea how this pointer can ever become null, but it *seems* like that is happening. Because this circumstance would lead exactly to the aforementioned problem where all of a sudden the type of a property becomes null.
                              Of course, this is all conjecture and I'm going to have to test this stuff myself. I'm pretty swamped in work right now, so I hope I'll have time for it this evening, I'll do my best.

                              As for your question about comparing instances, in actionscript if you want to compare two references its best to use the === operator. Which is a strict comparison. (The opposite is !== of course)
                              I'm pretty sure ApplicationDomain.currrentDomain === ApplicationDomain.currentDomain will yield 'true'.

                              Anyways, thanks for the demolishing And I'll get back here with my finding as soon as I find the time for them.

                              cheers!

                              Roland

                              Comment


                              • #45
                                hmmmm....

                                Hi Roland,

                                I was playing some more with the module sytem with the debugger.
                                I cannot find the problem, but i did a extended search on ClassUtils.forName with less than 2 parameters. Enter the next line in the extended search of flex builder in the projects of asCommons and of sptingactionscript (not entirely right but filters out much redundant stuff):

                                ClassUtils.forName\([^\,\)]*\)

                                and make sure you search on regular expressions.

                                I found several potential problematic calls that don't pass in n applicationDomain
                                The problem may be in one of those, but not sure. But after seeing these calls without applicationDomain i do think the whole reflection system needs another critical look.

                                cheers!

                                Arnoud
                                Last edited by arnoudb; Nov 19th, 2009, 04:06 PM.

                                Comment

                                Working...
                                X