Announcement Announcement Module
Collapse
No announcement yet.
ActiveMQ listeners and transaction proxy Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ActiveMQ listeners and transaction proxy

    I'm using the in-VM option of ActiveMQ and sending a message that contains domain objects (managed by hibernate). The message is created in my web controller and published for asynchronous processing. I am using the OSIV pattern however the hibernate session is not attached to the thread processing the message.

    The problem is that I a unable to attach a transaction proxy to the listener bean and as a result, when trying to process the message, I get errors like "net.sf.hibernate.LazyInitializationException: Failed to lazily initialize a collection - no session or session was closed"
    since the onMessage() method of the listener bean does not have a hibernate session in context.

    I tried proxying the listener as follows :

    Code:
    	<bean id="createBidConsumer" parent="txProxyTemplate">
    		<property name="target">
    			<ref local="createBidConsumerTarget"/>
    		</property>
    	</bean>
    
    	<bean id="createBidConsumerTarget" class="com.foo.jms.MessageProcessorBean" init-method="init">
    		<property name="template">
    			<ref bean="myJmsTemplate"></ref>
    		</property>
    
    		<property name="destination">
    			<bean class="org.codehaus.activemq.message.ActiveMQQueue" autowire="constructor">
    				<constructor-arg>
    					<value>create_bids</value>
    				</constructor-arg>
    			</bean>
    		</property>
    	</bean>
    however when stepping through the call stack in the debugger, Active MQ is calling the onMessage() of the unproxied MessageProcessorBean ie 'createBidConsumerTarget'.

    I guess all I need is the ability to demarcate transactions for my listener like MDB's.

    Any suggestion on how I can resolve this problem?

    Thanks,
    Sanjiv

  • #2
    I ended up wrapping my code in the onMessage() impl of my listener with

    Code:
    public void onMessage&#40;Message msg&#41;&#123;
    ...
    try
    &#123;
      session = SessionFactoryUtils.getSession&#40;sessionFactory, true&#41;;
    			session.setFlushMode&#40;FlushMode.NEVER&#41;;
      TransactionSynchronizationManager.bindResource&#40;sessionFactory, new SessionHolder&#40;session&#41;&#41;;
    
      ....
    //process message
    &#125; finally &#123;
      if&#40;session != null&#41; &#123;			
        SessionFactoryUtils.closeSessionIfNecessary&#40;session, sessionFactory&#41;;
      &#125;
    
    &#125;
    This works but I'm still interested in more elegant solutions.

    Thanks,
    Sanjiv

    Comment


    • #3
      The whole point of the asynchronous execution is to run the message consumption in another thread. Since the transaction is thread bound, I can't see how you could have the message consumption in the same transaction.
      I think you are looking for a way to put the message in the JMS queue in a transactional way: if the transaction rolls back, you want the message to be automatically removed from the queue without beeing processed by a consumer. In order to do this consult the docs of the JMS provider.

      Comment


      • #4
        No, I'm not looking for JMS transactions. I need the consumer processing thread to be within a hibernate session context / db transaction context so that I can carry out operations on my business objects like saving them, loading collections that are marked as lazy loaded.

        My requirement is analogous to the OpenSessionInView pattern which allows a hibernate session to be bound to the thread processing the servlet request.

        Thanks,
        Sanjiv

        Comment


        • #5
          I see, I missunderstood what you needed.

          Comment


          • #6
            You can use the Hibernate.initialize(proxy) method to fully initialize the proxy before sending it in the message.

            Originally posted by sjivan
            My requirement is analogous to the OpenSessionInView pattern which allows a hibernate session to be bound to the thread processing the servlet request.

            Comment

            Working...
            X