Results 1 to 9 of 9

Thread: AutoProxied bean not propagating transaction rollback

  1. #1
    Join Date
    May 2005
    Posts
    3

    Default AutoProxied bean not propagating transaction rollback

    I've set up auto proxying and created a TransactionInterceptor to rollback on exceptions thrown from methods named "processMessage". It's configured with the following attribute:

    Code:
        <property name="properties">
          <props>
    	<prop key="processMessage">
    	  PROPAGATION_REQUIRED,-MessageProcException
    	</prop>
          </props>
        </property>
    My bean is an ActiveMQ container connector that is injected with an implementation of javax.jms.MessageListener.

    Code:
    <bean id="mqConnector" ...>
      ...
      <property name="messageListener">
        <ref bean="listener"/>
      </property>
    </bean>
    
    <bean id="listener" class="MyProcessor">
      <property name="destination"><value>my.Queue</value></property>
      ...
    </bean>
    Because the MessageListener interface (method 'onMessage()') doesn't throw checked exceptions, my implementation is an abstract class that includes an abstract 'processMessage()' method that does, and that is called by onMessage(). Implementations of this class for various processing needs implement processMessage():

    Code:
    abstract class my.MessageListenerImpl implements javax.jms.MessageListener &#123;
    
      public void onMessage&#40;Message m&#41; &#123;
        try &#123;
          processMessage&#40;m&#41;;
        &#125; catch &#40;Exception e&#41; &#123;
          logger.error&#40;e.getMessage&#40;&#41;&#41;;
        &#125;
    
      public abstract void processMessage&#40;Message m&#41; 
        throws MessageProcException;
    
    &#125;
    
    class MyProcessor extends MessageListenerImpl &#123;
    
      public void processMessage throws MessageProcException &#123;
        ...
      &#125;
    
    &#125;
    The onMessage() method is called by the connector when a message arrives for processing. It in turn calls processMessage(). If processMessage() throws, however, the transaction is not rolled back.

    When I add "PROPAGATION_REQUIRED,..." for "onMessage" in the interceptor's attributes and generate unchecked exceptions in onMessage(), the transaction is rolled back, but my MQ provider (ActiveMQ) doesn't seem to handle exceptions from MessageListener implementations gracefully (although I could be misinterpreting the logs.)

    I've also tried turning the two classes into two concrete classes, listener and processor, and injecting the listener with the processor but still no rollback on exception (the processor in this case still implements a processor interface). I was thinking that local method calls within a class might not execute proxy code.

    I'd love advice (no pun intended) on what to try next (or whether to just throw unchecked exceptions from MessagListener) from anyone who's configured transacted JMS message processing like this -- especially with ActiveMQ.

    thanks,

    kirt

  2. #2
    Join Date
    Oct 2004
    Location
    Antwerp, Belgium
    Posts
    96

    Default

    Let onMessage throw MessageProcException wrapped in an unchecked exception, that's the only way to notify the transaction interceptor to rollback, apart from doing a programmatic rollback.

  3. #3
    Join Date
    Aug 2004
    Location
    Melbourne, Australia
    Posts
    1,104

    Default

    that's the only way to notify the transaction interceptor to rollback, apart from doing a programmatic rollback
    You can specify rollback of checked exceptions declaritively as shown in the original post. See 7.4. Declarative transaction management of the reference manual.

  4. #4
    Join Date
    Oct 2004
    Location
    Antwerp, Belgium
    Posts
    96

    Default

    The checked exception is never thrown by the onMessage method, as illustrated in the code example.

  5. #5
    Join Date
    Aug 2004
    Location
    Melbourne, Australia
    Posts
    1,104

    Default

    The checked exception is never thrown by the onMessage method, as illustrated in the code example.
    I see. kirt, if processMessage() is called directly by onMessage(), which it is, the proxy will never see the exception to enforce the rollback.

  6. #6
    Join Date
    May 2005
    Posts
    3

    Default

    Quote Originally Posted by katentim
    I see. kirt, if processMessage() is called directly by onMessage(), which it is, the proxy will never see the exception to enforce the rollback.
    If I change this so that onMessage() calls a processMessage() method on another bean, the proxy should then see exceptions thrown from the latter, right? So the proxy doesn't affect the inner workings of a class at all, just external calls to proxied objects?

    Thanks for your responses.

  7. #7
    Join Date
    Oct 2004
    Location
    Antwerp, Belgium
    Posts
    96

    Default

    Quote Originally Posted by kirt
    Quote Originally Posted by katentim
    I see. kirt, if processMessage() is called directly by onMessage(), which it is, the proxy will never see the exception to enforce the rollback.
    If I change this so that onMessage() calls a processMessage() method on another bean, the proxy should then see exceptions thrown from the latter, right? So the proxy doesn't affect the inner workings of a class at all, just external calls to proxied objects?
    Not quite. The proxy is a vehicle to decorate method calls with - in this case - an interceptor. The transactional interceptor will catch exceptions thrown by the target bean and based on its transaction attributes may do a rollback. The onMessage method catches the exception and does not rethrow so the exception will never reach the interceptor, hence no rollback will occur.

  8. #8
    Join Date
    Oct 2004
    Location
    Antwerp, Belgium
    Posts
    96

    Default

    Quote Originally Posted by kirt
    Quote Originally Posted by katentim
    I see. kirt, if processMessage() is called directly by onMessage(), which it is, the proxy will never see the exception to enforce the rollback.
    If I change this so that onMessage() calls a processMessage() method on another bean, the proxy should then see exceptions thrown from the latter, right? So the proxy doesn't affect the inner workings of a class at all, just external calls to proxied objects?
    Something just occured to me. The messages are processed asynchronously, so indeed, if you call a proxy instance from within the onMessage method a rollback would indeed occur.

  9. #9
    Join Date
    May 2005
    Posts
    3

    Default

    Right -- the autoproxy mechanism would be used to proxy any bean implementation of a processMessage() method. Thanks for your help.

Similar Threads

  1. Unit testing with JOTM and JtaTransactionManager
    By lalle in forum Architecture
    Replies: 1
    Last Post: Oct 15th, 2005, 09:05 AM
  2. Spring container fails with no exception
    By naor in forum Container
    Replies: 9
    Last Post: Oct 1st, 2005, 03:39 PM
  3. EHCaching Hibernate
    By dencamel in forum Data
    Replies: 3
    Last Post: Sep 6th, 2005, 09:03 PM
  4. could not satisfy dependencies
    By springuser in forum Container
    Replies: 4
    Last Post: Apr 26th, 2005, 01:15 PM
  5. Replies: 1
    Last Post: Apr 25th, 2005, 07:37 PM

Posting Permissions

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