5 Replies Latest reply on Aug 7, 2013 5:30 PM by Jonathan Fuerth

    @Produces with 2 lists causes error

    Anton Hughes Master

      Hi

       

      I am using the recommendation from Jonanthan - see https://community.jboss.org/thread/231190?tstart=0

       

      And this works fine if I am only using @Produces once for a list.

       

      I have two classes:

       

      SymbolProducer:

      has @Produces List<Symbol> symbols

      IndicatorProducer:

      has @Produces List<Indicator> indicators

       

      I am only able to run the application with one of these - either one - but not both. I have both, I get the following error - is this a bug, or am I doing something wrong?

       

              00:10:15.514 [ERROR] Error generating extensions 

      org.jboss.errai.ioc.rebind.ioc.exception.UnsatisfiedDependenciesException:  @> app.client.local.ModifyStrategy
      - field org.jboss.errai.codegen.meta.MetaField:app.client.local.ModifyStrategy.indicatorList could not be satisfied for type: java.util.List
        Message: ambiguous injection type (multiple injectors resolved): java.util.List  @Any  @Default :
           matching> org.jboss.errai.ioc.rebind.ioc.injector.ProducerInjector:java.util.List  @Any  @Default
           matching> org.jboss.errai.ioc.rebind.ioc.injector.ProducerInjector:java.util.List  @Any  @Default
        Note: configure an alternative to take precedence or remove all but one matching bean.
        • 1. Re: @Produces with 2 lists causes error
          Jonathan Fuerth Master

          The problem is that the producers both produce the same raw type (java.util.List) and this is confusing Errai's IOC generator. This might be a bug; I'm not sure how it's supposed to work in the presence of generic type arguments.

           

          Whether or not this is a bug, here are two different workarounds you can try:

           

          1. Subclass ArrayList for each of the list types, for example public class SymbolList extends ArrayList<Symbol>. Modify your producers and injection points to use the new types.

           

          2. Use CDI qualifiers to differentiate between the two lists. So your producer methods/fields would be @Produces @Symbol List<Symbol> symbols and @Produces @Indicator List<Indicator> symbols. The injection points would also use the qualifiers: @Inject @Symbol List<Symbol> symbols.

           

          -Jonathan

          1 of 1 people found this helpful
          • 2. Re: @Produces with 2 lists causes error
            Anton Hughes Master

            Hi Jonathan, I tried #2, but that also did not work. I still get the same error.

            • 3. Re: @Produces with 2 lists causes error
              Jonathan Fuerth Master

              That's surprising. We have a mountain of test cases for qualified injection points. Are you sure you qualified all of the injection points as well as all producers? You'll still get the "ambiguous injection type" error if even one injection point lacks a qualifier.

               

              -Jonathan

              • 4. Re: @Produces with 2 lists causes error
                Anton Hughes Master

                Hi Jonathan

                 

                Yes, am sure.

                 

                 

                Howerver, I was able to fix this issue by following your first suggestion.

                 

                1. Subclass ArrayList for each of the list types, for example public class SymbolList extends ArrayList<Symbol>. Modify your producers and injection points to use the new types.

                • 5. Re: @Produces with 2 lists causes error
                  Jonathan Fuerth Master

                  I think suggestion 1 was the better one anyway, because it allows the Java compiler to ensure type safety at your injection points. With option 2, there is no compile time safety against a mistake like @Inject @Symbol List<Indicator> indicators. This would happily inject the list of Symbol objects into the Indicator list injection point. You'll get mysterious errors when you try to use the items in the list.

                   

                  However, I'm still concerned that option 2 didn't work for you. I've just added the following to an Errai project, and GWT compilation completed without error:

                   

                  Two List producers:

                   

                  package org.jboss.errai.cdiwb.client.local;
                  
                  import java.util.ArrayList;
                  import java.util.List;
                  
                  import javax.enterprise.context.ApplicationScoped;
                  import javax.enterprise.inject.Produces;
                  
                  import org.jboss.errai.cdiwb.shared.Qual1;
                  import org.jboss.errai.cdiwb.shared.Qual2;
                  
                  @ApplicationScoped
                  public class ListProducers {
                  
                    @Produces @Qual1
                    private List<String> stringList = new ArrayList<String>();
                  
                    @Produces @Qual2
                    private List<Integer> intList = new ArrayList<Integer>();
                  }
                  

                   

                  Two List injection points:

                   

                  package org.jboss.errai.cdiwb.client.local;
                  
                  import java.util.List;
                  
                  import javax.enterprise.context.Dependent;
                  import javax.inject.Inject;
                  
                  import org.jboss.errai.cdiwb.shared.Qual1;
                  import org.jboss.errai.cdiwb.shared.Qual2;
                  
                  @Dependent
                  public class ListUsers {
                  
                    @Inject @Qual1 List<String> stringList;
                    @Inject @Qual2 List<Integer> intList;
                  
                  }
                  

                   

                  And finally the two qualifiers:

                   

                  package org.jboss.errai.cdiwb.shared;
                  
                  import java.lang.annotation.Documented;
                  import java.lang.annotation.Retention;
                  import java.lang.annotation.RetentionPolicy;
                  
                  import javax.inject.Qualifier;
                  
                  @Qualifier
                  @Retention(RetentionPolicy.RUNTIME)
                  @Documented
                  public @interface Qual1 {
                  
                  }
                  

                   

                   

                  package org.jboss.errai.cdiwb.shared;
                  
                  import java.lang.annotation.Documented;
                  import java.lang.annotation.Retention;
                  import java.lang.annotation.RetentionPolicy;
                    
                  import javax.inject.Qualifier;
                    
                  @Qualifier
                  @Retention(RetentionPolicy.RUNTIME)
                  @Documented
                  public @interface Qual2 {
                    
                  }
                  

                   

                  Is this structurally identical to what you did? Which version of Errai were you compiling against?

                   

                  -Jonathan