users@glassfish.java.net

[gf-users] Re: JMS Connection pooling

From: David Zhao <liang.x.zhao_at_oracle.com>
Date: Mon, 12 Jan 2015 11:57:55 +0800

Hi Will,

Thanks for your suggestion. It is a good idea to reuse connection from
the pool in the same transaction. This can be taken as a new enhancement
in future releases.

Thanks,
David Zhao

On 1/10/15 2:19 AM, Will Hartung wrote:
> I was disappointed to learn that when getting a JMS connection more
> than once in the same transaction, it actually consumes another
> connection from the pool.
In glassfish, the jms service is implemented as resource adaptor and the
logic is complex to decide if the physical jms connection can be reused.
But yes it doesn't take transaction into account now.
>
> We do a lot of side affect event stuff in to JMS, and with a large
> transaction, this can burn through connections at a pretty fast rate.
>
> I came up with a way to mitigate it a little bit using a Stateful
> Session Bean, and SessionSynchronization. But even with that, in the
> end, I have the same issues of having to pass it around, since
> whenever I ask for a new bean from JNDI, I get a new bean -- and a new
> connection. But it does handle connection lifecycle, and closing the
> connection properly, in a reasonably elegant manner.
Does every bean manage its own jms connection lifecycle, for example,
create a connection, then send/receive, and finally close it? Maybe you
can try this: In a XA transaction, create a jms connection and pass it
as parameter to the user transaction managed beans, then close it at the
end of transaction.
>
> In today's day and age of declarative properties, it sees quite
> "creaky" to have to be passing around things like JMS connections in
> order to conserve them.
>
> What I would really like is something that lets me tie in to the
> current transaction life cycle, then I can use a combination
> singleton/threadlocal to cache the "current" JMS connection, and then
> clean it up afterward.
>
> I've tried using TransactionSynchronizationRegistry, but things get
> out of sync and I get all sorts of transaction errors. I also tried
> using TransactionSynchronizationRegistry.getTransactionKey() to use
> that as a key to a map, but it too lead to problems. I contemplated
> using the UserTranscation as a key, but JNDI won't even give me one in
> a CMT environment (which is what I'm in).
What problem is it? The jms connection you got is not eligible to be
passed to remote RMI object (e.g. EJB remote interface). But in theory
it can be passed to local objects in the same JVM, like local EJB
interface.
>
> I can't just use a raw ThreadLocal, because we do a lot of nested
> transactions, so the connection needs to be mated with the current
> transaction.
>
> For now, I'm simply passing my Stateful Bean around, just like I did
> back 15 years ago. I'm hoping there's a better solution. A GlassFish
> specific vs a JEE solution would be fine, we have no plans on porting
> this code to anything else anytime soon.
>
> We're running GF 3.1.2.
>
> Speaking of Stateful Beans, if I don't have a @StatefulTimeout, are
> the beans automatically destroyed when the transaction
> commits/rollsback?
>
> Thanks for any thoughts on this.
>
> Regards,
>
> Will Hartung
> (willh_at_mirthcorp.com)
>