title: CDI bean-type resolution issue when the bean class implements parameterized interfaces that also extend some parameterized interface
body: <p>Given I lack the vocabulary to explain the issue, I show it by means of an example that reproduces the failure and helps to find the cause:</p>
  
  <pre><code>public interface BaseType&lt;P&gt; {}
  public interface DerivedType&lt;T&gt; extends BaseType&lt;T&gt; {}
  
  public interface SomeType1 {}
  public interface SomeType2 {}
  
  @Dependent
  public static class BeanClass1 implements DerivedType&lt;SomeType1&gt; {}
  
  @Dependent
  public static class BeanClass2 implements DerivedType&lt;SomeType2&gt; {}
  
  @ApplicationScoped
  public static class Test implements Serializable {
  
      @Inject
      private BaseType&lt;SomeType1&gt; field; // if not commented throws following exception during deployment: org.jboss.weld.exceptions.DeploymentException: WELD-001409 Ambiguous dependencies for type [BaseType&lt;SomeType1&gt;] with qualifiers [@Default] at injection point [[field] @Inject private Test.field]. Possible dependencies [[Managed Bean [class BeanClass2] with qualifiers [@Any @Default], Managed Bean [class BeanClass1] with qualifiers [@Any @Default]]]
  
      @Inject
      private Instance&lt;BaseType&lt;SomeType1&gt;&gt; instance;
  
      @Inject
      private BeanManager bm;
  
      @PostConstruct
      private void postConstruct() {
          // This block outputs two bean classes and it should be only one:
          // beanClass: BeanClass1@11be5bab
          // beanClass: BeanClass2@764a72e9
          {
              Iterator&lt;BaseType&lt;SomeType1&gt;&gt; iterator = instance.iterator();
              while (iterator.hasNext()) {
                  System.out.println("beanClass: " + iterator.next().toString());
          }
      }
  
  
          // And this block outputs:
          //
          // bean: Managed Bean [class BeanClass1] with qualifiers [@Any @Default]
          // beanTypes:
          //  - class BeanClass1
          //  - DerivedType&lt;SomeType1&gt;
          //  - class java.lang.Object
          //  - BaseType&lt;T&gt;
          //
          // bean: Managed Bean [class BeanClass2] with qualifiers [@Any @Default]
          // beanTypes:
          //  - DerivedType&lt;SomeType2&gt;
          //  - class java.lang.Object
          //  - class BeanClass2
          //  - BaseType&lt;T&gt;
          {
              Set&lt;Bean&lt;?&gt;&gt; beans = bm.getBeans(new ParameterizedTypeImpl(BaseType.class, new Type[] { SomeType1.class }, null));
              for (Bean&lt;?&gt; bean : beans) {
                  System.out.println("\nbean: " + bean+"\nbeanTypes: ");
                  for (Type beanType : bean.getTypes()) {
                      System.out.println(" - " + beanType);
                  }
              }
  
              bm.resolve(beans); // if not commeted throws an AmbiguousResolutionException
          }
      }
  }
  </code></pre>
  
  <p>The second block shows the set of bean types of the bean classes <code>BeanClass1</code> and <code>BeanClass2</code>, according to <code>Weld</code>. There we found that the bean types set contains the type <code>BaseType&lt;T&gt;</code> instead of <code>BaseType&lt;SomeType1&gt;</code> or <code>BaseType&lt;SomeType2&gt;</code>.</p>
  
  <p>So, the bean type of <code>BeanClass2</code> corresponding to the indirect interface <code>BaseType&lt;P&gt;</code> that <code>Weld</code> remembers has the type variable <code>T</code> instead of the actual type parameter <code>SomeType2</code>.
  Therefore, and a according to the last point of <a href="http://docs.jboss.org/cdi/spec/1.0/html/injectionelresolution.html#assignableparameters" rel="nofollow">this specification</a>, <code>BeanClass2</code> is wrongly considered assignable to <code>BaseType&lt;SomeType1&gt;</code>.</p>
  
  <p>Is this the desired behavior or a bug? Is there a workaround? Was it fixed in a new <code>Weld</code> version.</p>
  
  <p>The test was executed on a JBoss AS 7.1.1 which uses maven artifact org.jboss.as:jboss-as-weld:7.1.1</p>
  
  <p>EDIT:
  I think the cause of this problem is not type erasure as the first answer suggest (it was deleted) but a bug in <code>Weld</code>. All the information required to generate the bean types is available during runtime.
  The bug is, I guess, when <code>Weld</code> generates the bean types of the bean class by means of reflection. The type variable resolution should be recursive and, apparently, it is not.</p>
  
  <p>I am sure that the information required to generate the bean types of indirect interfaces is available during runtime because I made and tested a method that accomplishes this using a library - I made some years ago for a memory efficient java serializer - that fortunately has a function that does exactly what we need: generate a/get the <code>Type</code> instance for each ancestor of a java class, resolving type variables recursively. I tryed to put the involved methods down here but I had formating issues when pasting the code; and the fact that the library is long and poorly documented gave me reasons to give up. </p>
  
  <p>To show, at least, the essence of how to resolve the type variables of indirect interfaces I wrote the following code. It works only for a specific class but can be generalized with some effort:</p>
  
  <pre><code>public static Set&lt;Type&gt; getActualInterfacesOfBeanClass1() {
      Set&lt;Type&gt; actualInterfaces = new HashSet&lt;&gt;();
  
      ParameterizedType directInterface = (ParameterizedType) BeanClass1.class.getGenericInterfaces()[0]; // = DerivedType&lt;SomeType1&gt;  ; assumes only one interface is extended
      actualInterfaces.add(directInterface);
  
      // because ParameterizedType doesn't have a method like Class.getGenericInterfaces(), we have to do it by hand
      Type indirectInterface; // = BaseType&lt;SomeType1&gt;
      {
          Class&lt;?&gt; directInterfaceRaw = (Class&lt;?&gt;) directInterface.getRawType(); // = DerivedType&lt;T&gt;
          Map&lt;String,Type&gt; resolutionMap = new HashMap&lt;&gt;(); // = { T -&gt; SomeType1 }
          for( int i=0; i&lt;directInterfaceRaw.getTypeParameters().length;++i) {
              resolutionMap.put(directInterfaceRaw.getTypeParameters()[i].getName(),directInterface.getActualTypeArguments()[i]);
          }
  
          ParameterizedType indirectInterfaceUnresolved = (ParameterizedType) directInterfaceRaw.getGenericInterfaces()[0]; // = BaseType&lt;T&gt; ;  assumes only one interface is extended
          ArrayList&lt;Type&gt; resolvedParameters = new ArrayList&lt;&gt;(); // = { SomeType1 }
          for(Type param : indirectInterfaceUnresolved.getActualTypeArguments()) {
              Type resolvedParam;
              if( param instanceof TypeVariable) {
                  resolvedParam = resolutionMap.get(((TypeVariable&lt;?&gt;)param).getName());
              } else {
                  resolvedParam = param;
              }
              resolvedParameters.add(resolvedParam);
          }
          indirectInterface = new ParameterizedTypeImpl(indirectInterfaceUnresolved.getRawType(), resolvedParameters.toArray(new Type[resolvedParameters.size()]),indirectInterfaceUnresolved.getOwnerType());
      }
      actualInterfaces.add(indirectInterface);
  
      return actualInterfaces;
  }
  </code></pre>
  
  <p>I hope this avoids to believe that type erasure is the cause of this issue.</p>