users@glassfish.java.net

[gf-users] Re: JMS Connection pooling

From: Will Hartung <willh_at_mirthcorp.com>
Date: Mon, 12 Jan 2015 10:05:14 -0800

On Sun, Jan 11, 2015 at 7:57 PM, David Zhao <liang.x.zhao_at_oracle.com> wrote:
> 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.

Well, the desire was that I could just call something like:

JMSUtil.sendEvent(Event e), and then JMSUtil would manage all of the
connection details, so the rest of the code was ignorant of it.

What I have right now is JMSUtil is a Stateful bean. Because a
stateful bean can tie in to the transacation lifecycle.

That allows something simple like:

// in a session bean
public void doSomething() {
    JMSUtil jms = Lookup.getJMSUtil(); // Look it up from JNDI
    // send multiple messages with jms.sendEvent
}

Originally, JMSUtil just grabbed a connection, posted the message,
then closed it. But if you called the method, say, 5 times, you burned
5 connections. Once I made it stateful, each instance of JMSUtil was
able to hang on to its personal JMS Connection.

But when you scattered JMSUtil around, with each method looking up
their own instance, for the one-off message send, it basically gave no
benefit since each method was looking up their own instance of the
bean, and thus their own connection.

So, currently, I pass it around. If the parameter is null, I look it
up. That allows the code to selectively reuse the connection. It's
just that in todays day and age, managing theses resources "myself" is
clunky and invasive and ugly. Much like in JEE with JPA, I never get
my own database connection, nor do I ever explicitly call "commit" or
"rollback". The fact that I'm juggling JMS connections is 10 years
old.

Ideally I wouldn't have to manage it in the higher level code at all
(I have no problem with all the plumbing being stuck in JMSUtil).

> 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 was getting messages like this:

[#|2015-01-08T15:42:00.095-0800|INFO|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=344;_ThreadName=Thread-2;|com.sun.messaging.jms.JMSException:
[ROLLBACK_REPLY(49)] [C4036]: A broker error occurred. :[500] Bad
transaction state transition. Cannot perform operation
ROLLBACK_TRANSACTION(48) (XAFlag=null) on a transaction in state
STARTED(1). user=guest, broker=localhost:3076(63895)

Experience has taught me, when I've gone this deep in the weeds for
ostensibly simple code, that I just back out and give up and try
something completely different. I've found fighting transactions at
this level within the container not a fruitful use of my time. I've
never resolved such a problem to my satisfaction in the past, so I use
it as a trigger that I'm reaching the event horizon of a black hole,
and just try something else. At this point I abandoned the whole
precept of trying to manage the connection myself, and rewrote my code
to pass it around.

I tried this before with TransactionSynchronizationRegistry, and had
similar issues. I can't remember the use case off hand.

>> Speaking of Stateful Beans, if I don't have a @StatefulTimeout, are
>> the beans automatically destroyed when the transaction
>> commits/rollsback?

Anyone have any insight on this question also?

Thanks!

Regards,

Will Hartung
(willh_at_mirthcorp.com)

-- 
This message, and any documents attached hereto, may contain confidential 
or proprietary information intended only for the use of the addressee(s) 
named above or may contain information that is legally  privileged. If you 
are not the intended addressee, or the person responsible for delivering it 
to the intended addressee, you are hereby notified that reading, 
disseminating, distributing or copying this message is strictly prohibited. 
If you have received this message by mistake, please immediately notify us 
by replying to the message and delete the original message and any copies 
immediately thereafter.  Thank you for your cooperation.