1 2 Previous Next 23 Replies Latest reply on Feb 10, 2012 3:15 AM by ataylor Go to original post
      • 15. Re: Messages redelivered after committed transaction
        mrpi

        Yea, we have two options now I suppose:

        1. Switch to JBoss
        2. Create our own TransactionManagerLocator and hook that up to Weblogc Transaction Manager

         

        We're working on both at the moment.

         

        Do you know anyone that has got MDB transaction management to work in a container that is not JBoss? Is this flaw documented somewhere?

        • 16. Re: Messages redelivered after committed transaction
          ataylor

          Do you know anyone that has got MDB transaction management to work in a container that is not JBoss?

          yeah, CMP should work fine if you dont throw an exception or implement TransactionManagerLocator

           

          Is this flaw documented somewhere?

          which flaw do you mean

          • 17. Re: Messages redelivered after committed transaction
            mrpi

            The flaw that MDB transactions won't work at all within a application server that is not JBoss.

            If you look at the catch-block  in HornetQMessageHandler.onMessage();

             

            catch (Throwable e)
            {
             HornetQMessageHandler.log.error("Failed to deliver message", e);
             // we need to call before/afterDelivery as a pair
             if (beforeDelivery)
             {
                if (useXA && tm != null)
                {
                   // This is the job for the container,
                   // however if the container throws an exception because of some other errors,
                   // there are situations where the container is not setting the rollback only
                   // this is to avoid a scenario where afterDelivery would kick in
                   try
                   {
                      Transaction tx = tm.getTransaction();
                      if (tx != null)
                      {
                         tx.setRollbackOnly();
                      }
                   }
                   catch (Exception e1)
                   {
                      log.warn("unnable to clear the transaction", e1);
                      try
                      {
                         session.rollback();
                      }
                      catch (HornetQException e2)
                      {
                         log.warn("Unable to rollback", e2);
                         return;
                      }
                   }
                }
            
                try
                {
                   endpoint.afterDelivery();
                }
                catch (ResourceException e1)
                {
                   HornetQMessageHandler.log.warn("Unable to call after delivery", e);
                }
             }
             if (useLocalTx || !activation.isDeliveryTransacted())
             {
                try
                {
                   session.rollback(true);
                }
                catch (HornetQException e1)
                {
                   HornetQMessageHandler.log.warn("Unable to roll local transaction back");
                }
             }
            }
            

             

            The only place where a rollback will be performed is if the following statement is fulfilled:

             

                if (useXA && tm != null)
            

             

            In my head that means that if you use a application server other than JBoss you HAVE to create YOUR OWN TransactionManagerLocator AND change the ra.xml-configuration to to be able to use rollback functionality, right?

            This is definitely not trivial and I would very much like to call that a flaw.

             

            We are three people here that have spent two full days on this without getting MDB transactions to work as we want it to.

            • 18. Re: Messages redelivered after committed transaction
              ataylor

              In my head that means that if you use a application server other than JBoss you HAVE to create YOUR OWN TransactionManagerLocator AND change the ra.xml-configuration to to be able to use rollback functionality, right?

              This is definitely not trivial and I would very much like to call that a flaw.

              I disagree, this is not a flaw, its as the J2EE spec, useXA = true when CMT is used, useXA = false when  BMT is used dont use xa. The piece of code is also just belt and braces for some scenarios where jboss doesnt set rollback only on the tx.

               

              So according to the spec if you are using BMP, once the onMessage has been called then the message is considered consumed.

               

              If CMT is used then the session will be xa and enlisted with the tx, the tx will then rollback or commit. If this doesnt happen then its an issue with weblogic.

               

              Alternatively if the onMessage throws an unchecked exception, then we make our best efforts to try and deal with it, altho we can only do this with access to the transaction manager, hence the transactionmanagerlocatorclass. MDB's that do this however are badly behaved and the spec doesnt actually specify what should happen. A well behaved MDB should catch exceptions and set rollbackonly on the messagedrivencontext if cmt or on the usertransaction if bmt.

               

              btw, this code has been run against the TCK test suite and passes fine, trust me, if their was a flaw the test TCK would find it.

               

              Andy

               

              btw writing a TransactionManagerLocatorclass would be trivial, probably 2-3 lines of code

              • 19. Re: Messages redelivered after committed transaction
                jbertram

                To follow up on what Andy said...

                 

                According to the JMS 1.1 specification (section 4.5.2) it isn't appropriate to throw a RuntimeException from onMessage():

                A client can register an object that implements the JMS MessageListener interface with a MessageConsumer. As messages arrive for the consumer, the provider delivers them by calling the listener’s onMessage method.

                 

                It is possible for a listener to throw a RuntimeException; however, this is considered a client programming error. Well-behaved listeners should catch such exceptions and attempt to divert messages causing them to some form of application-specific 'unprocessable message' destination.

                Furthermore, section 5.4.17 of the EJB 3 spec states:

                Message-driven beans should not, in general, throw RuntimeExceptions.

                 

                A RuntimeException that is not an application exception thrown from any method of the message-driven bean class (including a message listener method and the callbacks invoked by the container) results in the transition to the “does not exist” state.

                In other words, the container has to trash the MDB instance and create a new one if a RuntimeException is thrown from the onMessage method.  This is not something you should be doing to roll back the transaction as Andy said.

                • 20. Re: Messages redelivered after committed transaction
                  ataylor

                  btw we are always in the IRC channel if you ever want to chat more about this stuff, we would be happy to help

                  • 21. Re: Messages redelivered after committed transaction
                    mrpi

                    Thank's for all the help! I think we found a solution now.

                     

                    We cannot use BMT with HornetQ and Weblogic. It simple does not work as it is supposed to. We even created our own TransactionManagerLocator to make the HornetQ JCA adapter get a hold of the TransactionManager in Weblogic. Did not help.

                    Instead we tried to use CMT (using MessageDrivenContext as I believe you guys suggested at some point in time) and now everything works like a charm.

                     

                    Thanks to Justin for pointing out the JMS and EJB3 specifications. Nobody here knew that you're not supposed to throw RuntimeExceptions from the onMessage() method.

                    In school 7 or 8 years ago I learned that when using EJB's with a database you're supposed to:

                    1. Call some kind of a rollback()-method if using BMT
                    2. Throw and exception to make the container roll back the transaction for you if using CMT

                     

                    That is what we all learned! But as the specification says, you are no longer supposed to throw any kind of exception.

                    No one here had heard about the MessageDrivenContext, so we did not know that you could use that in combination with CMT to make transactions work.

                     

                    I guess we should go buy some books, huh? =)

                    • 22. Re: Messages redelivered after committed transaction
                      mrpi

                      Btw, which IRC server do you use and in what channel do you usually hang out? =)

                      • 23. Re: Messages redelivered after committed transaction
                        ataylor

                        We cannot use BMT with HornetQ and Weblogic. It simple does not work as it is supposed to

                        It works exactly like it is supposed too, remember  when using BMT the consumption of the message is *NOT* part of the transaction

                        Istead we tried to use CMT (using MessageDrivenContext as I believe you guys suggested at some point in time) and now everything works like a charm.

                        Good Stuff

                        I guess we should go buy some books, huh? =)

                        Maybe I should write on

                         

                        Btw, which IRC server do you use and in what channel do you usually hang out? =)

                        #hornetq on freenode, theres usually someone their from the team, either myself, Justin, Clebert, Howard (ghoward) or Francisco (fborges), feel free to join at anytime.

                        1 2 Previous Next