[cdi-dev] CDI and generics
Marko Lukša
marko.luksa at gmail.com
Tue Jul 16 06:31:21 EDT 2013
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 <https://twitter.com/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 at gmail.com
> <mailto: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//
>> /LinkedIn: //_http://fr.linkedin.com/in/rmannibucau_/
>> /Github: https://github.com/rmannibucau/
>>
>>
>>
>> 2013/7/16 Marko Lukša <marko.luksa at gmail.com
>> <mailto: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
>>> <mailto: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
>>>> <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 <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
>>>
>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/cdi-dev/attachments/20130716/a88c2396/attachment-0001.html
More information about the cdi-dev
mailing list