Reputation: 551
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. UsingSingleConnectionFactory
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?
Upvotes: 1
Views: 11217
Reputation: 403461
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.
Upvotes: 6