users@jms-spec.java.net

[jms-spec users] [jsr343-experts] Re: JMS Support for DI

From: <reza_rahman_at_lycos.com>
Date: Mon, 5 Dec 2011 15:37:19 +0000 (GMT)
I agree this is quite possible, even using qualifiers (in the qualifier case, you would simply be "bending" the rules of how standard CDI reacts to qualifiers in your extension).

Dec 2, 2011 03:29:13 AM, jsr343-experts@jms-spec.java.net wrote:
John,

I understand that CDI is built with the assumption that all beans to be injected know everything at compile time (Spring does almost the same thing, only that the beans are configured in external files, so it's at deploy time, but still in advance). Even qualifiers are only used to then pick the correct bean at runtime, if there are multiple ones. The only exception to this way of thinking is non-binding qualifier attributes. They allow the bean to react on a piece of configuration, but that's not enough for these examples, esp. if e.g. the @ConnectionFactory is supposed to be optional: If it's optional, it can't be a qualifier, or you need two beans which are otherwise exactly the same. With 3 optional qualifiers, that makes 8 beans... good scaling is something else.

It's not easy, but quite possible, to write a CDI extension that builds those beans on demand. You have to scan all injection points, and for every variant of qualifiers, you dynamically create a bean. I did that for the MessageApi, so I can react on, e.g., the @DestinationName annotated to the injection point. It's actually a triple jump and the code is a little tangled right now, as it does three things... I'll fix that.

The only scope that I've yet needed was Dependent, so it's a constant right now. But I think this could be dynamic just as well. And even if not: The bean could itself reference beans that have a different scope, couldn't it.


RĂ¼diger


On 02.12.2011, at 01:33, John D. Ament wrote:

Rudiger,

So I think here is one of the issues that Pete Muir raised to us, that didn't end up on the whole EG.  This mostly stems from an issue I had that I was using incorrectly.  Basically, CDI doesn't handle the "configuration" elements that DI can provide, only the injection part.  This would be represented in things like Spring where you can read files from the file system as your context, which may differ between environments.  Configuration in this case could be done in the external files and loaded into the application context.  CDI provides no mechanism for this, though it seems like you can do this using qualifiers.  The problem is that you need to reinject on each injection point.  So the injected object must be dependent scoped, rather than bound to other contexts.  This is the main issue I see with trying to inject against a connection factory. 

Nigel,

As far as an example goes, yes that is what I was thinking. 

I really don't have an example with shared transaction.  I would imagine though just a receive method that returns a message.

John


On Thu, Dec 1, 2011 at 3:57 PM, RĂ¼diger zu Dohna <ruediger.dohna@1und1.de> wrote:
I think it could go like this:

Java SE clients require a Connection to produce MessagingContexts (formerly known as Sessions). The Connection in turn is produced from a ConnectionFactory that is looked up from JNDI. Or it could be injected with CDI, when the injection point is annotated to provide the name of the factory and the parameters required for creating the connection (user name, etc.).

@Inject
@ConnectionFactory("jms/ConnectionFactory")
@JmsCredentials(userName = "joe", password = "doe")
Connection connection;
...
MessagingContext context = connection.createMessagingContext(MessagingContext.TRANSACTED)


Java EE clients don't need a Connection, so the MessagingContext could be produced from a MessagingContextFactory that is looked up from JNDI, or directly injected with CDI. The EE client would have to provide the same parameters/annotations as the SE client, plus those required for creating the MessagingContext itself.

@Inject
@ConnectionFactory("jms/ConnectionFactory")
@JmsCredentials(userName = "joe", password = "doe")
@AcknowledgeMode(MessagingContext.AUTO_ACKNOWLEDGE)
MessagingContext context;

And best of all: Every annotation could be optional if they have useful defaults.

Does this sound feasible?