Uploaded image for project: 'Spring Framework'
  1. Spring Framework
  2. SPR-10829

spring-jms 3.0.4 introduces a change that breaks using JMSTemplate (and for that matter any JMS resource) with Oracle AQ when JMS Session are used in SESSION_TRANSACTED mode.

    Details

    • Type: Bug
    • Status: Closed
    • Priority: Major
    • Resolution: Complete
    • Affects Version/s: 3.0.4
    • Fix Version/s: 3.2.5, 4.0 RC1
    • Component/s: JMS
    • Labels:
      None
    • Last commented by a User:
      true

      Description

      Actually the problem just surfaced after the IllegalStateException from JMSResourceHolder.commitAll was thrown out instead of being swallowed. (See the linked ticket for details)

      In my use case we are using OracleAQ with JMS libraries, (high level operations done using spring-jms).
      We jave JPA transaction manager doing transaction management for us.
      In a sample transaction we insert/update/delete some JPA entities, and in the same transaction we also push some messages to an Oracle queue.

      Now, it is a requirement for us to ensure that the DML and the message production are atomic, hence they are made to use the same underlying oracle connection (read, using spring-data-oracle convenience xml namespace).

      To achieve this we have to use a transacted connection factory, and the JMS template that is used to push messages has to be made "sessionTransacted", this is done to avoid the JMSTemplate.send to commit the messages before the enclosing spring transaction commits. (In summary, JMSTemplate.send eventually reaches, session.commit or something alike that commits the underlying jdbc connection, thus, committing the normal DML operation as well).

      This is a typical use case. And everything works fine with spring-jms 3.0.2 ( and also with 3.0.3), and it works "by accident".
      By accident because, when eventually then enclosing spring (JPA) transaction commits, the transactional JMSResourceHolder also tries to commit the underlying JMS resources (triggered by transaction synchronization), which fails because for Oracle AQ, as soon as the underlying JDBC connection gets committed by the JPA transaction manager, all JMS resource are also committed and closed, so this JMSResourceHolder commit operation fails (something on the lines of IllegalStateException because session/consumer/producer is already closed). Again as mentioned in the beginning swallowing the IllegalStateException there saves us.

      In spring-jms 3.0.4 as the linked ticket provides details, this behavior was fixed, which broke things for Oracle AQ.

      I agree that swallowing that exception is not the proper fix here, but there is no way to instruct the JMS transaction framework to "not synchronize" JMS resources in case of Oracle AQ. The decision to synchronize JMS resources is done based on the sessionTransacted flag (this is for JMSTemplate, but the logic is more or less similar everywhere else), which unfortunately has to be set true to avoid committing by JMS framework.

      I believe sessionTransacted and transaction synchronization should be dealt separately. The reason I believe this logic exists is because unlike JDBC resources, there could be more than one JMS resource bound to a single transaction, so at the end all of these resources have to be synchronize with the transaction. But there may be cases where we don't want this behavior, as in my case.

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                juergen.hoeller Juergen Hoeller
                Reporter:
                rsanwal Ravi Sanwal
                Last updater:
                Spring Issuemaster
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Days since last comment:
                  47 weeks, 5 days ago