I should mention two restrictions:
* The implementation class must not be declared final.
* The type of the @Supports method/field must be an interface
On Fri, Nov 14, 2008 at 2:58 PM, Gavin King <gavin(a)hibernate.org> wrote:
I've been thinking about the problem of implementing re-usable
components like our JMS endpoints. What I'm trying to do is implement
the requirements of JMS endpoints as a simple Web Bean. To do that
today, I would need to create a class which implemented all the API
types:
@ApplicationScoped
public class QueueEndpoint
implements Queue, QueueSession, QueueSender, QueueConnection { ... }
and I would have to go and implement every one of the operations of
each of those interfaces to delegate to the correct object. (A bunch
of tedious code.)
However, if we assume that the client proxy is smart enough, we could
let the Web Bean manager automagically do that delegation for us. We
would need a new annotation that could be applied to fields or
methods, for example:
@ApplicationScoped
public class QueueEndpoint {
...
@Supports Queue getQueue() { ... }
@Supports QueueSession getQueueSession() { ... }
@Supports QueueSender getQueueSender() { ... }
@Supports QueueConnection getQueueConnection() { ... }
}
We no longer need to write all those annoying delegation methods! The
client proxy would just call the correct @Supports method when the
QueueEndpoint type did not define the method that was invoked by the
client, and delegate the method to the returned object.
To make this really work, we would need to say:
* the set of API types of the Web Bean includes all types of @Supports
methods/fields
* if a certain method name appears on more than one @Supports
method/field type, it must also be implemented directly by the impl
class
* if a certain method name appears on more than one @Supports
method/field type, or on both the impl class and a @Supports
method/field type, it is always called on the impl class
Therefore, close() would need to be implemented by QueueEndpoint:
@ApplicationScoped
public class QueueEndpoint {
...
@Supports Queue getQueue() { ... }
@Supports QueueSession getQueueSession() { ... }
@Supports QueueSender getQueueSender() { ... }
@Supports QueueConnection getQueueConnection() { ... }
void close() { throw new UnsupportedOperationException(); }
}
You're probably thinking that we can do all this with @Producer
methods, however, the semantics are not exactly the same, since the
association b/w the producer object and produced object is lost as
soon as the producer method returns. Furthermore, @Producer methods
aren't really appropriate for 3rd-party reusable objects, since the
XML configuration of a producer method is verbose.
I don't believe that Web Beans 1.0 absolutely has to have this
feature, but I know its useful, and I know that we will implement it
in the RI, so I would prefer if it was portable. What do you guys
think? Useful? Too much magic? Let me know...
Seam already has an extremely primitive/braindead version of this
feature, that I've found *extremely* useful when writing reusable
components:
http://docs.jboss.com/seam/2.1.0.SP1/reference/en-US/html/concepts.html#d...
(@Factory is more or less like @Produces, whereas @Unwrap is a really
crappy version of @Supports.)
--
Gavin King
gavin.king(a)gmail.com
http://in.relation.to/Bloggers/Gavin
http://hibernate.org
http://seamframework.org