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."
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_."!
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?
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)!
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(a)gmail.com> schrieb am Mo, 7.12.2009:
Von: Gavin King <gavin.king(a)gmail.com>
Betreff: Re: Discussion on Delegate/Decorated types
An: "Marius Bogoevici" <mariusb(a)redhat.com>
CC: "Mark Struberg" <struberg(a)yahoo.de>, "Weld-Dev"
<weld-dev(a)lists.jboss.org>, "Pete Muir" <pmuir(a)redhat.com>
Datum: Montag, 7. Dezember 2009, 8:31
On Mon, Dec 7, 2009 at 2:04 AM,
Marius Bogoevici <mariusb(a)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(a)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.