[webbeans-dev] Re: @Supports
Gavin King
gavin at hibernate.org
Sun Nov 23 11:39:36 EST 2008
An alternative solution to this problem would be to define the notion
of a "prototype" producer:
@ApplicationScoped
public class QueueEndpoint {
...
@Prototype @Produces Queue getQueue() { ... }
@Prototype @Produces getQueueSession() { ... }
@Prototype @Produces getQueueSender() { ... }
@Prototype @Produces getQueueConnection() { ... }
}
The effect of the @Prototype annotation would be to define a producer
method for every Web Bean which has the implementation class
QueueEndpoint or a subclass. (Without the @Prototype annotation, there
is exactly one producer method declared.) Each of these producer
methods would have the same deployment type and binding types as the
Web Bean with which they are associated.
For example, If I configure a Queue in XML:
<Queue>
<destination>java:/comp/env/jms/PriceQueue</destination>
<connectionFactory>...</connectionFactory>
<myapp:Prices/>
</Queue>
Then I get four producer methods with binding type @Prices.
If I add the following subclass:
@Staging @Special
public class MySpecialQueueEndpoint extends QueueEndpoint {
...
}
Then there would be four new producer methods, each with deployment
type @Staging and binding type @Special.
The advantages of the approach are:
* it avoids introducing a whole new first-level construct
* it can also be applied to other "non-inherited" constructs (disposal
and observer methods)
* it avoids the problem of ambiguous method names
* types other than interfaces are supported
* the object returned by the producer method can have any scope
On the downside:
* I think it's slightly more difficult to explain
* you can't typecast the client proxy between the various types
* you don't inherit the interceptors of the "owning" Web Bean (good or bad?)
* it's a bit less dynamic - the producer method is not called for
every method invocation
* potential problems when subtypes change the scope of the "owning" Web Bean
On Fri, Nov 14, 2008 at 2:58 PM, Gavin King <gavin at 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#d0e4283
>
> (@Factory is more or less like @Produces, whereas @Unwrap is a really
> crappy version of @Supports.)
>
> --
> Gavin King
> gavin.king at gmail.com
> http://in.relation.to/Bloggers/Gavin
> http://hibernate.org
> http://seamframework.org
>
--
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