Thursday, June 12, 2008

Be aware the implication when using Spring JMS template with JBoss Messaging

This is a daylog note that I keep for myself and share with anyone that is interested to know. We all know the convenience of using various of template classes that Spring framework provides, but seldom we pay much attention to the implication and implicit design choices made by Spring, and recently while working with JBoss Messaging I almost missed something critical due to this kind of implication.

JmsTemplate implementation for JMS 1.1 made a crucial design choice of relying on application container to providing JMS connection pooling and caching. According to the API document:

The ConnectionFactory used with this template should return pooled Connections (or a single shared Connection) as well as pooled Sessions and MessageProducers. Otherwise, performance of ad-hoc JMS operations is going to suffer.

Spring framework assumed that most of the application server will provide a pooled JMS connection, but apparently JBoss does not think so and even openly declared that they do not provide any support if you running into any problem using Spring JmsTemplate, in this JBoss Messaging Wiki page they mentioned:

The Spring JMSTemplate code employs several anti-patterns, like creating a new connection, session, producer just to send a message, then closing them again.

...

This not only results in very poor performance, but can also make you run out of operating system resources such as threads and file handles, since some of the connection resources are released asynchronously.

....

Please note that JBoss / Red Hat will not support people using the Spring JMSTemplate with JBoss Messaging apart from the one acceptable use case for the reasons outlined above.


That being said, I am not sure that JMSTemplate actually employs anti patterns, as serious as they mentioned, in my opinion its a rather a design choice that JBoss messaging decided not to support. The recommended solution for small scale JMS usage is to decorate your connection factory with SingleConnectionFactory, this factory always returns a shared single connection wrapper and ignores the close method, which will work for most of the low volume scenario. On top of that, the new JBoss Messaging clustered connection factories, when used with clustered destination, allows seamless fail-over using a single connection which
makes this a pretty reliable solution in a clustered JMS environment. For high volume scenario, my suggestion is to use JCA managed connection factory within JBoss application server or implement your own JMS connection factory bean with connection caching or pooling outside the container (check out open JCA container implementation - Jencks) to eliminate this problem, if you are determined to work with JMSTemplate implementation.



Other references:

http://activemq.apache.org/jmstemplate-gotchas.html

2 comments:

Josh Devins said...

Thanks Nick! Used this today...

Nick Zhu said...

You are welcome :)