We had an app in production OOME, and we were looking at the hprof and
noticed that it had an enormously large number of ActiveMQTextMessages it
was hanging onto. This app creates a dynamic JMS Consumer via
jmsContext.createConsumer. The consumer is created outside of a XA
transaction as the bean is marked with TransactionAttrbiute.NotSupported

Pool is defined:

<Resource
 id="jms/connectionFactory"
 type="javax.jms.ConnectionFactory">
 ResourceAdapter=ra/activemq
 poolMaxSize=5
 poolMinSize=1
 connectionMaxWaitTime=5s
</Resource>

The JMSContext is injected with:

@Inject
@JMSConnectionFactory("jms/connectionFactory")
private JMSContext jmsContext;

And then the app repeatedly calls consumer.receiveBody(String.class) ad
infinum and kicks off an async ejb call to handle the result. So basically,
no transactions anywhere.

What was interesting is that a bunch of these ActiveMQTextMessages had a
reference to a TomEEXAConnection... which raised some eyebrows.

The fix was to define the pool with:

<Resource
 id="jms/connectionFactory"
 type="javax.jms.ConnectionFactory">
 ResourceAdapter=ra/activemq
 poolMaxSize=5
 poolMinSize=1
 connectionMaxWaitTime=5s
 transactionSupport=none
</Resource>

That fixed the leak. Now that being said, I think TomEE is doing the right
thing: It's an XA Pool by default, and it's waiting for a transaction to
complete... but there never will be, so the JMSContext/Consumer leak
messages.

The lesson is, if you are leaking messages from a dynamically created
consumer, make sure that if your consumer is transactional, your pool is
transactional. If your dynamically created consumer is non-xa, make sure
your pool is transactionSupport=none.

cheers,
-- 
Jonathan | [email protected]
Pessimists, see a jar as half empty. Optimists, in contrast, see it as half
full.
Engineers, of course, understand the glass is twice as big as it needs to
be.

Reply via email to