2 Replies Latest reply on Oct 13, 2011 7:41 AM by Gert Kropiunik

    Injection of parmeterized Types

    Gert Kropiunik Newbie

      Hello,

       

      I am currently playing with the IOC capabilities of errai-ioc. I am using the latest 1.3.0-SNAPSHOT in my project.

       

      When I try to inject my presenter class using @Inject everything works perfect a long as I don't use parmeterized types.

       

      Here is my example code and the class I want to inject as dependency to my application entry point:

      @ApplicationScoped

      public class LoginPresenter extends Presenter { ...


      When I refactor the app by adding a type parameter to the Presenter interface I get an exception during application startup.

      @ApplicationScoped

      public class LoginPresenter extends Presenter<LoginPresenter.Display> { ...

       

      Here is the exception stack trace:

      org.jboss.errai.ioc.rebind.ioc.InjectionFailure: could not resolve type for injection: at.apa.excelsa.web.client.login.LoginPresente

              at org.jboss.errai.ioc.rebind.ioc.InjectionContext.getInjector(InjectionContext.java:112)

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

              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)

              at com.google.gwt.core.ext.GeneratorExtWrapper.generateIncrementally(GeneratorExtWrapper.java:60)

              at com.google.gwt.dev.javac.StandardGeneratorContext.runGeneratorIncrementally(StandardGeneratorContext.java:681)

              at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:41)      

              at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:74)

              at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:285)

              at com.google.gwt.dev.shell.ShellModuleSpaceHost.rebind(ShellModuleSpaceHost.java:141)

              at com.google.gwt.dev.shell.ModuleSpace.rebind(ModuleSpace.java:585)              

              at com.google.gwt.dev.shell.ModuleSpace.rebindAndCreate(ModuleSpace.java:455)     

              at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:49)                 

              at com.google.gwt.core.client.GWT.create(GWT.java:98)                                   

              at org.jboss.errai.ioc.client.Container.onModuleLoad(Container.java:31)                 

              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)                          

              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)        

              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

              at java.lang.reflect.Method.invoke(Method.java:597)                                     

              at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:396)                    

              at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:193)

              at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:510)

              at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352)  

       


      I have tracked down the reason of this issue to the classes org.jboss.errai.ioc.rebind.ioc.InjectionContext and org.jboss.errai.ioc.rebind.ioc.codegen.meta.impl.AbstractMetaClass:

       

      The InjectionContext stores a map of injectors. This map contains a MetaClass instance for my LoginPresenter with all the expected details about the type and the parameterized type. But when the app tries to check if the injector for the LoginPresenter exists in the map (InjectionContext.getInjector(type)) it cannot find it. The reason is that the equals method on the AbstractMetaClass which is called to check if an injector exists is somehow broken for the case with type parameters.

      public boolean equals(Object o) {

          return o instanceof MetaClass && hashString().equals(MetaClass.class.getName()

                  + ":" + ((MetaClass) o).getFullyQualifiedName());

        }

       

      As you can see equals() compares the hashString() with a concatenated string that contains the full qualified class name but without the parameterized type. But the hashString() contains the information about the parameterized type.

        private String hashString() {

          if (hashString == null) {

            hashString = MetaClass.class.getName() + ":" + getFullyQualifiedName();

            if (getParameterizedType() != null) {

              hashString += getParameterizedType().toString();

            }

          }

          return hashString;

        }

       

      In my case the equals compares the following strings:

      org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaClass:my.test.client.login.LoginPresenter

      and

      org.jboss.errai.ioc.rebind.ioc.codegen.meta.MetaClass:my.test.client.login.LoginPresenter<my.test.client.login.LoginPresenter.Display>

      which is obviously not equal. In the case where I don't use the parameterized type the String are equal because getParameterizedType() is null in the hashString() method.

       

      Now to my question: Is this is a bug or intended behavior and injection won't work in that case.

      I hope the description was not too confusing.

       

      Cheers, Gert