11 Replies Latest reply on Feb 1, 2013 12:23 PM by Justin Bertram

    Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final

    firebet99 Newbie

      Hi - I'm new to JBoss 7 and have recently undergone a solo effort to upgrade a large legacy application from JBoss 4.2.2 to 7.1.1-Final. I'll admit it wasn't straightforward but for the most part it has been successful. There are a few issues that I've struggled with though, one of which I'd like to discuss here.

       

      I spent most of yesterday trying to track down an issue with timeouts and rollback in a number of MDBs that I have migrated. I followed a few different EJB 2.x -> 3.x migration articles and have a MDB setup that uses purely Bean-managed transactions. The MDBs generally kick-off long-running async processes from a servlet-based application to allow us to continue without waiting for response from the processes (which write to log tables).  For example, the onMessag() method may start a Grid-enabled process that may take up to 30-40 mins to return a result or may start a series of large data updates using DAOs that control their own transactions, and the onMessaga() method blocks until the result returns.

       

      In JBoss 4.2.2 these MDBs always worked fine and I did not see a timeout set explicitly anywhere in the ejb xml config.  However after migration I found that processes taking longer than 5 min (300 seconds) appeared to be rolled-back by the Arjuna TX 'reaper' process, which was causing havoc in the app as the messages were then being re-tried causing duplicate results (fortunately it's only in QA for now!)  After creating a test case with a sleep() method and trying various methods of increasing the timeout using annotations in the class - (none of which appeared to work) - I finally tracked the issue down to the transactions subsystem entry <coordinator-environment default-timeout="300"/> thanks to this post: https://community.jboss.org/thread/203599

      Changing this setting to a higher value allows the processes to complete without Arjuna timing them out.

       

      My questions are:

      1) If I specify the class as bean-managed @TransactionManagement(TransactionManagementType.BEAN) and @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) why is Arjuna still timing out the onMessage() method? Does the system process the onMessage() method inside a transaction regardless of the class/method annotations specified?

      2) If the MDB does timeout and rollback, how can I prevent the message being re-tried? The Use-Case is to try the operation once and notify the user if something goes wrong via log tables - but not to retry unless the user explicitly tries the operation again.

      3) I don't really like the workaround of increasing the general default timeout as I'm concerned about effects on other  processes. The underlying DAOs control transaction management but I'd like to configure the onMessage() timeout on a per-MDB basis to make it clear in the code that the process may take a long time to complete. Is this possible? The timeout annotation (org.jboss.ejb3.annotation.TransactionTimeout) value seems to get ignored - presumably something to do with the TransactionAttributeType I am setting? Do I need to implement UserTransaction.setTransactionTimeout()? I've seen various posts pointing out issues with that approach too. Right now, I don't declare UserTransaction in any of my MDBs - only @Resource MessageDrivenContext, which is only invoked in the case of a JMSException (I call setRollbackOnly()) but not if any other kind of Exception occurs.

       

      Any suggestions for best-practise given my scenario? I'm happy to post code examples if necessary.

      Many thanks.

        • 1. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
          Justin Bertram Master

          In JBoss 4.2.2 these MDBs always worked fine and I did not see a timeout set explicitly anywhere in the ejb xml config.

          The container-wide transaction timeout configuration in AS 4.2.2 is in <profile>/conf/jboss-service.xml:

           

             <mbean code="com.arjuna.ats.jbossatx.jta.TransactionManagerService"

                name="jboss:service=TransactionManager">

                <attribute name="TransactionTimeout">300</attribute>

                <attribute name="ObjectStoreDir">${jboss.server.data.dir}/tx-object-store</attribute>

             </mbean>

           

          I would expect the same timeout to occur on 4.2.2 as on 7.x unless this was changed.

           

           

          1) If I specify the class as bean-managed @TransactionManagement(TransactionManagementType.BEAN) and @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) why is Arjuna still timing out the onMessage() method? Does the system process the onMessage() method inside a transaction regardless of the class/method annotations specified?

          If your MDB is using BMT then the delivery of the message to the MDB shouldn't be part of a transaction.  Can you paste or attach the MDB where you've configured BMT?

           

           

          2) If the MDB does timeout and rollback, how can I prevent the message being re-tried? The Use-Case is to try the operation once and notify the user if something goes wrong via log tables - but not to retry unless the user explicitly tries the operation again.

          Message redelivery behavior is controlled by the <max-delivery-attempts> for the associated address defined in <hornetq-server>.  The default <max-delivery-attempts> is 10.

           

           

          3) I don't really like the workaround of increasing the general default timeout as I'm concerned about effects on other  processes. The underlying DAOs control transaction management but I'd like to configure the onMessage() timeout on a per-MDB basis to make it clear in the code that the process may take a long time to complete. Is this possible?

          Yes, that should be possible - either programmatically if you are using BMT or declaratively if you are using CMT.

           

           

          The timeout annotation (org.jboss.ejb3.annotation.TransactionTimeout) value seems to get ignored - presumably something to do with the TransactionAttributeType I am setting? Do I need to implement UserTransaction.setTransactionTimeout()?

          If you are using CMT then @TransactionTimeout applies, but if you are using BMT then @TransactionTimeout does not apply.  If you are using BMT and starting a transaction programmatically then you can use UserTransaction.setTransactionTimeout().

           

           

          Right now, I don't declare UserTransaction in any of my MDBs - only @Resource MessageDrivenContext, which is only invoked in the case of a JMSException (I call setRollbackOnly()) but not if any other kind of Exception occurs.

          That approach is only viable if you are using CMT.  What are you doing with other exceptions?  Is there any possibility that a RuntimeException could be thrown from the onMessage()?  If so, you should eliminate that possibility as it is considered a programming error.

           

           

          Any suggestions for best-practise given my scenario? I'm happy to post code examples if necessary.

          First, you need to figure out what kind of transaction management you want to use - CMT or BMT.  Once you do that then I can help you configure your MDB accordingly.

          1 of 1 people found this helpful
          • 2. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
            firebet99 Newbie

            Justin, many thanks for such a swift response. Your reply is extremely helpful in understanding what is going on here.

            In JBoss 4.2.2 these MDBs always worked fine and I did not see a timeout set explicitly anywhere in the ejb xml config.

            The container-wide transaction timeout configuration in AS 4.2.2 is in <profile>/conf/jboss-service.xml:

             

               <mbean code="com.arjuna.ats.jbossatx.jta.TransactionManagerService"

                  name="jboss:service=TransactionManager">

                  <attribute name="TransactionTimeout">300</attribute>

                  <attribute name="ObjectStoreDir">${jboss.server.data.dir}/tx-object-store</attribute>

               </mbean>

             

            I would expect the same timeout to occur on 4.2.2 as on 7.x unless this was changed.

             

            I checked this and it looks like the default in 4.2.2 was changed to 1200 seconds - I really should have figured that one out myself - it was late and I only checked the application configuration... not the old JBoss config.

             

               <mbean code="org.jboss.tm.TransactionManagerService"

                  name="jboss:service=TransactionManager"

                  xmbean-dd="resource:xmdesc/TransactionManagerService-xmbean.xml">

                  <attribute name="TransactionTimeout">1200</attribute>

                  <!-- set to false to disable transaction demarcation over IIOP -->

                  <attribute name="GlobalIdsEnabled">true</attribute>

                  <depends optional-attribute-name="XidFactory">jboss:service=XidFactory</depends>

               </mbean>

             

            Looking at this, I think we've just been lucky so far not to hit the 20 min limit in production. We definately come close with some transactions. We will certainly expect to exceed 20 mins over the next year with the increased data we anticipate on processing.

             

            Below is current configuration of one of the MDBs I have upgraded (with superfluous business logic, proprietary imports + javadoc removed!) We have an abstract base class that all MDBs inherit from and I've included an example implementation class. All the beans are implemented as BMT. From the docs I believe the default TransactionAttribute is NOT_SUPPORTED for MDBs?

             

            import javax.annotation.Resource;
            import javax.ejb.MessageDrivenContext;
            import javax.jms.Message;
            import javax.jms.MessageListener;
            import javax.jms.ObjectMessage;
            
            public abstract class BaseMessageDrivenBean implements MessageListener {
                
                private static final Log LOG = LogFactory.getLog(BaseMessageDrivenBean.class);
            
                @Resource
                private MessageDrivenContext mdc;
            
                protected MessageDrivenContext getMessageDrivenContext() {
                    return mdc;
                }
            
                protected void rollbackTransaction() {
                    try {
                        getMessageDrivenContext().setRollbackOnly();
                    } catch (Exception e) {
                        LOG.warn("Unable to rollback TX for MDB", e);
                    }
                }
                
                @Override
                public void onMessage(Message inMessage) {
            
                    // Convenient cast..
                    if (inMessage instanceof ObjectMessage) {
                        onMessage((ObjectMessage) inMessage);
                    } else {
                        LOG.error("Message of wrong type received by " + this.getClass().getName() + " : " + inMessage.getClass().getName());
                    }
                }
            
                public abstract void onMessage(ObjectMessage objMsg);
            }
            

             

            Implementation class

            import javax.ejb.ActivationConfigProperty;
            import javax.ejb.MessageDriven;
            import javax.ejb.TransactionManagement;
            import javax.ejb.TransactionManagementType;
            import javax.jms.JMSException;
            import javax.jms.ObjectMessage;
            
            @MessageDriven(activationConfig =
            {  @ActivationConfigProperty(propertyName="destinationType",
                propertyValue="javax.jms.Queue"),
               @ActivationConfigProperty(propertyName="destination",
                propertyValue="queue/validationRequestQueue")
            })
            @TransactionManagement(TransactionManagementType.BEAN)
            public class ValidationMessageBean extends BaseMessageDrivenBean {
                
            
                private static final long serialVersionUID = 5657315726160959334L;
                private static final Log LOG = LogFactory.getLog(ValidationMessageBean.class);
            
                /**
                 * {@inheritDoc}
                 */
                @Override
                public void onMessage(ObjectMessage objMsg) {
                    try {
            
                        ... kick off some Grid-enabled processing that can take a long time to return ... 
                                     
                    } catch (ValidationGridException e){
                        LoggingLocator.logError(Constants.VALIDATION_COMPONENT, "Validation error occurred", e);
                        LOG.error("System error from the (re)validation process: ", e);
                    } catch (JMSException jmse) {
                        LOG.error("JMS problem - ValidationMessage not found", jmse);
                        rollbackTransaction();
                    } catch (Throwable t) {
                        LOG.error("ERROR: Unexpected exception from validation: " + t.getMessage());
                    }
                }
            }
            

             

            As you can see from the example, we do a final catch-all for Throwable so nothing should escape from onMessage(). It should probably be refactored to just catch Exception and not Error too!

             

            From your notes, to implement programable timeouts in these MDBs, I am assuming I will need to implement calls to UserTransaction from the onMessage() method in my implementation classes in order to set a programatical timeout that differs from the default in standalone.xml?  I also need to start/commit/rollback the user transaction? Which rollback method do I call? rollback() or setRollbackOnly()?


            Since many of the MDBs kick off Grid-enabled processes in other JVMs (we use GridGain), if the underlying DAOs in these processes manage their own transaction boundaries, how does the UserTransaction in onMessage() affect this? Or does it have no effect other than to inform the MDB transaction manager that the message has been processed?

             

            Thanks again.

            • 3. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
              Justin Bertram Master

              From the docs I believe the default TransactionAttribute is NOT_SUPPORTED for MDBs?

              That's not correct.  By default, all EJB3s use:

               

              @TransactionManagement(TransactionManagementType.CONTAINER)
              @TransactionAttribute(TransactionAttributeType.REQUIRED)
              

               

              As the Java EE 6 Tutorial from Oracle says, "By default, if no transaction demarcation is specified, enterprise beans use container-managed transaction demarcation..." and, "The Required attribute is the implicit transaction attribute for all enterprise bean methods running with container-managed transaction demarcation."  I'm sure there's a section in the EE spec that says as much but I don't really want to wade through that right now.

               

              Based on what you pasted here, since you're using @TransactionManagement(TransactionManagementType.BEAN) there should be no transaction at all started by or for the MDB so therefore there should be no timeout to worry about.  Are you seeing timeouts when you use this code?

               

              From your notes, to implement programable timeouts in these MDBs, I am assuming I will need to implement calls to UserTransaction from the onMessage() method in my implementation classes in order to set a programatical timeout that differs from the default in standalone.xml?  I also need to start/commit/rollback the user transaction? Which rollback method do I call? rollback() or setRollbackOnly()?

              If you want the MDB to start a transaction here then yes, you'll need to use UserTransaction.  There are lots of tutorials out there as well as good books no how to use this interface.

               

              Since many of the MDBs kick off Grid-enabled processes in other JVMs (we use GridGain), if the underlying DAOs in these processes manage their own transaction boundaries, how does the UserTransaction in onMessage() affect this? Or does it have no effect other than to inform the MDB transaction manager that the message has been processed?

              If you're calling components in other JVMs it's unlikely the MDB's transaction (if one exists) has any impact on those components since the transaction almost certainly isn't propagating across those boundaries.  Furthermore, if the DAOs are managing their own transactions rather than participating in the caller's transaction then what they do wouldn't impact the MDB's transaction even if it did propagate (and vice-versa).

               

              At the end of the day I'm not entirely sure what purpose a transaction in the MDB would serve.  It sounds to me like the MDB is simply kicking off a ton of work that is being done transactionally in bits and pieces rather than being completely atomic which means if the MDB fails to process the message for some reason and the message happens to get redelivered you get duplicate data (i.e. a big mess).  I think you're in for some long nights if you allow this kind of risk in production.  Murphy's Law.

               

              Long-running transactions are a well-known anti-pattern, but at least they prevent nasty data integrity issues if everybody participates properly (which may not even be possible in your situation).

              • 4. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
                firebet99 Newbie

                 

                From the docs I believe the default TransactionAttribute is NOT_SUPPORTED for MDBs?

                That's not correct.  By default, all EJB3s use:

                 

                @TransactionManagement(TransactionManagementType.CONTAINER)
                @TransactionAttribute(TransactionAttributeType.REQUIRED)
                

                 

                Ok, I may be misquoting something I read relating to an old 2.x article that said MDBs default trans-attribute is NOT_SUPPORTED:

                http://docs.oracle.com/cd/B14099_19/web.1012/b14012/jta.htm#CIAIADDG

                This is not the case with EJB3 and I certainly didn't mean to spread misinformation. (I read a lot of different articles on Tuesday night!)

                 

                 

                Based on what you pasted here, since you're using @TransactionManagement(TransactionManagementType.BEAN) there should be no transaction at all started by or for the MDB so therefore there should be no timeout to worry about.  Are you seeing timeouts when you use this code?

                Yes, as my original post indicated, I was seeing the arjuna TX 'reaper' thread attempting to set a rollback state for the MDB after the default 300 sec timeout expired if the onMessage() method had not completed. I verified this behaviour with a test bean set to BMT and several different configurations of TransactionAttribute set to NOT_SUPPORTED with a sleep() method in the bean that overran the default timeout setting by a few seconds. Each time I triggered the MDB, the arjuna TX reaper attempted a rollback which triggered message re-delivery. This is what confused me, because I thought by marking the MDB as BMT, no transaction would be started therefore there would be nothing for arjuna to rollback and the <coordinator-environment default-timeout> value would be irrelevant? Am I missing something?

                 

                If you're calling components in other JVMs it's unlikely the MDB's transaction (if one exists) has any impact on those components since the transaction almost certainly isn't propagating across those boundaries.  Furthermore, if the DAOs are managing their own transactions rather than participating in the caller's transaction then what they do wouldn't impact the MDB's transaction even if it did propagate (and vice-versa).

                I hadn't expected that the MDBs transaction boundaries would propagate to other JVMs which is why I don't want to use transactions in the MDBs. They are irrelevant in my example. The purpose of the example MDB is simply to kick-off an asynchronous process that (once triggered) is entirely self-contained. I guess they could have used threads to achieve the same thing for this, but they chose MDBs. There are no transactions required in the MDB which is why I had set them to BMT and was testing the NOT_SUPPORTED setting. But, as stated, it had no effect on the arjuna TX reaper process, which still appeared to trigger a rollback in the MDB.

                 

                Right now, with the default timeout increased we have effectively mimic'd the setup from 4.2.2 I think. We certainly haven't noticed any further issues since I changed the setting. Having looked at other MDBs in the app more carefully, we actually could implement BMT properly with UserTransactions (or even CMT) and remove the custom transaction management from the DAOs in those MDBs - but this involves refactoring quite a few classes... so for now, I'd rather avoid that route as time is a factor.

                 

                At the end of the day I'm not entirely sure what purpose a transaction in the MDB would serve.

                It serves no purpose at all, I don't want to initiate one, but I couldn't seem to figure out how to stop arjuna from triggering a rollback programatically using annotations in the code. What has worked is to increase the default timeout for coordinator-environment... I was hoping to do it programmatically in the code on a per-class basis?

                It sounds to me like the MDB is simply kicking off a ton of work that is being done transactionally in bits and pieces rather than being completely atomic which means if the MDB fails to process the message for some reason and the message happens to get redelivered you get duplicate data (i.e. a big mess).  I think you're in for some long nights if you allow this kind of risk in production.  Murphy's Law.

                 

                Long-running transactions are a well-known anti-pattern, but at least they prevent nasty data integrity issues if everybody participates properly (which may not even be possible in your situation).

                 

                You are correct, except the 'ton of work' is managed by passing messages to Grid-enabled 'nodes' which then process batches of work atomically. This app has been in production on JBoss 4.2.2 for several years without a problem. I was asked to upgrade the JBoss version by management who (rightly or wrongly) thought that 4.2.2 was too old for a production system. Probably a fair point.

                 

                By setting the max-delivery-attempts to 1, we overcome the problem of message duplication, so that issue is also addressed.

                 

                As for long-running transactions, I agree. I try to keep mine as short as possible without compromising data integrity. Once again, thanks for taking the time to reply. I appreciate the clarifications and feedback.

                • 5. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
                  Justin Bertram Master

                  Yes, as my original post indicated, I was seeing the arjuna TX 'reaper' thread attempting to set a rollback state for the MDB after the default 300 sec timeout expired if the onMessage() method had not completed. I verified this behaviour with a test bean set to BMT and several different configurations of TransactionAttribute set to NOT_SUPPORTED with a sleep() method in the bean that overran the default timeout setting by a few seconds. Each time I triggered the MDB, the arjuna TX reaper attempted a rollback which triggered message re-delivery. This is what confused me, because I thought by marking the MDB as BMT, no transaction would be started therefore there would be nothing for arjuna to rollback and the <coordinator-environment default-timeout> value would be irrelevant? Am I missing something?

                  I just performed a quick test of this and everything worked as expected.  Here's the MDB I used:

                   

                  import javax.ejb.ActivationConfigProperty;
                  import javax.ejb.MessageDriven;
                  import javax.ejb.TransactionAttribute;
                  import javax.ejb.TransactionAttributeType;
                  import javax.ejb.TransactionManagement;
                  import javax.ejb.TransactionManagementType;
                  import javax.jms.Message;
                  import javax.jms.MessageListener;
                  
                  @MessageDriven(name = "MDB_CMT_Example", activationConfig = { 
                          @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
                          @ActivationConfigProperty(propertyName = "destination", propertyValue = "testQueue")
                   })
                  @TransactionManagement(value = TransactionManagementType.CONTAINER)
                  @TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED)
                  public class MDB_CMT_Example implements MessageListener { 
                  
                      public void onMessage(final Message message) {
                          try {
                              System.out.println("message received");
                              Thread.sleep(310000);
                          } catch (Exception e) {
                              e.printStackTrace();
                          } finally {
                              System.out.println("Done.");
                          }
                      }
                  }
                  

                   

                  Even though the MDB slept for 310 seconds (which exceeded the default transaction timeout of 300 seconds) I never saw any rollbacks or logging from the transaction manager.

                   

                  I sent 5 messages.  Here is the output from the log:

                   

                  10:13:19,050 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) message received
                  10:18:29,050 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) Done.
                  10:18:29,054 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) message received
                  10:23:39,054 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) Done.
                  10:23:39,057 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) message received
                  10:28:49,057 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) Done.
                  10:28:49,058 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) message received
                  10:33:59,059 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) Done.
                  10:33:59,060 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) message received
                  10:39:09,061 INFO  [stdout] (Thread-7 (HornetQ-client-global-threads-8928332)) Done.
                  
                  • 6. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
                    firebet99 Newbie

                    Taking your example and changing the TransactionManagementType to BEAN, (effectively replicating the current setup of my MDBs), I get the error that prompted this discussion. I'd like to understand why this happens if there is no transaction.

                     

                     

                    import javax.ejb.ActivationConfigProperty;
                    import javax.ejb.MessageDriven;
                    import javax.ejb.TransactionAttribute;
                    import javax.ejb.TransactionAttributeType;
                    import javax.ejb.TransactionManagement;
                    import javax.ejb.TransactionManagementType;
                    import javax.jms.Message;
                    import javax.jms.MessageListener;
                    
                    @MessageDriven(name = "TestMDB", activationConfig = { 
                            @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
                            @ActivationConfigProperty(propertyName = "destination", propertyValue = "testQueue")
                     })
                    @TransactionManagement(value = TransactionManagementType.BEAN)
                    @TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED)
                    public class TestMDB implements MessageListener { 
                    
                        public void onMessage(final Message message) {
                            try {
                                System.out.println("TestMDB message received");
                                Thread.sleep(310000);
                            } catch (Exception e) {
                                e.printStackTrace();
                            } finally {
                                System.out.println("Done.");
                            }
                        }
                    }
                    

                     

                    13:43:29,813 INFO  [stdout:71] TestBean sending message to testQueue

                    13:43:30,016 INFO  [stdout:71] TestBean message sent

                    13:43:30,031 INFO  [stdout:71] TestMDB message received

                    13:48:30,033 WARN  [com.arjuna.ats.arjuna:148] ARJUNA012117: TransactionReaper::check timeout for TX 0:ffff0a054935:-6f5fd3f5:510abb3d:18 in state  RUN

                    13:48:30,043 WARN  [com.arjuna.ats.arjuna:436] ARJUNA012121: TransactionReaper::doCancellations worker Thread[Transaction Reaper Worker 0,5,main] successfully canceled TX 0:ffff0a054935:-6f5fd3f5:510a

                    bb3d:18

                    13:48:30,043 INFO  [stdout:71] TestMDB message received

                    13:48:40,034 INFO  [stdout:71] Done.

                    13:48:40,034 WARN  [com.arjuna.ats.arjuna:1588] ARJUNA012077: Abort called on already aborted atomic action 0:ffff0a054935:-6f5fd3f5:510abb3d:18

                    13:48:40,034 WARN  [org.hornetq.ra.inflow.HornetQMessageHandler:320] Unable to call after delivery: javax.resource.spi.LocalTransactionException: javax.transaction.RollbackException: ARJUNA016063: The

                    transaction is not active!

                            at org.jboss.as.ejb3.inflow.MessageEndpointInvocationHandler.afterDelivery(MessageEndpointInvocationHandler.java:88)

                            at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_20]

                            at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) [rt.jar:1.6.0_20]

                            at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_20]

                            at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_20]

                            at org.jboss.as.ejb3.inflow.AbstractInvocationHandler.handle(AbstractInvocationHandler.java:60)

                            at org.jboss.as.ejb3.inflow.MessageEndpointInvocationHandler.doInvoke(MessageEndpointInvocationHandler.java:136)

                            at org.jboss.as.ejb3.inflow.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:73)

                            at $Proxy20.afterDelivery(Unknown Source)       at org.hornetq.ra.inflow.HornetQMessageHandler.onMessage(HornetQMessageHandler.java:287) [hornetq-ra-2.2.13.Final.jar:]

                            at org.hornetq.core.client.impl.ClientConsumerImpl.callOnMessage(ClientConsumerImpl.java:983) [hornetq-core-2.2.13.Final.jar:]

                            at org.hornetq.core.client.impl.ClientConsumerImpl.access$400(ClientConsumerImpl.java:48) [hornetq-core-2.2.13.Final.jar:]

                            at org.hornetq.core.client.impl.ClientConsumerImpl$Runner.run(ClientConsumerImpl.java:1113) [hornetq-core-2.2.13.Final.jar:]

                            at org.hornetq.utils.OrderedExecutorFactory$OrderedExecutor$1.run(OrderedExecutorFactory.java:100) [hornetq-core-2.2.13.Final.jar:]

                            at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [rt.jar:1.6.0_20]

                            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [rt.jar:1.6.0_20]

                            at java.lang.Thread.run(Thread.java:619) [rt.jar:1.6.0_20]

                    Caused by: javax.transaction.RollbackException: ARJUNA016063: The transaction is not active!

                            at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1155) [jbossjts-4.16.2.Final.jar:]

                            at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:117) [jbossjts-4.16.2.Final.jar:]

                            at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75)

                            at org.jboss.as.ejb3.inflow.MessageEndpointInvocationHandler.afterDelivery(MessageEndpointInvocationHandler.java:72)

                            ... 16 more

                     

                    I should add that if I add a UserTransaction to the example and programatically extend the timeout beyond the default and allow the onMessage() to complete before the UTX timeout fires, then it works as expected. No arjuna error. If I reduce the UTX timeout to less than the sleep(), then I get the error, so this confirms the programatical timeout is being used. But the question remains though, if I'm not starting a transaction inside the MDB, what is arjuna timing out?

                     

                    @TransactionManagement(value = TransactionManagementType.BEAN)
                    @TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED)
                    public class TestMDB implements MessageListener { 
                    
                        @Resource
                        UserTransaction ut;
                    
                        public void onMessage(final Message message) {
                            try {
                                ut.setTransactionTimeout(400);
                                System.out.println("TestMDB message received");
                                Thread.sleep(410000);
                            } catch (Exception e) {
                                e.printStackTrace();
                            } finally {
                                System.out.println("Done.");
                            }
                        }
                    }
                    
                    
                    
                    • 7. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
                      Justin Bertram Master

                      This looks like a bug to me.  I'll continue to investigate. 

                       

                      In the mean time, can you confirm that using this does not result in a transaction timeout?

                       

                      @TransactionManagement(value = TransactionManagementType.CONTAINER)
                      @TransactionAttribute(value = TransactionAttributeType.NOT_SUPPORTED)
                      
                      • 8. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
                        firebet99 Newbie

                        Confirmed. My test class passes with those settings.

                        • 9. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
                          Justin Bertram Master

                          I believe I found the bug.  I've got a fix in my local branch.  I'll open a JIRA and send a pull-reqest soon to get this fixed on master.  Thanks for the heads-up.

                          • 10. Re: Transaction timeouts in MDB migration from JBoss 4.2.2 to 7.1.1-Final
                            firebet99 Newbie

                            Thanks Justin, glad I could help. Can you post JIRA details when available?