jms-spec
  1. jms-spec
  2. JMS_SPEC-28

Clarify how the JMS provider should interact with Transaction Managers.

    Details

    • Type: Improvement Improvement
    • Status: Open
    • Priority: Critical Critical
    • Resolution: Unresolved
    • Affects Version/s: 1.1
    • Fix Version/s: None
    • Labels:
      None

      Description

      Clarify how the JMS provider should interact with Transaction Managers. In particular, the responsibilities of the JMS Provider, the TM and the App Server during recovery need to be clearly defined.

      (This issue is a placeholder. More information about the ambiguities that need to be resolved will be added later)

        Activity

        Hide
        cptmauli added a comment -

        Please provide a way to specify explicitly when a JMS Message is sent.

        Current situation (for instance JBoss 6, but others have the same problem):

        • a method updates the database and sends a JMS message (transactional)
        • the message is received and the same record is read from the database, but it will often still read the state before the update

        Cause:

        the JMS message is sent when the transaction manager decides that the commit is valid. That doesn't mean the actual database commit is now visible! This hurt us badly and we had to use the TransactionSynchronizationRegistry to work around this issue.

        Solution:

        The ideal solution would be if I could define the way when the message should be sent, I also would like to see that even beeing within a Transaction that I have the means to send a message non-transactional. Further it also should provide a way to send a message if a rollback occurs. A enum in the send method would be nice, something like NON_TRANSACTIONAL, DEFAULT, ON_COMMIT, ON_ROLLBACK, AFTER_COMMIT.

        Show
        cptmauli added a comment - Please provide a way to specify explicitly when a JMS Message is sent. Current situation (for instance JBoss 6, but others have the same problem): a method updates the database and sends a JMS message (transactional) the message is received and the same record is read from the database, but it will often still read the state before the update Cause: the JMS message is sent when the transaction manager decides that the commit is valid. That doesn't mean the actual database commit is now visible! This hurt us badly and we had to use the TransactionSynchronizationRegistry to work around this issue. Solution: The ideal solution would be if I could define the way when the message should be sent, I also would like to see that even beeing within a Transaction that I have the means to send a message non-transactional. Further it also should provide a way to send a message if a rollback occurs. A enum in the send method would be nice, something like NON_TRANSACTIONAL, DEFAULT, ON_COMMIT, ON_ROLLBACK, AFTER_COMMIT.
        Hide
        Nigel Deakin added a comment - - edited

        Can you explain the issue in more detail? You write

        > the JMS message is sent when the transaction manager decides that the commit is valid.

        It's up to the JMS provider to decide when to actually send the message from the producing client to the JMS server. It's fine to sent it immediately (when the application calls MessageProducer.send()). When the JMS server receives the message it can add it to the queue or topic but (assuming we're in a Java EE transaction) must not commit the operation.

        > That doesn't mean the actual database commit is now visible!

        When the transaction on the client is committed, the transaction manager will call commit() on the XAResource object provided by the JMS client. The JMS client will send the commit to the JMS server which will then commit the previous addition of the message to the queue or topic. The message will then become available for delivery to consumers.

        > This hurt us badly and we had to use the TransactionSynchronizationRegistry to work around this issue.

        Please provide more information to allow us to understand the problem.

        Show
        Nigel Deakin added a comment - - edited Can you explain the issue in more detail? You write > the JMS message is sent when the transaction manager decides that the commit is valid. It's up to the JMS provider to decide when to actually send the message from the producing client to the JMS server. It's fine to sent it immediately (when the application calls MessageProducer.send()). When the JMS server receives the message it can add it to the queue or topic but (assuming we're in a Java EE transaction) must not commit the operation. > That doesn't mean the actual database commit is now visible! When the transaction on the client is committed, the transaction manager will call commit() on the XAResource object provided by the JMS client. The JMS client will send the commit to the JMS server which will then commit the previous addition of the message to the queue or topic. The message will then become available for delivery to consumers. > This hurt us badly and we had to use the TransactionSynchronizationRegistry to work around this issue. Please provide more information to allow us to understand the problem.
        Hide
        Leos.Bitto added a comment -

        > When the transaction on the client is committed, the transaction manager will call commit() on the XAResource object provided by the JMS client. The JMS client will send the commit to the JMS server which will then commit the previous addition of the message to the queue or topic. The message will then become available for delivery to consumers.

        The problem is that after the message becomes available for delivery to the consumers, some consumer might start processing it and find old information in the database (for some record(s) identified by the data in the JMS message), because the commit() on the relevant database XAResource has not been processed yet (because it is processed after commit() of the JMS XAResource).

        Some transaction managers allow ordering of the calls to commit() of the XAResources enlisted in the transaction, but this is an optional extenstion which is not required by JTA. See http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/5/html/Transactions_Development_Guide/chap-Transactions_JTA_Programmers_Guide-Test.html#form-Transactions_JTA_Programmers_Guide-The_XAResource_Interface-Extended_XAResource_control for example. With the TransactionManager implementation from JBoss the possible workaround is to use the JMS XAResource wrapper which implements com.arjuna.ats.jta.resources.EndXAResource and therefore ensures that when the JMS message is sent, all the relevant database operations are already committed.

        I am not sure whether this can be solved in JMS 2.0 only, though. It seems that this would require some cooperation from the JTA specification as well.

        Show
        Leos.Bitto added a comment - > When the transaction on the client is committed, the transaction manager will call commit() on the XAResource object provided by the JMS client. The JMS client will send the commit to the JMS server which will then commit the previous addition of the message to the queue or topic. The message will then become available for delivery to consumers. The problem is that after the message becomes available for delivery to the consumers, some consumer might start processing it and find old information in the database (for some record(s) identified by the data in the JMS message), because the commit() on the relevant database XAResource has not been processed yet (because it is processed after commit() of the JMS XAResource). Some transaction managers allow ordering of the calls to commit() of the XAResources enlisted in the transaction, but this is an optional extenstion which is not required by JTA. See http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/5/html/Transactions_Development_Guide/chap-Transactions_JTA_Programmers_Guide-Test.html#form-Transactions_JTA_Programmers_Guide-The_XAResource_Interface-Extended_XAResource_control for example. With the TransactionManager implementation from JBoss the possible workaround is to use the JMS XAResource wrapper which implements com.arjuna.ats.jta.resources.EndXAResource and therefore ensures that when the JMS message is sent, all the relevant database operations are already committed. I am not sure whether this can be solved in JMS 2.0 only, though. It seems that this would require some cooperation from the JTA specification as well.
        Hide
        Nigel Deakin added a comment - - edited

        > The problem is that after the message becomes available for delivery to the consumers,
        > some consumer might start processing it and find old information in the database
        > (for some record(s) identified by the data in the JMS message),
        > because the commit() on the relevant database XAResource has not been processed yet
        > (because it is processed after commit() of the JMS XAResource).

        The commit won't happen until onMessage() has returned, so how does the order in which the two resources in the transaction are committed make any difference?

        Show
        Nigel Deakin added a comment - - edited > The problem is that after the message becomes available for delivery to the consumers, > some consumer might start processing it and find old information in the database > (for some record(s) identified by the data in the JMS message), > because the commit() on the relevant database XAResource has not been processed yet > (because it is processed after commit() of the JMS XAResource). The commit won't happen until onMessage() has returned, so how does the order in which the two resources in the transaction are committed make any difference?
        Hide
        Leos.Bitto added a comment - - edited

        1. onMessage() is called for processing of the JMS message #1
        2. in onMessage() some data is updated in the database, based on the identification of this data from the JMS message #1
        3. in onMessage() a JMS message #2 is sent, including the the identification (only a key, not the whole data) of the modified data in the database
        4. onMessage() returns
        5. XAResource#prepare is called for both the JDBC and JMS XAResources (the order is irrelevant)
        6. XAResource#commit is called for the JMS XAResource, which removes the JMS message #1 from its queue, and sends the JMS message #2 to another queue
        7. onMessage() is called in another thread for processing of the JMS message #2
        8. data from the database is read, based on the data in the JMS message #2
        9. problem is here - old data is read from the database!
        10. in the original thread, XAResource#commit is called for the JDBC XAResource, which persists the updated data in the database, but it is too late now - another thread read wrong data already

        Show
        Leos.Bitto added a comment - - edited 1. onMessage() is called for processing of the JMS message #1 2. in onMessage() some data is updated in the database, based on the identification of this data from the JMS message #1 3. in onMessage() a JMS message #2 is sent, including the the identification (only a key, not the whole data) of the modified data in the database 4. onMessage() returns 5. XAResource#prepare is called for both the JDBC and JMS XAResources (the order is irrelevant) 6. XAResource#commit is called for the JMS XAResource, which removes the JMS message #1 from its queue, and sends the JMS message #2 to another queue 7. onMessage() is called in another thread for processing of the JMS message #2 8. data from the database is read, based on the data in the JMS message #2 9. problem is here - old data is read from the database! 10. in the original thread, XAResource#commit is called for the JDBC XAResource, which persists the updated data in the database, but it is too late now - another thread read wrong data already
        Hide
        Nigel Deakin added a comment -

        I understand now. Thanks for the clarification.

        This seems to be a general issue with the two-phase commit of two resources, where the updates to one resource are dependent on the updates to the other. As you suggested, this doesn't sound like something that can be tackled at the level of an individual resource manager such as JMS. It might be worth raising it with the Java EE 7 Platform Expert Group.

        Show
        Nigel Deakin added a comment - I understand now. Thanks for the clarification. This seems to be a general issue with the two-phase commit of two resources, where the updates to one resource are dependent on the updates to the other. As you suggested, this doesn't sound like something that can be tackled at the level of an individual resource manager such as JMS. It might be worth raising it with the Java EE 7 Platform Expert Group .
        Hide
        Leos.Bitto added a comment -

        I am not sure whether this is the proper way of raising it, but here you are: http://java.net/jira/browse/JAVAEE_SPEC-1

        Show
        Leos.Bitto added a comment - I am not sure whether this is the proper way of raising it, but here you are: http://java.net/jira/browse/JAVAEE_SPEC-1
        Hide
        Nigel Deakin added a comment - - edited

        That seems a good way to start (I note this is the first issue!).

        I'll ping the Java EE spec leads to check they see it.

        Any discussions on this will be automatically copied to, or take place on, the users' mailing list for that project so I would suggest subscribing there if you want to follow this up.

        Show
        Nigel Deakin added a comment - - edited That seems a good way to start (I note this is the first issue!). I'll ping the Java EE spec leads to check they see it. Any discussions on this will be automatically copied to, or take place on, the users' mailing list for that project so I would suggest subscribing there if you want to follow this up.

          People

          • Assignee:
            Unassigned
            Reporter:
            Nigel Deakin
          • Votes:
            1 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated: