2015-08-27 18:00 GMT+02:00 Nigel Deakin <nigel.deakin(a)oracle.com>:
On 27/08/2015 16:35, Romain Manni-Bucau wrote:
>
> 2015-08-27 17:31 GMT+02:00 Nigel Deakin <nigel.deakin(a)oracle.com <mailto:
> nigel.deakin(a)oracle.com>>:
>
>
> On 26/08/2015 10:16, Romain Manni-Bucau wrote:
>
>
>
> The sample I gave before with the JmsStart event basically:
>
>
> public class JmsRegistrar {
> @Inject
> @JmsConnectionFactory(...)
> private ConnectionFactory factory;
>
> @Inject
> @JmsQueue(...)
> private Queue queue;
>
> public void startJms(@Observes JmsStart start) {
> start.withFactory(factory) // withFactory should be
> optional if only 1 bean matches it
> .register(MyCdiTypedListener.class) // with
> defaults for all potential config
> .listenOn(queue)
> .register(MyCdiTypedListener2.class, new
> MyLiteral())
> .withMaxSessions(10)
> .listenOn(Queue.class, new
> QueueLiteral(...))
> ......;
> }
> }
>
>
> The power of it appears when you have a config injection in
> JmsRegistrar you can iterate over to get the list of
> listener for instance.
>
> Also JMS resources can be decorated and referenced from
> qualifiers instead of instances thanks to CDI.
>
> It doesnt prevent the app to use @JmxListener somewhere else if
> the listener doesnt need any input/config to be
> registered.
>
>
> I'm trying to understand this. Are you suggesting that
>
> 1. When the application is started an event of type JmsStart is
> fired. This class will be defined by JMS and
> implemented by the application server.
>
> 2. The application defines a class (in this example called
> JmsRegistrar). This has a method startJms which receives
> the event.
>
> 3. JmsStart (the event class) has several builder methods. The most
> important of these is register() which you can
> use to specify the class of a listener. The other methods
> withFactory, register, withMaxSession and listenOn specify
> things like which connection factory is used, which queue is used and
> so on.
>
> This doesn't look very different from the normal JMS API, except that
> it uses a builder pattern and is triggered
> automatically at startup. Apart from triggering the initial event,
> what is CDI doing for you here?
>
>
> Yes this is it, few details important for CDI:
>
> 1- ensure JMS is CDI ready - ie dont use it before the start event, if
> JMS uses @Initialized(ApplicationScoped) then the
> app cant use it for instance, same using extension
> AfterValidationDeployment etc...so this event is just to ensure we
> dont use "JMS CDI" too early
> 2- JMS can use contextual instances implicitely which is not the case in
> SE
>
> otherwise you are right the API is just fluent compared to what is
> already there - found it nicer to expose but this
> point is maybe personal.
>
OK. I'm interested in your statement "JMS can use contextual instances
implicitly". That suggests that the method
register(MyCdiTypedListener.class) would use some CDI API such as
Instance.get() to obtain an instance of MyCdiTypedListener rather than
simply using new. Is that right?
it would do a lookup in CDI context - using the bean manager most probably.
It also means to retrieve the JMS components linked (connection factory,
Destination?....) it can do a lookup as well and do the wiring if not
ambiguous. Very good point about it is it makes default resource optional -
and then makes CDI integration more SE friendly and avoids the pain to rely
on a default resource you can't suppose anything about excepted it is there.
What I can't see yet is how to pass in the configuration
parameters for
specifying things like the queue. These are not qualifiers which are used
by Instance.select() to determine which class is instantiated. They are
values which are used by the bean's postConstruct method (as extended by
the portable extension) to initialise the bean.
Options are IMO:
- get actual instance, at this point in CDI lifecycle you can get them
injected if you want or create them manually if you desire
- use a jms qualifier to find them
Having both makes sense if a jms qualifier is added.
Nigel