[cdi-dev] CDI and generics
Romain Manni-Bucau
rmannibucau at gmail.com
Tue Jul 16 03:23:19 EDT 2013
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/d39ad406/attachment-0001.html
More information about the cdi-dev
mailing list