21

I have a spring web app running on jboss that is currently configured to use the HibernateTransactionManager for db transactions and the JmsTransactionManager for jms. For jms we use Camel and ActiveMQ, our database is DB2. Within a transaction I need to write a number of records to the database and send two asynchronous jms messages. The jms messages are event notifications and I only want them to be sent if the database transaction commits.

I am willing to accept the risk of the communication with the broker failing after the jdbc transaction has already committed (and thus no messages sent but db committed) so I do not think I need proper XA.

I believe that what I need is "best efforts" transaction management using spring transaction synchronization.

The spring documentation sort of hints at the fact that spring will synchronize the two transactions and commit the jms transaction only after the jdbc transaction has been committed - but I don't think it is very clear. The spring documentation here http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#tx-resource-synchronization doesn't go into enough detail about how it works.

I have found a couple of other sources that say spring will do what I want including some javadoc below, and I have written some integration tests that also show it.

http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/jms/support/JmsAccessor.html#setSessionTransacted%28boolean%29 The javadoc on setSessionTransacted here sounds like exactly what I want.

From what I have seen I think creating the Camel JmsConfiguration with transacted set to true like this is enough:

<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
    <property name="connectionFactory" ref="pooledConnectionFactory"/>
    <property name="transacted" value="true"/>
    <property name="concurrentConsumers" value="10"/>
</bean>

However I need to convince someone I work with who is a bit skeptical and thinks that my integration test only works because of a poorly documented side effect rather than a intentional spring feature.

So my question is - Am I correct that spring can be relied upon to synchronize the transactions and always commit the jms transaction after the jdbc transaction or is that not something that I should rely on, and could you point me at any official documentation that says that clearly? And I guess in general is this a good approach to take or should we be managing these transactions in a different way?

Cœur
  • 37,241
  • 25
  • 195
  • 267
laurie
  • 265
  • 1
  • 2
  • 9
  • Hi there, have you got an answer to your question by now? – snowindy May 16 '13 at 11:31
  • Hi, no not really. I still haven't seen any really clear documentation which is what I wanted but we are now using it in production without any issues. – laurie May 16 '13 at 14:45

3 Answers3

3

This article might be of help Distributed transactions in Spring, with and without XA. I don't think it covers your case specifically - sending message + updating database.

gkamal
  • 20,777
  • 4
  • 60
  • 57
  • Thanks, I have read that article a couple of times. In the Best Efforts 1PC section they provide two examples of spring synchronization but in one they configure a TransactionAwareConnectionFactoryProxy and in the other a ChainedTransactionManager. If I do not need to do any additional configuration to get the same result then I would rather not. – laurie Feb 12 '12 at 12:14
1

Official Spring Boot repository contain JTA examples that combine JMS with JDBC based on Atomikos, Bitronix or Java EE server JBoss WildFly.

Additionally I also created few examples that are located in my Github repository. This contains also non-Spring Boot (pure Spring) example.

luboskrnac
  • 23,973
  • 10
  • 81
  • 92
0

If you are using Local transactions And the usecase is save to database and then send to jms

Then there could be three cases :

  1. Exception just after receiving(before DB and JMS)

No problem everything will be rolledback

  1. After saving to DB , we have exception

If there is an insert operation,there will be mutiple rows in DB due to retries.With each retry , an insert will be done.And for JMS , message will go to DeadLetterQueue

  1. After saving to DB and sending to JMS , we have an exception

    If there is an insert operation,there will be mutiple rows in DB due to retries.With each retry , an insert will be done.And for JMS , message will go to DeadLetterQueue

Now you dont want to use XA, so the solutions could be

1)Check If(message.getJmsRedelivered() {…}

If not , process it

If its redelivered , check if you processed it already

Check if the data is in database based on details in message

Note that re-deliveries are rare so , this check is also rare and there is no overhead

2)If your method is idempotent , then you dont need this check

And regarding XA , XA guarantees that message is delivered only once And synchronize the transaction across multiple resources

But with XA , you have overhead

So if you can manage without XA , it is preferable

Ruchi Saini
  • 301
  • 2
  • 5
  • I could not understand your 2 point. What I understood is If after saving to dB we have exception then dB will rollback and also the jms message will rollback. Is it correct? – Vishal Patel Jun 02 '20 at 16:50