[weld-dev] Discussion on Delegate/Decorated types

Marius Bogoevici mariusb at redhat.com
Mon Dec 7 02:04:08 EST 2009


Gavin,

Mark and I had a discussion tonight about decorators, trying to clarify 
some aspects of the specification. It would be great if you could review 
the statements/comments/use cases described below and indicate what is 
correct, what isn't, how will the spec address this in the future, etc. 
It is a long message, but I tried to err by being too verbose rather 
than risking to leave something out.

So, the main themes of the discussion were:

a) what are the decorated types of the decorator how do we identify them 
and what role do they play?
b) what are the beans that a decorator can decorate?
c) reviewing a few examples that illustrate the various points being made.

So, I think that a) could be answered by looking at the preamble of 
chapter 8, which states that "A decorator implements one or more bean 
types and intercepts business method invocations of beans which 
implement those bean types. These bean types are called decorated types" 
and 8.1 which states that "The set of decorated types of a decorator 
includes all interfaces implemented directly or indirectly by the bean 
class, except for java.io.Serializable"
The role of decorated types is laid out by 8.1.3 which states "The 
decorator intercepts every method: • declared by a decorated type of the 
decorator [...]"

b)On the other hand, I read 8.3 as saying that a decorator can decorate 
only beans which are injectable as delegates ("The bean is eligible for 
injection to the delegate injection point according to the rules defined 
in Section 5.3, “Typesafe resolution”.")

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.
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. (I personally think this 
violates 8.1, but Pete - in CC - knows better what are the reasons for 
this).

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,.

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.
Furthermore, if a decorator decorates more than one type/interface, what 
is the type of the injected delegate? 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. If the gap was 
closed by eliminating concrete classes, then you can't have a decorator 
that decorates more than one interface.

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. 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.


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.

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.

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

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

So - Gavin, please also indicate which of these use cases is valid and 
which assertions hold or not.

Mark, I tried to lay out your questions/opinions, as well as mine, as 
accurate as I could. Feel free to comment/add anything you think is 
relevant. I think it is important to agree on both the letter as well as 
the spirit of the specification.

Cheers,
Marius









More information about the weld-dev mailing list