Question

I have the need to send/receive messages towards/from different topics stored on a single JMS Server.

I would like to use JmsTemplate for sending and MessageListenerContainer for registering asyncronous listeners.

My configuration looks like this:

<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    <property name="environment">
        <props>
            <prop key="java.naming.factory.initial">xxx</prop>
            <prop key="java.naming.provider.url">yyy</prop>
        </props>
    </property>
</bean>
<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiTemplate" ref ="jndiTemplate"/>
        <property name="jndiName" value="TopicConnectionFactory"/>
    </bean>

    <bean id="singleConnectionFactory" class="org.springframework.jms.connection.SingleConnectionFactory">
        <constructor-arg ref="connectionFactory"/>
    </bean>

    <bean id="tosJmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="singleConnectionFactory"/>
        <property name="destinationResolver" ref="destinationResolver"/>
        <property name="pubSubDomain" value="true"/>
    </bean>

As far as I understood, the singleConnectionFactory, returning always the same connection instance, helps reducing the overhead of creating and closing a connection each time a jmsTemplate needs (for example) to send/receive a message (as it would be when using a normal ConnectionFactory).

My first question is: if I create multiple jmsTemplate(s), can they all share a ref to a singleConnectionFactory? Or do they have to receive a distinct instance each (singleConnectionFactory1, singleConnectionFactory2, etc)?

Reading the API for SingleConnectionFactory, I found this:

Note that Spring's message listener containers support the use of a shared Connection within each listener container instance. Using SingleConnectionFactory in combination only really makes sense for sharing a single JMS Connection across multiple listener containers.

This sound a bit cryptic to me. As far as I know, it is possible to register only 1 Listener per MessageListenerContainer, so I don't understand to what extent is a connection shared.

Suppose I want to register N Listeners: I will need to repeat N times something like this:

<bean 
    class="org.springframework.jms.listener.SimpleMessageListenerContainer"> 
    <property name="connectionFactory" ref="connectionFactory" /> 
    <property name="destinationName" value="destX" /> 
    <property name="messageListener" ref="listener1outOfN" /> 
</bean> 

How many Connections are created in such case from connectionFactory? One for each ListenerContainer or just a pool of Connections? And what if I provide the SimpleMessageListenerContainer-s with a ref to singleConnectionFactory?

What is the best approach (from the point of view of the performances, of course) in this case?

Was it helpful?

Solution

if I create multiple jmsTemplate(s), can they all share a ref to a singleConnectionFactory?

Yes, this is fine. The javadoc for SingleConnectionFactory says:

According to the JMS Connection model, this is perfectly thread-safe (in contrast to e.g. JDBC).

JMS Connection objects are thread-safe, and can be used by multiple threads concurrenctly. So there's no need to use multiple SingleConnectionFactory beans.

As far as I know, it is possible to register only 1 Listener per MessageListenerContainer, so I don't understand to what extent is a connection shared.

This is true; however, each MessageListenerContainer can have multiple threads processing messages concurrently, all using the same MessageListener object. The MessageListenerContainer will use a single, shared Connection for all of these threads (unless configured to do otherwise).

Note that Spring's message listener containers support the use of a shared Connection within each listener container instance. Using SingleConnectionFactory in combination only really makes sense for sharing a single JMS Connection across multiple listener containers.

In other words, if all you have is a single MessageListenerContainer, then SingleConnectionFactory is unnecessary, since the single connection is managed internally to MessageListenerContainer. if you have multiple listener containers, and want them all to share a connection, then SingleConnectionFactory is required. Also, if you want to share a connection between listening and sending, as you do, then SingleConnectionFactory is also necessary.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top