Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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. [SPR-10829] #15455

Closed
spring-issuemaster opened this issue Aug 13, 2013 · 4 comments
Assignees
Milestone

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Aug 13, 2013

Ravi Sanwal opened SPR-10829 and commented

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.


Affects: 3.0.4

Issue Links:

  • #12018 JmsResourceHolder.commit should not ignores IllegalStateException
  • #16412 SPR-10829: Spring JMS problem with Oracle AQ still exists if underlying DataSource is decorated

Referenced from: commits 26e697b, 11d20e3

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Aug 13, 2013

Ravi Sanwal commented

Gosh, I can't find how to link to another issue, the linked issue I mentioned in the description is https://jira.springsource.org/browse/SPR-7360

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 26, 2013

Juergen Hoeller commented

After considering the various options, I went with a built-in approach. In case of an IllegalStateException on commit, we're checking for the existence of a "getDataSource()" method on the ConnectionFactory now: If found, we'll obtain the associated DataSource and check for its participation in the current Spring transaction - in which case we'll silently swallow the JMS commit exception. This should work fine on Oracle AQ, since AQjmsConnectionFactory does have a corresponding "getDataSource()" method, and is an easy enough pattern to comply with for other JDBC-based ConnectionFactory references as well.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 27, 2013

Ravi Sanwal commented

I don't know how to close this ticket.
This change works fine and the ticket can be closed.

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented May 15, 2014

Ravi Sanwal commented

This issue seems to be not fixed. Sorry about the previous comment.
#16412 created with more details and a fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.