4 Replies Latest reply on Aug 20, 2013 2:42 AM by pacodelucia

    Transaction Synchronization and MDBs

    pacodelucia

      Hi

       

      Not sure if this is the right place to ask. It's more a general question regarding transaction handling in a JEE-Container and MessageDrivenBeans.

       

      Let's assume an EJB writes to a database and to a JMS queue. This is done inside a XA-Transaction. An MDB is reading the messages written to the queue and relies on the data written to the database before.

       

      What is clear:

      - The transaction the MDB is running in (if there is any) is not related at all to the first XA-Transaction. A transaction context is not passed with a message.

      - XA guarantees that the the data is written to the database AND the queue or in case of a failure to neither of them. (ok, there can still occure some heuristic exception and so, but generally this should not happen)

       

      Within the two-phase-commit protocol first the prepare-statement is sent. DB and queue respond with ok (or something like this) and then the Transaction Manager sends the commit command. If everything is fine the resource manager from database and queue send an acknowledge message.

       

      Now to the question: The acknowledge messages may take some time to get from the resource managesr to the transaction manager. And also the commit message may take some time to get from the transaction manager to the resource manager. It might be that the queue commit is done before the database commit. So the question is: When is the onMessage() method called in the MDB? Right after the queue commit is done? Or does the Container wait until the acknowledge messages from both resource managers (db and queue) are received before invoking onMessage()?

       

      So is this behaviour defined somewhere? I observed that the database was always up-to-date when accessing it from the MDB and when I consumed the message from the same queue. However it did not work anymore when I started using a divert that diverted the message to a second queue and the reading from this second queue. Several times I had the problem that the data was not in the database yet. This is either a timing issue or the container in this case does not wait because he doesn't know that the first queue is related to the second queue (because this is on a remote hornet queue server). Of course a solution could be to use a message delay (that's what I did).

       

      So my question is more a theoretical one. I don't really need a solution.

       

      I searched several specifications like EJB, JTA, JTS, etc. for an explanation but could not find anything. Hopefully someone can help here..

       

      Regards

      Oliver

        • 1. Re: Transaction Synchronization and MDBs
          ataylor

          Now to the question: The acknowledge messages may take some time to get from the resource managesr to the transaction manager. And also the commit message may take some time to get from the transaction manager to the resource manager. It might be that the queue commit is done before the database commit. So the question is: When is the onMessage() method called in the MDB? Right after the queue commit is done? Or does the Container wait until the commit from both resource managers (db and queue) are received before invoking onMessage()?

          Im not really sure what you are asking here but basically this happens.

           

          1. The MDB's session is enlisted with the current tx via the tm

          2  The onMessage is called

          3. The tm calls prepare() on each resource

          4. The tm calls commit() on each resource

           

          3 and 4 are both blocking calls

          So is this behaviour defined somewhere? I observed that the database was always up-to-date when accessing it from the MDB and when I consumed the message from the same queue. However it did not work anymore when I started using a divert that diverted the message to a second queue and the reading from this second queue. Several times I had the problem that the data was not in the database yet. This is either a timing issue or the container in this case does not wait because he doesn't know that the first queue is related to the second queue (because this is on a remote hornet queue server). Of course a solution could be to use a message delay (that's what I did).

          If you mean accessing the database record that hasnt been committed from within the onMessage then this can't happen, it will be committed after the onMessage method has completed.

           

          I think what you are talking about here is tx ordering, each resource will be committed separately so if the message is commited first and you have some logic that consumes this message and looks in the db then its likely that the data wont be there. This works as expected, you should design your app not to depend on ordering of commits (unless you can specify the order).

          • 2. Re: Transaction Synchronization and MDBs
            pacodelucia

            Hi Andy

             

            Thanks for your response. I think I haven't explained the problem clear enough. The MDB is actually accessing data that is written in the XA-Transaction. The MDB doesn't write data itself.

             

            1. Bean B1 uses Container managed transaction.

            2. Someone calls method doSomething() in B1. A new transaction is started.

            3. Bean B1 writes a Record R1 to the database

            4. Bean B1 writes (in the same method) a Message M1 to the Queue Q1

            5. The method exits and the (XA) transaction is committed by the container.

             

            I understand that I cannot know which transaction finished first. It could be the db or the queue.

             

            Now onMessage() is invoked from the Container:

            1. The MDB uses Container managed Transaction, so a new transaction is started.

            2. in the onMessage() method the MDB tries to read the record r1 that was written before (as described above in the EJB).

             

             

            The point is that I have the impression that somehow the JEE-Container (which is a kind of transaction monitor) does not invoke the onMessage() method until he gets both acknowledge messages. This would be possible theoretically. The container could stop devlivering message to MDBs while there are new messages written to it. The question is, if something like this is actually done.

             

            Thanks and regards

            Oliver

            • 3. Re: Transaction Synchronization and MDBs
              ataylor

              The point is that I have the impression that somehow the JEE-Container (which is a kind of transaction monitor) does not invoke the onMessage() method until he gets both acknowledge messages. This would be possible theoretically. The container could stop devlivering message to MDBs while there are new messages written to it. The question is, if something like this is actually done.

              Ok so the onMessage is in no way cocnnected to the xa transaction in the bean B1, it has no knowledge of it. basically when the Bean B1's commits the JMS branch of the transaction the message is from that point on the queue and available to the MDB, whether or not the database part of the tx has been committed is completely unrelated.

              • 4. Re: Transaction Synchronization and MDBs
                pacodelucia

                OK. thanks. In this case I was just lucky when it worked and it does not have to do with wether I consume from a diverted queue or not.

                Thanks!

                Regards

                Oliver