[weld-dev] Discussion on Delegate/Decorated types

Pete Muir pmuir at redhat.com
Mon Dec 7 08:33:01 EST 2009


On 7 Dec 2009, at 07:31, Gavin King wrote:

> On Mon, Dec 7, 2009 at 2:04 AM, Marius Bogoevici <mariusb at redhat.com> wrote:
> 
>> Overall, it seems like there are two competing restrictions at play: that a
>> decorator can decorate only methods defined on the decorated types (so
>> methods which are not on the decorated types will be ignored) and it can
>> decorate only beans which are injectable as delegates.
> 
> I don't understand how these restrictions are competing, and I don't
> understand your doubt. The decorated types identify the methods that
> are intercepted. The delegate injection point identifies the beans
> that are decorated. There is no overlap here. These are orthogonal
> things.

Agreed.

> 
>> It should be noted that, according to Mark, quoting Pete (and I can see the
>> same in the code) - Weld does not look at the interfaces implemented by the
>> @Decorator bean in order to retrieve the decorated types, but it infers them
>> from the type of the delegate.
> 
> That definitely doesn't sound right to me. That's not what the spec
> says. The delegate might implement some interface that is not
> implemented by the decorator, and is hence not a decorated type.

Right, this is due to the (mis-)interpretation of the sentence in the spec (and vs. or)

> 
>> Now, it may happen that a method is defined on the decorator and the target
>> class, but not on any type implemented by the decorator - according to a)
>> and 8.1.3, it won't be used to decorate anything. But in Weld, for example,
>> since the decorated types are inferred from the @Delegate, it will be used
>> for decoration anyway,.
> 
> If true, that would be a bug. That is not what the spec says. The spec
> is the source of truth here, not Weld!

Right, given the "and" interpretation of said sentence, this is a bug in Weld :-)

> 
>> The main question raised by Mark during the discussion was what is the use
>> for having the Decorator implement an interface, when for practical
>> purposes, the decorated types are indicated by the delegate type.
> 
> No, they are not. The delegate attribute may implement additional
> types that are not decorated types. And this is *useful*.

Right, we do read the decorated types in Weld from the decorator, not the delegate injection point, however we don't use em quite right due to the and/or problem.

> 
>> Furthermore, if a decorator decorates more than one type/interface, what is
>> the type of the injected delegate?
> 
> It must be a subtype of all the decorated types. The spec says this
> *explicitly*.

Right, this is implemented, and tested by 8.1.3 (a).

> 
>> The only possible solution now is a type
>> which implements/extends both interfaces, which means that only a bean of
>> that class or a subclass of it (including implementors if we're talking
>> about an interface) can be decorated. Apparently, this is possible because
>> of the gap in the specification that Gavin mentioned yesterday, which allows
>> concrete types to be delegates.
> 
> An interface can be a subtype of other interface types. I really don't
> get your point.
> 
>> If the gap was closed by eliminating
>> concrete classes, then you can't have a decorator that decorates more than
>> one interface.
> 
> Definitely not true.
> 
>   interface X extends A,B {}
> 
>> The delegate type restricts the eligible beans anyway (only beans that
>> implement/extend this class are eligible), but why is then necessary to
>> indicate a number of interface types which can be decorated? My take on this
>> is that you may not want to decorate all methods on the delegate, only
>> certain methods and requiring the decorator bean to state the interfaces it
>> wants to decorate can be used for that purpose.
> 
> Right.
> 
>> But Mark has a point here,
>> that you can achieve the same result by just not implementing those methods,
>> so the requirement for the decorator to implement certain interfaces could
>> be considered superfluous.
> 
> You've really, really lost me here. WTF would I not want to implement
> the interface? Aside from this just being a totally normal and natural
> thing to do, this makes my code typesafe (when I add @Override), and
> lets my IDE fill in the method signature for me.
> 
> Suppose the interface X declares a method void foo(), and I'm going to
> implement that same method on a class D (my decorator). Why would I
> not want to say D implements X? How the hell can the CDI impl be sure
> that this method named foo() is actually the method X.foo(), and not
> some other method that just happens to have the same name? This is not
> fucking Ruby. Java is a statically typed language. We identify methods
> by type+name+signature. Not by name alone.
> 
> What exactly are you trying to achieve here? What is wrong with having
> a decorator implement the interface it is intercepting? Why would I
> ever want to do it any differently?
> 
> 
>> c) Samples
>> Let's look at an example provided by Mark:
>> class Cat { String getName() {return "";}};
>> class AngoraCat extends Cat { boolean getHairLength() {return true}}
>> class SiamCat extends Cat { };
>> @Decorator CatDecorator { @Delegate Cat c; String getName() {
>> log.info("something"); return c.getName(); } }
>> 
>> Now, looking at this sample it seems like:
>> (ASSERTION 1) In the sample above there are no decorated types, therefore no
>> actual decoration takes place.
> 
> Correct.
> 
>> Let's add Pet, an interface and have Cat implement it
>> class Pet { String getRegistrationNumber()};
>> 
>> (ASSERTION 2) The set of decorated types consists of the interface Pet.
> 
> Not correct. Not unless CatDecorator implements Pet.
> 
>> Now let's consider the following two decorators:
>> 
>> @Decorator PetDecorator implements Pet {@Delegate Pet p; String getName() {
>> log.info("something"); return c.getName(); }}
>> @Decorator CatDecorator { @Delegate Cat c; String getName() {
>> log.info("something"); return c.getName(); } }
>> 
>> (ASSERTION 3) With the modification above, both PetDecorator and
>> CatDecorator apply to all types of cats, but PetDecorator also applies to
>> Pets which are not Cats
> 
> Correct. But note that CatDecorator has no decorated types.
> 
>> Now, if we had:
>> interface Cat { String getName();};
>> class SiamCat implements Cat, Pet { };
>> class RussianForestCat implements Cat, Pet { };
>> @Decorator PetCatDecorator implements Cat,Pet {@Delegate SiamCat c; String
>> getName() { log.info("something"); return c.getName(); }}
>> 
>> (ASSERTION 4) PetCat will decorate SiamCat but not RussianForestCat (won't
>> even be picked up as a decorator since it does not meet 8.3 wrt
>> RussianForestCat
> 
> Correct.
> 
> 
> 
> -- 
> Gavin King
> gavin.king at gmail.com
> http://in.relation.to/Bloggers/Gavin
> http://hibernate.org
> http://seamframework.org




More information about the weld-dev mailing list