Currently, CDI never tries to find the closer match. This would mean we
would be turning the whole spec completely around. Also, I don't think
it would always be clear what the closer match is:
@Inject Animal animal;
@Produces Dog produceDog();
@Produces Cat produceCat();
Both Cat and Dog are the same distance away from Animal.
But maybe it could be "if an exact match exists, use the exact match,
otherwise use the generic bean, but only if there is exactly one". But
that would still be backwards-incompatible.
Marko
On 22.7.2013 8:40, Mark Struberg wrote:
I'm still not quite sure. My gut feeling tells me that we need to
refine the rules of either BeanManager#getBeans() or BeanManager#resolve() (might fit
better, but misses the target type parameter) to find the 'nearest' Bean and apply
a cast. I'm also not really sure why we explicitly disallow <?> parameters for
producer methods. From a byte code perspective it's basically the same as a
non-subclassed <T> right?
Let us switch back to a pure user perspective for a moment - without taking care of what
we already have in the spec .
If you do it in native Java, then having a method
public <T> Cache<T> createCache(T type) {
...
}
is perfectly usable for
Cache<User> userCache = createCache(User.class);
The same could be done via CDI
@Produces @Dependent
public Cache<T> createCache(InjectionPoint ip) {
return createCache(ip.getType());
}
Of course, if there is a more closer Bean<?> for it, e.g.
@Produces @Dependent
public Cache<User> createUserCache(InjectionPoint ip) {
}
then this one should be taken for any @Inject Cache<User> userCache, but the former
one for @Inject Cache<Car> carCache.
Currently BM#getBans() would give you both Producer Methods. Means we would need some
additional resolving step. Does this sound reasonable?
It should be possible to check all those things at startup as the types are in the
classes which get validated.
I didn't have any coffee yet today, so please review properly ;)
LieGrue,
strub
----- Original Message -----
From: Marko Lukša <marko.luksa(a)gmail.com>
To: Matus Abaffy <maabaffy(a)redhat.com>
Cc: cdi-dev(a)lists.jboss.org
Sent: Friday, 19 July 2013, 13:55
Subject: Re: [cdi-dev] CDI and generics
Yes, the whole section is a definition of assignability of parameterized
types. But since bounds of type variables & wildcards can also be
parameterized types, I would expect the same rules to apply to them
also, right?
Here's a concrete example:
- is required type Foo<Bar<Object>> assignable from bean type:
Foo<Bar<T>>
Here, initially bullet 1 applies, and since type Foo is parameterized,
the same rules must be used to check assignability of Bar<T> to
Bar<Object> (bullet 4 applies in this case)
Now a very similar example (NOTE: the only difference is the "? extends"
in the required type):
- is required type Foo<? extends Bar<Object>> assignable from bean type:
Foo<Bar<T>>
Bullet 2 applies and demands we check whether Bar<T> is assignable to
Bar<Object> using Java assignability rules (?)
It's strange that you would use CDI rules in the first and Java rules in
the second example, since the two examples actually partially overlap
(<? extends Bar<Object>> includes <Bar<Object>>).
Plus, the answer to the question in example 1 is YES, while the answer
is NO in example 2. But this doesn't make sense, since the required type
in example 2 is LESS restrictive than in example 1.
What am I missing?
Marko
On 19.7.2013 13:23, Matus Abaffy wrote:
> Marko,
>
> I have a possibly very stupid answer:
>
> There is a recursive DEFINITION of when a parameterized bean type (bean type
parameter) is considered *assignable*. The bullets you mention are under this definition.
However, only the first bullet, which uses the phrase "according to these rules"
(= according to this definition), states something about *assignability* of a bean type
parameter. All the others talk about assignability of actual types/bounds/... which is
defined elsewhere. (I.e. this definition has no effect on whether "the actual type of
... is assignable to ...")
>
> I believe this is what the author wanted to say. Maybe another (italic) font should
be used for the word *assignable* when used in the newly defined meaning.
>
> Matus
>
> ----- Original Message -----
> From: "Marko Lukša" <marko.luksa(a)gmail.com>
> To: cdi-dev(a)lists.jboss.org
> Sent: Friday, July 19, 2013 12:05:41 PM
> Subject: Re: [cdi-dev] CDI and generics
>
> I have a possibly very stupid question:
>
> Do the words "assignable to" in the bullets in section 5.2.4 refer to
assignability according to the rules in that same section or to java assignability rules?
The first bullet specifically says "...is assignable to ... according to these rules
", while all the other bullets simply say "is assignable to".
>
> Since this whole section is talking about assignability, I would expect every
"is assignable to" to mean "is assignable to according to these
rules", but others think otherwise - mainly because the first bullet specifically
states "according to these rules" and others don't.
>
> Marko
>
> On 16.7.2013 13:19, Arne Limburg wrote:
>
>
>
> Makes sense to me. So we have to revert the change of CDI-85?
>
> Regards,
> Arne
>
> Von: Marko Lukša < marko.luksa(a)gmail.com >
> Datum: Dienstag, 16. Juli 2013 12:31
> An: Romain Manni-Bucau < rmannibucau(a)gmail.com >
> Cc: " cdi-dev(a)lists.jboss.org " < cdi-dev(a)lists.jboss.org >
> Betreff: Re: [cdi-dev] CDI and generics
>
> Looking at [1] again, I see the mistake now:
>
> while MediumClass is assignable to SmallClass, ArrayList<MediumClass> is NOT
assignable to ArrayList<SmallClass> (this is a common mistake - see [2]).
>
> So, given the following:
>> public class C1<T extends MediumClass> { > @Produces ...
ArrayList<T> m1() > > @Inject ... ArrayList<SmallClass> s1; >
@Inject ... ArrayList<BigClass> b1;
> s1 needs an object that is exactly an ArrayList<SmallClass> and b1 needs
exactly ArrayList<BigClass>.
>
> The producer method is able to produce ArrayList<MediumClass> and
ArrayList<BigClass>. It is NOT able to produce ArrayList<SmallClass>.
Therefore s1 cannot be satisfied.
>
> The original wording in the CDI 1.0 spec was correct:
> " - the required type parameter is an actual type, the bean type parameter is a
type variable and the actual type is assignable *to* the upper bound, if any, of the type
variable"
>
> s1: the required type parameter is the actual type SmallClass, the bean type
parameter is a type variable with upper bound MediumClass. The actual type is not
assignable to the upper bound (SmallClass is not assignable to MediumClass), therefore s1
cannot be satisfied.
>
> b1: the required type parameter is the actual type BigClass, the bean type parameter
is a type variable with upper bound MediumClass. The actual type IS assignable to the
upper bound (BigClass is assignable to MediumClass), therefore b1 can be satisfied.
>
> [1]
http://lists.jboss.org/pipermail/weld-dev/2010-August/002627.html
> [2]
http://docs.oracle.com/javase/tutorial/java/generics/inheritance.html
>
> Marko
>
> On 16.7.2013 9:36, Romain Manni-Bucau wrote:
>
>
> 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
> Blog:
http://rmannibucau.wordpress.com/
> LinkedIn:
http://fr.linkedin.com/in/rmannibucau
> Github:
https://github.com/rmannibucau
>
>
>
> 2013/7/16 Marko Lukša < marko.luksa(a)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
> Blog:
http://rmannibucau.wordpress.com/
> LinkedIn:
http://fr.linkedin.com/in/rmannibucau
> Github:
https://github.com/rmannibucau
>
>
>
> 2013/7/16 Marko Lukša < marko.luksa(a)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/b32243350ace6a0bba337f91a35f5fd05c...
>
> 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(a)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(a)gmail.com >
> Datum: Montag, 15. Juli 2013 23:41
> An: Arne Limburg < arne.limburg(a)openknowledge.de >
> Cc: Mark Struberg < struberg(a)yahoo.de >, Martin Kouba < mkouba(a)redhat.com
>, " cdi-dev(a)lists.jboss.org " < cdi-dev(a)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
> Blog:
http://rmannibucau.wordpress.com/
> LinkedIn:
http://fr.linkedin.com/in/rmannibucau
> Github:
https://github.com/rmannibucau
>
>
>
> 2013/7/15 Arne Limburg < arne.limburg(a)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 po int 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(a)gmail.com >
> Datum: Montag, 15. Juli 2013 07:55
> An: Mark Struberg < struberg(a)yahoo.de >
> Cc: Martin Kouba < mkouba(a)redhat.com >, Arne Limburg <
arne.limburg(a)openknowledge.de >, " cdi-dev(a)lists.jboss.org " <
cdi-dev(a)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
> Blog:
http://rmannibucau.wordpress.com/
> LinkedIn:
http://fr.linkedin.com/in/rmannibucau
> Github:
https://github.com/rmannibucau
>
>
>
> 2013/7/14 Mark Struberg < struberg(a)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(a)redhat.com >
> To: Arne Limburg < arne.limburg(a)openknowledge.de >
> Cc: " cdi-dev(a)lists.jboss.org " < cdi-dev(a)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(a)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(a)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(a)lists.jboss.org
>>>>>>>
https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>>>
>>>>>> _______________________________________________
>>>>>> cdi-dev mailing list
>>>>>> cdi-dev(a)lists.jboss.org
>>>>>>
https://lists.jboss.org/mailman/listinfo/cdi-dev
>>>>>>
>>>>> _______________________________________________
>>>>> cdi-dev mailing list
>>>>> cdi-dev(a)lists.jboss.org
>>>>>
https://lists.jboss.org/mailman/listinfo/cdi-dev
> _______________________________________________
> cdi-dev mailing list
> cdi-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/cdi-dev
>
> _______________________________________________
> cdi-dev mailing list
> cdi-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/cdi-dev
>
>
>
>
> _______________________________________________
> cdi-dev mailing list cdi-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/cdi-dev
>
>
> _______________________________________________
> cdi-dev mailing list
> cdi-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/cdi-dev
>
>
>
>
>
>
>
> _______________________________________________
> cdi-dev mailing list
> cdi-dev(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/cdi-dev
_______________________________________________
cdi-dev mailing list
cdi-dev(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/cdi-dev