[weld-dev] Discussion on Delegate/Decorated types
Pete Muir
pmuir at redhat.com
Mon Dec 7 08:44:12 EST 2009
On 7 Dec 2009, at 08:48, Mark Struberg wrote:
> Gavin, for understanding why I read this different please look at 8.1.3 "Decorated types of a decorator":
>
> "The delegate type of a decorator must implement or extend every decorated type"
>
> plus
> "The decorator intercepts every method:
> • declared by a decorated type of the decorator
> • that is implemented by the bean class of the decorator."
This defines *which* methods are decorated once a decorator has been resolved as relevant to a bean. It does not define which decorators are applied to a bean.
>
> So this is why I assumed that the decorator type (the X thingy defined with @Decorate XDec implements X) defines the beans which are decorated. And please re-read the preamble of chapter 8, which many people read as the exact same: "A decorator implements one or more bean types and intercepts business method invocations of (all!) _beans_which_implement_those_bean_types_."!
This is in effect true actually (my and/or misunderstanding changes my understanding of all of this). Remember a delegate injection point must be a subtype of all decorated types, and methods declared on decorated types are intercepted. So in effect every decorated type will considered when resolution occurs, and all methods declared on decorated types will be intercepted.
>
> I read nothing from getting the delegated types (= in my read the bean types which should get decorated) from the @Delegate. But this is obviously the only way it could work. There may be many beans out there which e.g. implement Cat and Pet but would create a ClassCastException if the PetCatDecorator get applied (@Delegate SiamCat s <-boom for RussianForrestCat)
>
> Anyway. We are now d'accord (hope so at least) that the decission which beans get decorated is: every bean which is assignable to the type of the @Delegate. (Thus Weld is implemented correctly for this part). This is really the most important part of the whole discussion. Please let's pin the
> Q: "How to decide which bean instance get's decorated by which decorator"
> A: "Every bean that is assignable to the type of the @Delegate field in a decorator will be decorated by this decorator."
>
> Pete, Marius: is this the way Weld is currently implemented?
Yes, and this is correct.
>
> Further thoughts:
> There is no need to check the decorator type (the X of @Decorator XDec implements X),because that must always be a subset of the @Delegate (see 1st sentence in 8.1.3)
> Which imho makes the decorator type basically useless - thus our question.
> To repeat the argument: why using an interface to restrict the decorator to a few functions? Simply don't implement the functions you do not like to decorate! In fact the 2 parts are exactly _not_ orthogonal things because 1) is a pure subset of 2)!
This is *exactly* the point, it supports encapsulation. e.g.
interface Foo {
void ping();
}
@Decorator class FooDecorator implements Foo {
@Inject @Delegate Foo foo;
void ping() {
print();
foo.ping();
}
void print() {
System.out.println("foo!");
}
}
class FooImpl {
public void ping () {}
}
and another person decided to add
@Specializes class SpecialFoo {
void print() {
System.out.println("hello");
}
}
then some consumer:
class Consumer {
@Inject Foo foo;
void do() {
foo.print();
}
}
would see foo! printed, not "hello" - which to the write of SpecialFoo is totally unexpected and wrong.
>
> Regarding the @Override argument. That's nice for some IDEs, but is Retention.SOURCE thus will get discarded by the compiler and helps us nothing at deploy time in the container...
> To clarify this: we are surely talking about not only the fn-name but the whole signature of a function!
>
>
> I know its _very_ hard to form a short and precise definition, and my goal is not to rant about it, but to
> a) clarify what I misunderstood
> b) @all: get a common understanding of what decorators are about (what did you have in mind basically)
> c) give you a feedback about what sentences in the spec may be/get interpreted in a different way than you meant it.
>
> txs and LieGrue,
> strub
>
> --- Gavin King <gavin.king at gmail.com> schrieb am Mo, 7.12.2009:
>
>> Von: Gavin King <gavin.king at gmail.com>
>> Betreff: Re: Discussion on Delegate/Decorated types
>> An: "Marius Bogoevici" <mariusb at redhat.com>
>> CC: "Mark Struberg" <struberg at yahoo.de>, "Weld-Dev" <weld-dev at lists.jboss.org>, "Pete Muir" <pmuir at redhat.com>
>> Datum: Montag, 7. Dezember 2009, 8:31
>> 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.
>>
>>> 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.
>>
>>> 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!
>>
>>> 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*.
>>
>>> 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*.
>>
>>> 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
>>
>
> __________________________________________________
> Do You Yahoo!?
> Sie sind Spam leid? Yahoo! Mail verfügt über einen herausragenden Schutz gegen Massenmails.
> http://mail.yahoo.com
More information about the weld-dev
mailing list