
Originally Posted by
mpoitras
Hi,
I want only the producer to be part of the same transaction as the regular code (which writes things to the database and such).To be clearer I want to be able to do something like:
save data A to database
send data A message to JMS
save data B to database
send data B message to JMS
commit (all the save data and send to JMS gets committed to the database)
You want XA to synchronize your data source and JMS transactions.

Originally Posted by
jplmelanson
What you want is not clear. Your consumer won't receive the message unless commited (if you use transactional session). You can't have a single commit to do both tx, that is the challenge and some patterns already address this.
@jplmelanson -- I am also interested in "transactional message producers" but I keep finding references to these magic "patterns" but rarely anything concrete. Here are the patterns I am considering. Am I missing something?
If you can't use XA, then you'll have to commit the two transactions separately, for example:
Code:
save data A to database
send data A message to JMS
save data B to database
send data B message to JMS
commit database
commit JMS
Now, you can either live with the fact that in case of JMS infrastructure failure, you might commit your database but fail to send the message, or you can modify your flow:
Code:
send COMMAND MESSAGE containing data A and B
receive command message in a transacted JMS session (async)
save data A to database
send data A message to JMS
save data B to database
send data B message to JMS
commit database
commit JMS
Now, if you commit the database, but JMS fails to send, then the whole JMS transaction will be rolled back and the command message will be re-delivered. Then you can re-process the command (you must implement the "idempotent receiver" pattern) and re-send the messages.
Yet another way is to change the flow so your message and data are stored in the same database, so there is only one transaction:
Code:
save data A to database
save data A message to database (using a message store)
save data B to database
save data B message to database (using a message store)
commit database
then in a non-transactional worker thread:
Code:
read message from database
send JMS message
delete from database
(Spring integration message-store backed queue should make this all transparent.)