Page 1 of 2 12 LastLast
Results 1 to 10 of 11

Thread: Sharing a JMS session between producer and consumer from different topics using Sprin

  1. #1
    Join Date
    May 2012
    Location
    NY
    Posts
    23

    Default Sharing a JMS session between producer and consumer from different topics using Sprin

    How can I share a single session between two topics using Spring?

    Without Spring it is straightforward to do
    Look up ConnectionFactory using either of the two clientIds (both topics are on same broker)
    Code:
        Connection connection = connectionFactory.createConnection();
        session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
        session.createdurableSubscriber(Topic A);
        session.createProducer(Topic B);
    so this way both the consumer for topic A and producer for topic B come under the same session.
    I want to replicate this behavior using the Spring framework

    What I have so far is two jmsTemplates

    Code:
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory1"/>
        <property name="pubSubDomain" value="true"/>
        <property name="deliveryPersistent" value="true"/>
        </bean>
    	
        <bean id="jmsTemplate1" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory2"/>
        <property name="pubSubDomain" value="true"/>
        <property name="deliveryPersistent" value="true"/>
        </bean>
    ConnectionFactory1 and ConnectionFactory are different in that the name used to look them up in the JNDI is different as they both have different client IDs.

  2. #2
    Join Date
    Oct 2005
    Location
    Boston, MA
    Posts
    2,840

    Default

    One option is to use the JmsTemplate's execute method which requires a SessionCallback. In that callback you are handed the Session being used and can perform any low-level operations you need directly with the JMS API.

    I'm a bit confused that you talk about needing the same Session but then show 2 different ConnectionFactories in use, but maybe you are just showing that you have more than one JmsTemplate within the application?

    Hope that helps.
    -Mark

  3. #3
    Join Date
    May 2012
    Location
    NY
    Posts
    23

    Default

    Is there any way in the xml to indicate that I want the same sesion to be used?
    What if I use the same jmsTemplate for both the producer and consumer (and specify a different clientId for the MessageListener)

    Code:
                  <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
                        <property name="connectionFactory" ref="connectionFactory"/>
                       <property name="pubSubDomain" value="true"/>
                       <property name="deliveryPersistent" value="true"/>
                  </bean>
    
             <bean id="stagingMessageListener" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    		<property name="connectionFactory" ref="connectionFactory"/>
    		<property name="destination" ref="topicA"/>
    		<property name="messageListener" ref="messageListener"/>
    		<property name="sessionAcknowledgeModeName" value="AUTO_ACKNOWLEDGE"/>
    		<property name="subscriptionDurable" value="true"/>
    		<property name="clientId" value="XYZ"/>
    	</bean>
    	
    	<bean id="notificationSender" class="abc.my.MessageSender">
    		<constructor-arg index="0" type = "javax.jms.Destination" ref="topicB"/>
    		<constructor-arg index="1" type = "org.springframework.jms.core.JmsTemplate" ref="jmsTemplate"/>
    	</bean>
    Since they now share the same connectionFactory is there any way for them to share the same session.
    I am trying to make the receive() and publish() execute under the same session so that I can perform an atomic commit or rollback

  4. #4
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,022

    Default

    If you set sessionAcknowledgeMode="transacted", any jmsTemplate operations on the same thread will use the same session (do not add a transactionManager; it will just use a local transaction on the session).
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  5. #5
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,022

    Default

    Sorry; since you are not using namespace support, you need to set sessionTransacted to "true".

    With the <jms:message-listener-container/> namespace, transactions are enabled via acknowledge-mode="transacted".
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  6. #6
    Join Date
    May 2012
    Location
    NY
    Posts
    23

    Default

    Thanks Gary,
    So if I set sessionTransacted= true; I don't need to do this,

    Code:
    jmsTemplate.execute(new SessionCallback<Object>() {
    
    				public Object doInJms(Session session) throws JMSException {
    					session.commit();
    					return null;
    				}
    			});
    Is that correct?
    Is the commit() taken care of for me, if so then when does it happen?
    Also for certain Exceptions (InvalidMessageException), I want the MessageListener to commit() and not rollback(). Is the default behavior for exceptions in the MessageListener rollback() or commit()?

  7. #7
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,022

    Default

    Yes, with transacted sessions, the listener container takes care of the commit for you, when the message listener returns. The session is bound to the thread - that's how the jmstemplate gets access to it.

    Exceptions will cause a rollback; simply catch any exceptions in the listener for which you want the receive() to commit.
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  8. #8
    Join Date
    May 2012
    Location
    NY
    Posts
    23

    Default

    Awesome thanks,

    Also if a the connection to the broker is lost during the onMessage() does the JMSTemplate handle the rollback and reconnect for me?
    Where can I read more about how the reconnect is handled?

  9. #9
    Join Date
    Mar 2010
    Location
    Gtr Philadelphia, PA
    Posts
    2,022

    Default

    No; if the connection is lost, the session will be bad and the template will throw a (JMS) exception; let this propagate back to the listener container and he will take care of reconnecting. Since the connection was lost during a transaction everything will be rolled back.

    I suggest you read the chapter on JMS in the Spring Reference...

    http://static.springsource.org/sprin.../html/jms.html
    Gary P. Russell
    Spring Integration Team
    SpringSource, a division of VMware

  10. #10
    Join Date
    May 2012
    Location
    NY
    Posts
    23

    Default

    Thanks Gary,

    On the link you mentioned when they talk about Synchronous Receive they say:

    While JMS is typically associated with asynchronous processing, it is possible to consume messages synchronously. The overloaded receive(..) methods provide this functionality. During a synchronous receive, the calling thread blocks until a message becomes available.
    What overloaded receive method are they talking about? The only receive I can see on the JMSTemplate is receive(Destination)
    Last edited by sur4@njit.edu; May 9th, 2012 at 03:08 PM.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •