1 Reply Latest reply on Oct 25, 2016 3:21 AM by Martin Kouba

    TypeLiteral and Instance::select(TypeLiteral): limitations?

    Laird Nelson Apprentice

      (I have also asked this question on StackOverflow.)

      Suppose I have an interface like this:

      public interface Converter<T> { /*...*/ }

      And suppose in a CDI environment I have successfully done this:

      @Inject
      @Any
      private Instance<Converter<?>> converters;

      (By "successfully" I mean that I have a couple of implementations and can do the following and see several converters in the output, so beans are being discovered and supplied properly:

      for (final Object o : converters) {
        System.out.println("*** converter: " + o); // I see this output and two implementations; bean discovery is OK
      }

      …so bean discovery is not the issue.)

      And now suppose that given Integer.class, I'd like to do this:

      final TypeLiteral<Converter<Integer>> typeLiteral = new TypeLiteral<Converter<Integer>>(){};
      final Instance<Converter<Integer>> subInstance = converters.select(typeLiteral);
      final Converter<Integer> converter = subInstance.get(); // this works, when I use Integer "directly"

      In my actual code, Integer.class is passed in, so what I really have is this:

      final TypeLiteral<Converter<T>> typeLiteral = new TypeLiteral<Converter<T>>(){};
      final Instance<Converter<T>> subInstance = converters.select(typeLiteral);
      final Converter<T> converter = subInstance.get(); // this does not work, when I use T "directly"

      The get() call fails with a stack trace that starts with something that looks like the following:

      org.jboss.weld.exceptions.UnsatisfiedResolutionException: WELD-001334: Unsatisfied dependencies for type Converter<T> with qualifiers @Any
           at org.jboss.weld.bean.builtin.InstanceImpl.get(InstanceImpl.java:105)

      What must I do to make this selection succeed?

      One thing I notice is that the stack is reporting that a Converter<T> cannot be found. This looks suspicious: I would have expected it to talk in terms of Converter<Integer> instead, although, to be fair, I did indeed supply a new TypeLiteral<Converter<T>>(){}. That tells me that TypeLiteral<T> is using T as the type to look for, not the actual value "filling" the T "slot", and indeed, there is no converter declared as implements Converter<T>, and that what I'd like to do here is fundamentally impossible.

      Is that in fact the case?