[cdi-dev] CDI and generics

Romain Manni-Bucau rmannibucau at gmail.com
Tue Jul 16 03:36:47 EDT 2013


no no, what i say is CDI could handle generic beans as template it would
duplicate as many time as needed to match all instances. the same as for
@Dependent but with the scope you want. there is no technical blocking
point.

*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/16 Marko Lukša <marko.luksa at gmail.com>

>  Yes, you'd need an extension that registers multiple beans. But that's
> how it needs to be.
>
> It's not sad. This simply can't work. If you inject the same instance into
> both @Inject List<String> stringList and @Inject List<Integer> integerList,
> then the user can do this:
>
> stringList.add("some string");
> integerList.add(15);
> for (String str : stringList) {
>     System.out.println(str);
> }
>
> which would result in a ClassCastException, right?
>
> Marko
>
>
> On 16.7.2013 9:23, Romain Manni-Bucau wrote:
>
> hmm, and if you don't want a @Dependent? it is doable through an extension
> but not through declaration, that's sad IMO
>
>  *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/16 Marko Lukša <marko.luksa at gmail.com>
>
>>  What Arne was concerned about is that we cannot inject the same
>> instance into two different typed injection points. We can't have an object
>> that is a list of strings and a list of integers at the same time. We would
>> need such an object if we wanted to inject it into both @Inject
>> List<String> and @Inject List<Integer>.
>>
>> What I pointed out is that CDI has this covered, as it requires all beans
>> with a parameterized bean class to be dependent scoped and by definition
>> not sharable across multiple injection points. CDI will create a _new
>> instance_ for each injection point, therefore it actually can inject bean
>> MyClass<T> into both @Inject MyClass<String> and @Inject MyClass<Integer>,
>> since it injects two different instances. There is no need to have a custom
>> extension and register MyClass<T> multiple times (as MyClass<String>,
>> MyClass<Integer>, etc.).
>>
>> So this means the change at [1] was a mistake.
>>
>> [1]
>> https://github.com/cdi-spec/cdi/commit/b32243350ace6a0bba337f91a35f5fd05c151f14
>>
>> Marko
>>
>>
>> On 16.7.2013 7:17, Romain Manni-Bucau wrote:
>>
>> Hmm not sure i get the Dependent limit. Using a custom extension you'll
>> register the same bean as many times as needed but using different values
>> for parameters and the scope you want.
>>
>> Why CDI wouldnt be able of it out of the box?
>>
>> It is really something basic in 2013 and find really sad that's look so
>> complicated. Please explain me what i'm missing if so.
>> Le 16 juil. 2013 00:15, "Marko Lukša" <marko.luksa at gmail.com> a écrit :
>>
>>>  Actually, it will never be the same instance, since all beans with a
>>> parameterized bean class must be @Dependent scoped.
>>>
>>> Marko
>>>
>>> On 15.7.2013 23:46, Arne Limburg wrote:
>>>
>>> No, I understood you right ;-)
>>> In Java the same instance cannot be MyClass<String> and MyClass<Integer>
>>> at the same time.
>>> We would do exactly that, if we had two injection points like
>>> @Inject
>>> MyClass<String> myStringClass;
>>> @Inject
>>> MyClass<Integer> myIntegerClass;
>>> In plain java this could never be the same instances without heavy
>>> (compile-time) casting, thus this should not be the same instances in CDI.
>>>
>>>  Cheers,
>>> Arne
>>>
>>>   Von: Romain Manni-Bucau <rmannibucau at gmail.com>
>>> Datum: Montag, 15. Juli 2013 23:41
>>> An: Arne Limburg <arne.limburg at openknowledge.de>
>>> Cc: Mark Struberg <struberg at yahoo.de>, Martin Kouba <mkouba at redhat.com>,
>>> "cdi-dev at lists.jboss.org" <cdi-dev at lists.jboss.org>
>>> Betreff: Re: [cdi-dev] CDI and generics
>>>
>>>  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
>>>>>
>>>>
>>>>
>>>
>>>
>>> _______________________________________________
>>> cdi-dev mailing listcdi-dev at lists.jboss.orghttps://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/20130716/37ae43f9/attachment-0001.html 


More information about the cdi-dev mailing list