ConnectionFactories and Caching with Spring and ActiveMQ

© Sean Ryan

In my previous two posts on ActiveMQ and Spring I’ve shown how to implement both asynchronous and synchronous messaging using MessageListenerContainers and JmsTemplates. Since then I have continued to tweak and improve my use of Spring’s JMS support and have uncovered a few more details about the ConnectionFactories supplied by both ActiveMQ and Spring and how they play together nicely and not so nicely. Some of this info is new while some was covered in my second post and lead to an edit in my initial post but I will reiterate that information here to keep it all in one place.

PooledConnectionFactory

This bad boy is the ActiveMQ provide connection pooler. It pools connections, sessions and producers and does a fine job of it. There is nothing particularly wrong with this connection factory though it does strike me as odd that it caches connections since, according to the JMS spec, connections support concurrent use.

SingleConnectionFactory

It might seem odd to have a connection factory that ensures only one connection but in reality this is quite useful. When using multiple JmsTemplates and MessageListenerContainers in Spring they will end up each creating their own connection since the default ConnectionFactory will create a new connection for each createConnection() call. Initially I thought this would be fine but I ran into some very weird issues where producers and consumers couldn’t see each other. I’m not sure if this had something to do with using embedded brokers and the VM Transport but it wasn’t good. Using a SingleConnectionFactory as the initial decorator around the default ConnectionFactory solved these issues.

CachingConnectionFactory

This is the real heavy lifter. It will cache sessions and can optionally cache consumers and producers. As any post on JmsTemplate will tell you, you MUST use caching for any sort of reasonable performance if you are not running in a JCA container. As such, this is the factory to use when using a JmsTemplate. A few points should be made clear though. First, the default is for only one session to be cached. The javadoc claims this is sufficient for low concurrency but if you are doing something more high end you probably want to increase the SessionCacheSize. Additionally, there is some weirdness around cached consumers. They don’t get closed until they are removed from the pool and they are cached using a key that contains the destination and the selector. This lead to essentially a memory leak when trying to use cached consumers for request response semantics using JMSCorrelationIds. In general caching consumers is hard which is why MessageListenerContainers should be used instead.

How’s it all work

<amq:connectionFactory id="connectionFactory" brokerURL="${jms.url}"/>
<bean id="singleConnectionFactory" p:targetConnectionFactory-ref="connectionFactory" p:reconnectOnException="true"/>
<bean id="cachingConnectionFactory" p:targetConnectionFactory-ref="singleConnectionFactory" p:sessionCacheSize="100"/>
<bean id="jmsTemplate" p:connectionFactory-ref="cachingConnectionFactory"/>
<jms:listener-container connection-factory="singleConnectionFactory">
<jms:listener id="QueueHandler" destination="Queue" ref="queueHandler"/>
</jms:listener-container>

First we start with a basic ActiveMQ ConnectionFactory. From there we wrap it in a SingleConnectionFactory and then wrap that in a CachingConnectionFactory. I’ve increased the SessionCacheSize on the CachingConnectionFactory to 100, this might be overkill but my application is anything but memory hungry so I figured I could err on the side of too many sessions. Additionally, and this is important, ReconnectOnException is set to true on the SingleConnectionFactory. The CachingConnectionFactory requires this and will complain loudly but in such as way as to make it unclear what is going on if this is not set. From there we use the CachingConnectionFactory to create a JmsTemplate and we use the SingleConnectionFactory to create a MessageListenerContainer since it takes care of any caching of sessions and consumers that it needs.

About these ads

About Benjamin Darfler
Coder, Meditator, Photographer

9 Responses to ConnectionFactories and Caching with Spring and ActiveMQ

  1. Nitin says:

    Hi Again !

    I have scenario as below:
    1. Successfully setup AMQ 5.3 server running on tcp
    Defined Queue and Topics in activemq.xml, AMQ admin shows them correctly

    2. In my swing client application,
    on some action, class1 creates message and puts in Queue in AMQ so that only single listeners gets message.
    on some action, class2 creates message and puts in Topic in AMQ so that multiple listeners get same message.

    3. In swing client application, I have created spring-config.xml as follows:


    I am not sure if I have bind multiple consumers to Topic rightly.
    Also noticed that AMQ admin shows myTopic1 and myTopic2 under “Queues” after running my app !
    Your kind guidence will get me going.

    Thank you very much for your articles.
    Nitin

  2. Nitin says:

    oh its not working after putting xml content between ...
    How should I post it ?

    • I’m really not here to help you debug your system. Ask around on the AMQ and or Spring forums. You can use pastebin.com or pastebin.org to paste code around online.

      • Nitin says:

        I posted it at pastebin.org / 617311
        Thank you very much for the pointers.
        Please help me on this pls.

  3. Nitin says:

    Hi again !

    Thanks for the link and specific mention of the end part :)
    Looks like its solved. I have created two jms:listener-container. one with destination-type queue and other with topic :)

    Many Thanks,
    Nitin

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: