6 Replies Latest reply on Oct 19, 2011 10:32 AM by csa

    problem with dependency injection of tree like dependency structure

    faxe13

      Hello,

       

      I think I have found a problem when injecting dependencies into classes that themselfs get other objects injected which leads to a tree like structure. Here is the example I am working with:

       

      EntryPoint Class

          - EntryPoint depends on @ApplicationScoped ClassA

              - ClassA depends on @ApplicationScoped ClassB

          - EntryPoint depends on @ApplicationScoped ClassC

              - ClassC depends on @ApplicationScoped ClassD

       

      About 2 times out of 10 the application starts and works without problems. The other 8 times I get an exception during startup that one of the classes ClassA or ClassC cannot find one of the required dependencies.

       

      org.jboss.errai.ioc.rebind.ioc.InjectionFailure: unable to resolve type injector for: ClassB; at injection point: ClassA.(ClassB Display, org.jboss.errai.bus.client.framework.MessageBus MessageBus)    

        at org.jboss.errai.ioc.rebind.ioc.InjectionContext.getQualifiedInjector(InjectionContext.java:78)

                at org.jboss.errai.ioc.rebind.ioc.InjectUtil.resolveInjectionDependencies(InjectUtil.java:361)

                at org.jboss.errai.ioc.rebind.ioc.InjectUtil$1.generateConstructor(InjectUtil.java:95)

                at org.jboss.errai.ioc.rebind.ioc.TypeInjector.getType(TypeInjector.java:74)

                at org.jboss.errai.enterprise.rebind.JSR299IOCExtensionConfigurator$2.handle(JSR299IOCExtensionConfigurator.java:105)

                at org.jboss.errai.enterprise.rebind.JSR299IOCExtensionConfigurator$2.handle(JSR299IOCExtensionConfigurator.java:97)

                at org.jboss.errai.ioc.rebind.IOCProcessorFactory$1.process(IOCProcessorFactory.java:90)

                at org.jboss.errai.ioc.rebind.IOCProcessorFactory$ProcessingEntry.processAllDelegates(IOCProcessorFactory.java:215)

                at org.jboss.errai.ioc.rebind.IOCProcessorFactory.processAll(IOCProcessorFactory.java:172)

                at org.jboss.errai.ioc.rebind.ioc.bootstrapper.IOCBootstrapGenerator.generateExtensions(IOCBootstrapGenerator.java:159)

                at org.jboss.errai.ioc.rebind.ioc.bootstrapper.IOCBootstrapGenerator.generate(IOCBootstrapGenerator.java:145)

                at org.jboss.errai.ioc.rebind.IOCGenerator.generateIOCBootstrapClass(IOCGenerator.java:134)

                at org.jboss.errai.ioc.rebind.IOCGenerator.generate(IOCGenerator.java:102)

                at com.google.gwt.core.ext.GeneratorExtWrapper.generate(GeneratorExtWrapper.java:48)...

       

      After debugging the IOCBootstrapGenerator I found out that the MetaDataScanner contains the classes that have an @ApplicationScoped annotation in no special order. Also the MetaDataScanner.getTypesAnnotatedWith() method returns a Set of classes that is not ordered at all. The order is different every time I start the application. Some times it is correct and some times it is not. From that I saw the framework does not consider that ClassB and ClassD should be processed before ClassA and ClassC so that at the time when they will be processed (in IOCBootstrapGenerator.processAll()) the InjectionContext already contains the injectors for ClassB and ClassD.

       

      Is this something that should be improved in the framework or should I work around this issue e.g. by using my custom @Produces methods.

       

      Gert

        • 1. Re: problem with dependency injection of tree like dependency structure
          csa

          Yes, the classes returned by the MetaDataScanner have no guaranteed ordering. However, that should not be a problem. I have created a unit test for this injection scenario which works reliably for me (independent of how the classes are ordered). Can you take a look at it and compare it to your classes so we can narrow down the problem? Or alternatively, post some details about the classes you work with? The test classes can be found here.

          • 2. Re: problem with dependency injection of tree like dependency structure
            faxe13

            Hi Christian,

             

            Now I think I know why the problem only occurs in my app. In my case I am using constructor injection in ClassA to inject ClassB and also to inject ClassD into ClassC. My use case is even more complex because all the types are parameterized types inheriting from a superclass but I think that is not relevant for this issue. So the constructor looks like this:

             

            @Inject

            public ClassA(ClassB display) {

                                super(display);

            }

             

            I debugged a little bit deeper into the code and found the following things:

             

            The IOCProcessorFactory.processAll() is the place where all deletages of the @ApplicationScoped beans get executed. The order in which the beans are processed is random obtained from the MetaDataScanner. During execution of the delegates I reach one handler for @ApplicationScoped beans (JSR299IOCExtensionConfigurator line 105: i.getType(injectionContext, null); ). Inside this method the ConstructionStrategy is build and executed.In the case of constructor injection it is a different strategy than in the case of using the default constructor and injecting the references afterwards. Thats why only constructor injection causes the error.

             

            In the class InjectUtils.resolveInjectionDependencies() that is executed from the created ConstructionStrategy the InjectionContext.getQualifiedInjector() method is called that looks into the existing injectors map (line 66). In the case of the wrong ordering in processing the @ApplicationScoped beans the injectors map will not contain the required dependencies and lead to the exception of my first post.

             

            By the way I am using the 1.3.0-SNAPSHOT release from the maven repo.

             

            Cheers, Gert

            • 3. Re: problem with dependency injection of tree like dependency structure
              csa

              Using constructor injection, I can reproduce the problem now. I will look into this.

              • 4. Re: problem with dependency injection of tree like dependency structure
                csa

                OK this should be fixed now. You can download the latest errai-ioc-1.3.1-SNAPSHOT.jar from here. Can you give it a try?

                 

                The tests have been changed to cover both field and constructor injection. As for the ordering issue, our current algorithm to process injections doesn't rely on an ordered set of classes.

                • 5. Re: problem with dependency injection of tree like dependency structure
                  faxe13

                  This fix solved my problem. No InjectionFailures any more. Thank you very much.

                  • 6. Re: problem with dependency injection of tree like dependency structure
                    csa

                    Thanks for reporting and confirming.