[cdi-dev] CDI and generics

Marko Lukša marko.luksa at gmail.com
Mon Jul 15 18:15:36 EDT 2013


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 
> <mailto:rmannibucau at gmail.com>>
> Datum: Montag, 15. Juli 2013 23:41
> An: Arne Limburg <arne.limburg at openknowledge.de 
> <mailto:arne.limburg at openknowledge.de>>
> Cc: Mark Struberg <struberg at yahoo.de <mailto:struberg at yahoo.de>>, 
> Martin Kouba <mkouba at redhat.com <mailto:mkouba at redhat.com>>, 
> "cdi-dev at lists.jboss.org <mailto:cdi-dev at lists.jboss.org>" 
> <cdi-dev at lists.jboss.org <mailto: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//
> /LinkedIn: //_http://fr.linkedin.com/in/rmannibucau_/
> /Github: https://github.com/rmannibucau/
>
>
>
> 2013/7/15 Arne Limburg <arne.limburg at openknowledge.de 
> <mailto: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
>     <mailto:rmannibucau at gmail.com>>
>     Datum: Montag, 15. Juli 2013 07:55
>     An: Mark Struberg <struberg at yahoo.de <mailto:struberg at yahoo.de>>
>     Cc: Martin Kouba <mkouba at redhat.com <mailto:mkouba at redhat.com>>,
>     Arne Limburg <arne.limburg at openknowledge.de
>     <mailto:arne.limburg at openknowledge.de>>, "cdi-dev at lists.jboss.org
>     <mailto:cdi-dev at lists.jboss.org>" <cdi-dev at lists.jboss.org
>     <mailto: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//
>     /LinkedIn: //_http://fr.linkedin.com/in/rmannibucau_/
>     /Github: https://github.com/rmannibucau/
>
>
>
>     2013/7/14 Mark Struberg <struberg at yahoo.de <mailto: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 <mailto:mkouba at redhat.com>>
>         To: Arne Limburg <arne.limburg at openknowledge.de
>         <mailto:arne.limburg at openknowledge.de>>
>         Cc: "cdi-dev at lists.jboss.org <mailto:cdi-dev at lists.jboss.org>"
>         <cdi-dev at lists.jboss.org <mailto: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 <mailto: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 <mailto: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 <mailto:cdi-dev at lists.jboss.org>
>         >>>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>         >>>>>
>         >>>>>
>         >>>>>
>         >>>>> _______________________________________________
>         >>>>> cdi-dev mailing list
>         >>>>> cdi-dev at lists.jboss.org <mailto:cdi-dev at lists.jboss.org>
>         >>>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>         >>>>>
>         >>>> _______________________________________________
>         >>>> cdi-dev mailing list
>         >>>> cdi-dev at lists.jboss.org <mailto:cdi-dev at lists.jboss.org>
>         >>>> https://lists.jboss.org/mailman/listinfo/cdi-dev
>         >>>
>         >
>
>         _______________________________________________
>         cdi-dev mailing list
>         cdi-dev at lists.jboss.org <mailto:cdi-dev at lists.jboss.org>
>         https://lists.jboss.org/mailman/listinfo/cdi-dev
>
>         _______________________________________________
>         cdi-dev mailing list
>         cdi-dev at lists.jboss.org <mailto: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/20130716/fa9d20fe/attachment-0001.html 


More information about the cdi-dev mailing list