[cdi-dev] CDI and generics

Romain Manni-Bucau rmannibucau at gmail.com
Mon Jul 15 17:41:58 EDT 2013


hmm think you misunderstood what i said (sorry if it was unclear)

basically my point was a generic bean or produced bean should be injectable
everywhere so MyClass<T> should match @Inject MyClass<String>. In plain
java we do: new MyClass<String>().

*Romain Manni-Bucau*
*Twitter: @rmannibucau <https://twitter.com/rmannibucau>*
*Blog: **http://rmannibucau.wordpress.com/*<http://rmannibucau.wordpress.com/>
*LinkedIn: **http://fr.linkedin.com/in/rmannibucau*
*Github: https://github.com/rmannibucau*



2013/7/15 Arne Limburg <arne.limburg at openknowledge.de>

>   Hi Romain,
>
>  In plain old java the behavior would depend on where the type variable
> is declared.
> See the following samples:
>
>  public class MyClass<T> {
>
>      List<T> myList = new ArrayList<T>();
>
>      List<String> myStringList = myList;
> }
>
>  public class MyClass {
>
>      <T> List<T> myList() {
>         return new ArrayList<T>();
>     }
>
>      List<String> myStringList = myList();
> }
>
>  The first example does not work and the second works.
>
>  And even, if you would access myList from outside, the first example
> just works, if you instantiate myClass with the type argument:
>
>  List<String> myStringList = new MyClass<String>().myList;
>
>  To transfer this to CDI: We would need an instance of Bean MyClass with
> MyClass<String> in the type closure. And we would have to do this for every
> type argument that can be found within the injection points, i.e., if we
> had the injection points
> @Inject
> MyClass<String> myStringClass;
> @Inject
> MyClass<Integer> myIntegerClass;
> either the type closure of my class would have to contain MyClass<String>
> AND MyClass<Integer> or we would need to have different beans for both
> types. I think, we cannot do either.
>
>  I suggest to handle TypeVariables declared at class level different than
> TypeVariables declared at (producer-)method level. Thus we could handle
> Mark Strubergs case and leave the rest like it is in plain old java.
>
>  I suggest to change the fourth bullet point of chapter 5.2.4:
> "the required type parameter is an actual type, the bean type parameter is
> a type variable that is declared at class level and the actual type is
> assignable from the upper bound of the type variable,"
> and add another bullet point:
> "the required type parameter is an actual type, the bean type parameter is
> a type variable that is declared at method level and the actual type is
> assignable to the upper bound of the type variable, or"
> And add a footnote: "If no explicit upper bound is defined, the implicit
> upper bound java.lang.Object is assumed"
>
>  BTW. Should we create a spec issue for that?
>
>  WDYT?
> Regards,
> Arne
>
>  P.S.: I don't think this is a backward compatibility issue, just because
> Weld and OpenWebBeans implemented it differently in the past. It just was
> not clear in 1.0 and is not in 1.1. The misleading part is the "if any" in
> the fourth bullet point. A TypeVariable ALWAYS has an upper bound. "If no
> bound is given for a type variable, Object is assumed" (Java Lang Spec 4.4)
>
>   Von: Romain Manni-Bucau <rmannibucau at gmail.com>
> Datum: Montag, 15. Juli 2013 07:55
> An: Mark Struberg <struberg at yahoo.de>
> Cc: Martin Kouba <mkouba at redhat.com>, Arne Limburg <
> arne.limburg at openknowledge.de>, "cdi-dev at lists.jboss.org" <
> cdi-dev at lists.jboss.org>
> Betreff: Re: [cdi-dev] CDI and generics
>
>   +1, if we are no more aligned on something so simple in plain java we
> are useless i fear :(
>
> (i used and saw it used in a lot of real apps)
>
>
>  *Romain Manni-Bucau*
> *Twitter: @rmannibucau <https://twitter.com/rmannibucau>*
> *Blog: **http://rmannibucau.wordpress.com/*<http://rmannibucau.wordpress.com/>
> *LinkedIn: **http://fr.linkedin.com/in/rmannibucau*
> *Github: https://github.com/rmannibucau*
>
>
>
> 2013/7/14 Mark Struberg <struberg at yahoo.de>
>
>> folks, this breaks backward compatibility
>>
>>
>> In CDI 1.0 it was perfectly fine to do the following
>>
>>     @Produces
>>     @Dependent
>>     public <KEY, VALUE extends Serializable> Cache<KEY, VALUE>
>> getDefaultCache(InjectionPoint injectionPoint) {
>>         Type ipType = injectionPoint.getType();
>>         String cacheName = null;
>>
>>         if (ipType instanceof ParameterizedType) {
>>             ParameterizedType generic = (ParameterizedType) ipType;
>>             Type[] paramTypes = generic.getActualTypeArguments();
>>             if (paramTypes == null || paramTypes.length != 2) {
>>                 throw new RuntimeException("illegal param types for
>> generic type " + ipType);
>>             }
>>
>>             if (paramTypes[1] instanceof Class) {
>>                 cacheName = ((Class) paramTypes[1]).getSimpleName();
>>             }
>>             else {
>>                 cacheName = paramTypes[1].toString();
>>             }
>>         }
>>
>>         return getCache(cacheName);
>>     }
>>
>>
>>
>> usage:
>>
>>
>> @Inject
>> private Cache<String, IdmUser> userCache;
>>
>>
>> With your new interpretation you basically trash this, right?
>> For having a generic producer you would need to create a distinct
>> producer method for each and every usage. This just doesn't work out in
>> practice...
>>
>>
>>
>> LieGrue,
>> strub
>>
>>
>>
>>
>>
>> ----- Original Message -----
>> From: Martin Kouba <mkouba at redhat.com>
>>  To: Arne Limburg <arne.limburg at openknowledge.de>
>> Cc: "cdi-dev at lists.jboss.org" <cdi-dev at lists.jboss.org>
>> Sent: Wednesday, 10 July 2013, 14:01
>> Subject: Re: [cdi-dev] CDI and generics
>>
>>  No, it's not necessary. We'll fix this within CDITCK-349 [1]. Leave a
>> comment if you wish :-)
>>
>> Thanks
>> Martin
>>
>> [1]
>> https://issues.jboss.org/browse/CDITCK-349
>>
>>
>> Dne 10.7.2013 13:52, Arne Limburg napsal(a):
>> > OK, so shall I create a TCK issue for that?
>> >
>> >
>> > Cheers,
>> > Arne
>> >
>> > Am 10.07.13 13:50 schrieb "Martin Kouba" unter <mkouba at redhat.com>:
>> >
>> >> Hi Arne,
>> >>
>> >> I think so (except the required type is Baz<List<Qux>>) - there is no
>> >> bean with assignable bean type for this IP (according to CDI 1.1 rules
>> >> of course).
>> >>
>> >> Martin
>> >>
>> >> Dne 10.7.2013 13:16, Arne Limburg napsal(a):
>> >>> Hi Martin,
>> >>>
>> >>> So, which bean should be injected into
>> >>> @Inject
>> >>>     private Baz<List<T2>> t2BazList;
>> >>> ?
>> >>>
>> >>> Baz<T> is also not assignable to Baz<List<String>>, because
>> List<String>
>> >>> is also not assignable from Object.
>> >>>
>> >>>
>> >>> Am I right, that the test should throw an
>> >>> UnsatisfiedResolutionException?
>> >>>
>> >>> Cheers,
>> >>> Arne
>> >>>
>> >>> Am 08.07.13 12:17 schrieb "Martin Kouba" unter <mkouba at redhat.com>:
>> >>>
>> >>>> Re Arne's question:
>> >>>> Yes, Baz is a managed bean and AmbiguousResolutionException should
>> not
>> >>>> be thrown because Qux is not a managed bean (doesn't have a public
>> >>>> no-arg constructor).
>> >>>>
>> >>>> Re Marko's findings:
>> >>>> Yes, the TCK assertions are not up to date and Baz<T> is not
>> assignable
>> >>>> to Baz<String>, because String is not assignable from Object (no
>> bound
>> >>>> is defined -> Object is assumed; see JSL 4.4). So I confirm a TCK
>> >>>> issue.
>> >>>>
>> >>>> IMO this would deserve a proper cleanup...
>> >>>>
>> >>>> Martin
>> >>>>
>> >>>> Dne 8.7.2013 01:22, Marko Lukša napsal(a):
>> >>>>> I'd say it's a bug. While Baz indeed is a managed bean, it shouldn't
>> >>>>> be
>> >>>>> injected into injection point with type Baz<String> nor
>> >>>>> Baz<List<Qux>>.
>> >>>>> So I believe you're right in saying that this test should fail with
>> >>>>> UnsatisfiedResolutionException.
>> >>>>>
>> >>>>> There was a change made to the spec way back in 2010 (see [1]), but
>> >>>>> the
>> >>>>> TCK apparently wasn't updated then. I've filed an issue in the TCK
>> >>>>> jira
>> >>>>> [2].
>> >>>>>
>> >>>>> The problem isn't only in the TCK, but also in the spec itself. Some
>> >>>>> of
>> >>>>> the examples in section 5.2.4 don't conform to the rules defined in
>> >>>>> the
>> >>>>> same section (according to the rules, bean Dao<T extends Persistent>
>> >>>>> shouldn't be eligible for injection into Dao<Order> or Dao<User>). I
>> >>>>> remember asking about this a year ago ([3]), but I didn't articulate
>> >>>>> the
>> >>>>> problem properly.
>> >>>>>
>> >>>>> [1]
>> >>>>>
>> >>>>>
>> >>>>>
>> https://github.com/cdi-spec/cdi/commit/b32243350ace6a0bba337f91a35f5fd0
>> >>>>> 5c
>> >>>>> 151f14
>> >>>>> [2] https://issues.jboss.org/browse/CDITCK-349
>> >>>>> [3] http://lists.jboss.org/pipermail/cdi-dev/2012-April/001742.html
>> >>>>>
>> >>>>> Marko
>> >>>>>
>> >>>>> On 7.7.2013 16:04, Arne Limburg wrote:
>> >>>>>> Hi all,
>> >>>>>>
>> >>>>>> At the OpenWebBeans list we are currently discussing handling of
>> >>>>>> generics in CDI.
>> >>>>>> I found a test in the CDI 1.1 TCK, which imho has a bug. The test
>> >>>>>> is
>> >>>>>>
>> >>>>>>
>> org.jboss.cdi.tck.tests.inheritance.generics.MemberLevelInheritanceTes
>> >>>>>> t
>> >>>>>> and the (simplified) deployment scenario is the following:
>> >>>>>>
>> >>>>>> public class Baz<T> {
>> >>>>>> }
>> >>>>>>
>> >>>>>> public class Qux extends Baz<String> {
>> >>>>>> }
>> >>>>>>
>> >>>>>> @Vetoed
>> >>>>>> public class Bar<T1, T2> {
>> >>>>>>   @Inject
>> >>>>>>   private Baz<T1> baz;
>> >>>>>>   @Inject
>> >>>>>>   private Baz<List<T2>> t2BazList;
>> >>>>>> }
>> >>>>>>
>> >>>>>> @RequestScoped
>> >>>>>> public class Foo extends Bar<String, Qux> {
>> >>>>>> }
>> >>>>>>
>> >>>>>> public class Producer {
>> >>>>>>   @Produces
>> >>>>>>   @Amazing
>> >>>>>>   public String produceString() {
>> >>>>>>     return "ok";
>> >>>>>>   }
>> >>>>>>
>> >>>>>>   @Produces
>> >>>>>>   public String[] produceStringArray() {
>> >>>>>>     return new String[0];
>> >>>>>>   }
>> >>>>>>
>> >>>>>>   @Produces
>> >>>>>>   public Baz<Baz<Qux>> produceBazBazQux() {
>> >>>>>>     return new Baz();
>> >>>>>>   }
>> >>>>>> }
>> >>>>>>
>> >>>>>> The class Bar has some more injection points, but that does not
>> >>>>>> matter.
>> >>>>>> Due to the TCK this deployment should work, but I don't know how.
>> >>>>>> Question: Is Baz a Bean (I suppose so) and may it be injected into
>> >>>>>> Bean Foo, more precisely into the second injection point of class
>> >>>>>> Bar?
>> >>>>>> - If yes, it also should be injected into the first injection
>> >>>>>> point, right? This would lead to an AmbiguousResolutionException
>> >>>>>> since
>> >>>>>> Qux may also be injected into the first injection point.
>> >>>>>> - If no, the deployment should fail with a
>> >>>>>> UnsatisfiedResolutionException since there is no Bean that can be
>> >>>>>> injected into that injection point.
>> >>>>>>
>> >>>>>> Is this a bug in the TCK and if not, how is this supposed to work?
>> >>>>>>
>> >>>>>> Cheers,
>> >>>>>> Arne
>> >>>>>>
>> >>>>>>
>> >>>>>> _______________________________________________
>> >>>>>> cdi-dev mailing list
>> >>>>>> cdi-dev at lists.jboss.org
>> >>>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>> >>>>>
>> >>>>>
>> >>>>>
>> >>>>> _______________________________________________
>> >>>>> cdi-dev mailing list
>> >>>>> cdi-dev at lists.jboss.org
>> >>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>> >>>>>
>> >>>> _______________________________________________
>> >>>> cdi-dev mailing list
>> >>>> cdi-dev at lists.jboss.org
>> >>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>> >>>
>> >
>>
>> _______________________________________________
>> cdi-dev mailing list
>> cdi-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
>> _______________________________________________
>> cdi-dev mailing list
>> cdi-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/cdi-dev/attachments/20130715/c8f7017f/attachment-0001.html 


More information about the cdi-dev mailing list