users@jms-spec.java.net

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

From: John D. Ament <john.d.ament_at_gmail.com>
Date: Tue, 6 Dec 2011 05:47:09 -0500

I considered this approach a while ago. I think there are two issues (one
relevant to CDI developers, one relevant to JMS developers) that may make
this a bit awkward to the developer. Assuming MessagingContext object that
Nigel has proposed, see below.

1. You wouldn't be able to do the following, for a type of
JmsConnectionFactory not already known

@Inject Instance<MessagingContext> messagingInstance;

@Resource(mappedName="jms/SomeDestination")
Destination d;

public void publishMessage(String cfJndi, String payload) {
messagingInstance.select(new
JmsConnectionFactoryLiteral(cfJndi)).get().send(payload,d);
}

With this form of injection, you need to know the possible values before
hand. This would potentially be a runtime bean creation, which is not good
(for example, cfJndi could have come from a JSF form at some point). Based
on the discussion Nigel and I had yesterday, I believe we should try to
support this approach, for cases where a developer wants method level
scoping of objects.

2. You would need to validate that resources exist at deployment time.
Maybe its just my experience, but I've found that most application servers
do not validate the correlation between beans deployed and resources
required until the bean has been started. This can happen quicker with
Singletons, but we would need to require that the application server scan
all of these injection points and validate that a real connection factory
exists. Where I'm at currently, the admins typically deploy applications
first, then deploy configuration (e.g. CFs, Mail adapters, etc)

John


On Tue, Dec 6, 2011 at 4:11 AM, Pete Muir <pmuir_at_bleepbleep.org.uk> wrote:

> In CDI it's perfectly valid to have the bean instance vary at runtime to
> any object. What CDI (makes you) avoid is the idea that new bean
> definitions can be added at runtime. At deployment time you can add stuff
> just fine.
>
> So, if you want to give the effect of dynamically adding beans at runtime,
> you need to add a producer method that reacts to some other info on the
> injection point than the qualifiers. For example, non binding attributes of
> a qualifier, or just other annotations.
>
> What Reza describes is a great example of what you can do - scan injection
> points and reactively create beans at deployment time. In CDI 1.1 we will
> add first class support for this pattern by providing a
> "ProcessInjectionPoint" event which you can observe to be notified of all
> injection points, and can then add beans for.
>
> Late resolution is something people have requested as a feature often for
> CDI, but it would really destroy the semantics of CDI and make it quite
> inconsistent.
>
> On 5 Dec 2011, at 21:38, reza_rahman_at_lycos.com wrote:
>
> > Nope -- it's not really forbidden :-). In a very academic sense, every
> injection point with qualifiers is supposed to be married up with
> statically configured beans or producer method configuration. In a more
> loose sense though, there is nothing wrong if these beans are dynamically
> generated/resolved by an extension. For example, we do this kind of thing
> all the time in Resin:
> >
> > @Inject @JndiNamed("queue/MyQueue") Queue myQueue; // As opposed to
> @Resource
> >
> > In theory, a developer could define a Queue object and place a
> @JndiNamed qualifier on it, but in reality they never do and they do not
> expect these objects to be statically defined anywhere. Even if there was a
> static definition, we simply throw an ambiguous resolution exception in the
> "extension" at deployment time.
> >
> > Dec 5, 2011 03:31:47 PM, jsr343-experts_at_jms-spec.java.net wrote:
> > Reza,
> >
> > Exactly which rule do you see being bent? I understand that this is not
> the primary use case designed in CDI, but it's not 'forbidden' in any way,
> is it?
> >
> >
> > On 05.12.2011, at 16:37, reza_rahman_at_lycos.com wrote:
> >
> >> 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_at_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_at_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?
> >
> >
>
>