1 2 3 4 Previous Next 52 Replies Latest reply on Apr 7, 2008 6:29 AM by timfox

    Bug in transactional delivery in an MDB

    timfox

      I have been looking at http://jira.jboss.com/jira/browse/JBMESSAGING-721 and have uncovered a bug in transactional message delivery with MDBs.

      A message is received transactionally in the onMessage method of a MDB and the tx is marked rollback only, but the message is not redelivered.

      What is happening is this:

      1. JBoss Messaging receives message from destination (no tx at this point)

      2. JBM calls onMessage on the MDB container

      3. MDB container starts a global tx and enlists the session's xaresoource

      4. The user's onMessage executes

      5. The user set's rollback only

      6. The MDB container rolls back the transaction

      7. There is no redelivery since the message was received by JBM *before* the mdb container starts the transaction.

      This is a very well known issue and a result of a design flaw in the original JMS connection consumer design.

      It is well documented in Weston's favourite book ;), Mark Little's "Java Transaction processing, Chapter 5, section "applications server integration".

      Different app servers solve the problem in different ways.

      JBoss MQ, JBoss Messaging work by acting as a local transacted session when not in xa begin..end boundaries and then when XAResource.start is called, the work done in the local tx is converted into the work done in the new transaction (See MessagingXAResource.start)

      I have fixed this and added tests, however the above behaviour is incompatible with fixes Ovidiu did for:

      http://jira.jboss.com/jira/browse/JBMESSAGING-410

      (
      // leave the session in a 'clean' state, the currentTxId will be set when the XAResource will
      // be enrolled with a new transaction.

      setCurrentTransactionId(null);
      )

      Branch_1_0 revision 1317 (19/09/06) by Ovidiu which basically sets the current transaction id to null after a commit or rollback

      This breaks the MDB transactional delivery since because the current transaction id is set to null, there is nothing to convert.

      The problem here is that the desired behaviour for http://jira.jboss.com/jira/browse/JBMESSAGING-410 and for correct transactional delivery in MDBs seem to be fundamentally incompatible.

      For JBMessaging-410 - it wants an XASession to behave as non transacted when it is not enlisted in a global tx - but for correct MDB message delivery we want it to behave as a local session.

      My question is, is the requirement for JBMessaging-410 real?

      Weston - what should the correct JCA behaviour be here? Is JBMessaging-410 real or bogus and any ideas on how we can reconcile the two?

        • 1. Re: Bug in transactional delivery in an MDB
          weston.price

          I will take a look. Chances are one of us (either JCA or JBM) is getting in the way of each other.

          • 2. Re: Bug in transactional delivery in an MDB
            ovidiu.feodorov

            http://jira.jboss.com/jira/browse/JBMESSAGING-410 was reported by Elias after he noticed an incompatibility between the way JBossMQ and Messaging behave relative to a situation that is insufficiently specified. I took the decision to restore compatibility with JBossMQ, and with something that, personally, I believe it is the most intuitive behavior.

            I need to analyze the case you're talking about here a little bit better before coming up with a definitive(?) conclusion ...

            • 3. Re: Bug in transactional delivery in an MDB
              timfox

              Weston - what is the correct behaviour of the JCA JMS managed connection factory here?

              Just to recap:

              If I obtain a session from a connection created from the JCA JMS managed cf (i.e. the one normally at java:/jmsXA), and there is *no* JTA transaction associated with the current thread, and I receive a message, should the session act like a non transacted session and the message get acknowledged immediately, OR should it act like a transacted session? This is the key question.

              If it should act like a non transacted session, how can we reconcile this with transactional message receipt for MDBs?

              In a MDB the message is received *before* the MDB container has a chance to start a global tx, therefore it is received in a session where no JTA tx is associated with the current thread. In this case we must *not* ack it immediately, but we must let the session behave as a transacted session and later when the MDB container starts a JTA tx and enlists it, we can transfer the work done in the local tx into the global tx.

              Funnily enough - transferring the work into the JTA tx is exactly how JBoss MQ does it too, so I am puzzled as to how this behaviour is consistent with the behaviour of JCA without a JTA tx as Ovidiu reports. This is why I am trying to find out whether the supposed JCA behaviour is real or bogus.

              • 4. Re: Bug in transactional delivery in an MDB
                timfox
                • 5. Re: Bug in transactional delivery in an MDB
                  weston.price

                  In the latest version of the adapter (HEAD), the non-transactional context is handled by the JCA adapter using Local JMS transactions which was added to support the case where a Bean managed or CMT Not Supported MDB throws a Runtime Exception. Here the JMS and EJB specs differ as to how this should be treated. We had a long thread about this awhile ago when we were trying to address issues with the JBoss beta we were trying to get out the door.

                  Unfortunately, for this case (and many others) there is no 'correct' behavior as the spec is silent in this regard.

                  Note the behavior in HEAD is a complete rewrite from the way we originally handled this.

                  • 6. Re: Bug in transactional delivery in an MDB
                    timfox

                     

                    "weston.price@jboss.com" wrote:
                    In the latest version of the adapter (HEAD), the non-transactional context is handled by the JCA adapter using Local JMS transactions


                    Ok good, this is what I would expect, and is consistent with how transactional message delivery with MDBs works (convertion of work done outside the global tx into work done inside the global tx).

                    This means the behaviour expected in http://jira.jboss.com/jira/browse/JBMESSAGING-410 is not going to happen in HEAD anyway.

                    So I think we are safe to revert the changes in JBMESSAGING-410 and I can get the patch out ASAP.

                    Everyone agreed?

                    • 7. Re: Bug in transactional delivery in an MDB
                      weston.price

                      Lock and load.

                      • 8. Re: Bug in transactional delivery in an MDB
                        ovidiu.feodorov

                        Thinking about it, wouldn't be more logical the other way around: load and then lock?

                        Now, it what transactional behavior is concerned, would you guys please hold any major reverting decision for just a little bit, until I get to the problem (today or tomorrow)?

                        • 9. Re: Bug in transactional delivery in an MDB
                          weston.price

                          :-)

                          Yeah, I guess you are right...doesn't sound as cool though.

                          Guys, let me know if there is anything on the JCA side that I can clarify. Sounds like we are on the right track. Now, if we can just put a muzzle on Tim, we should be all set.

                          • 10. Re: Bug in transactional delivery in an MDB
                            ovidiu.feodorov

                            Counterintuitive as it sounds, "lock and load" it is actually technically correct:

                            On page 21 of the "M1 Garand Manual" the procedure for preparing the M1 Garand for firing is to "pull the operating rod handle to the rear until the bolt is securely LOCKED open". Then you load the clip. This indicates that first lock and then load is indeed the order of inserting a cartridge clip into the M1.

                            http://en.wikipedia.org/wiki/Lock_and_load

                            • 11. Re: Bug in transactional delivery in an MDB
                              timfox

                               

                              "ovidiu.feodorov@jboss.com" wrote:
                              Counterintuitive as it sounds, "lock and load" it is actually technically correct:

                              On page 21 of the "M1 Garand Manual" the procedure for preparing the M1 Garand for firing is to "pull the operating rod handle to the rear until the bolt is securely LOCKED open". Then you load the clip. This indicates that first lock and then load is indeed the order of inserting a cartridge clip into the M1.

                              http://en.wikipedia.org/wiki/Lock_and_load


                              Thanks for that.

                              Any chance of commenting on the transaction problem? ;)

                              • 12. Re: Bug in transactional delivery in an MDB
                                ovidiu.feodorov

                                Coming.

                                • 13. Re: Bug in transactional delivery in an MDB
                                  ovidiu.feodorov

                                  I spend a good part of the day today analyzing http://jira.jboss.com/jira/browse/JBMESSAGING-721
                                  and its implications (which include http://jira.jboss.org/jira/browse/JBMESSAGING-410
                                  and http://jira.jboss.org/jira/browse/JBMESSAGING-520)

                                  On one hand, the fixes for JBMESSAGING-410 and JBMESSAGING-520 insure that a JMS session created using a JMS connection produced by the JCA connection factory behaves as NON-TRANSACTED in absence of a global JTA transaction.

                                  This is an intuitive behavior, users rely on it, JBossMQ behaves similarly, and reportedly, other JMS providers as well.

                                  Unfortunately, the fix caused http://jira.jboss.com/jira/browse/JBMESSAGING-721. Reverting it would fix MDB redelivery problem, but it will break JBMESSAGING-410 and JBMESSAGING-520 again.

                                  At this moment, I am tempted to blame JCA and say that the fix for JBMESSAGING-410 and JBMESSAGING-520 belongs to the JCA layer. However, users don't see JCA, they see JBoss Messaging not working as expected. I haven't reached a definitive conclusion yet, I will continue thinking about this issue tomorrow.

                                  In the mean time, the fix for http://jira.jboss.org/jira/browse/JBMESSAGING-748 is badly needed at some production sites, so I will release a partial service pack (1.0.1.SP3) but not make it available for public consumption, pending a resolution on JBMESSAGING-721, which will be incorporated in 1.0.1.SP4.

                                  • 14. Re: Bug in transactional delivery in an MDB

                                     

                                    "ovidiu.feodorov@jboss.com" wrote:

                                    On one hand, the fixes for JBMESSAGING-410 and JBMESSAGING-520 insure that a JMS session created using a JMS connection produced by the JCA connection factory behaves as NON-TRANSACTED in absence of a global JTA transaction.

                                    This is an intuitive behavior, users rely on it, JBossMQ behaves similarly, and reportedly, other JMS providers as well.


                                    There is actually nothing in the spec about this behaviour.
                                    The XA stuff is massively underspecified in the JMS spec.
                                    And of course it is optional whether a JMS impl supports XA.

                                    The JBossMQ behaviour is to assume that an XASession behaves like
                                    AUTO_ACKNOWLEDGE when the XASession is not enlisted in a JTA transaction.
                                    (Some JMS implements throw an exception in this case).

                                    There is one exception to this. When the XASession is being used as part of
                                    a ServerSessionPool, the semantics need to be receive then enlist.
                                    So for this, the XASession behaves like there is a transaction, it will be told
                                    later what XID to use for the 2PC protocol.

                                    1 2 3 4 Previous Next