Let's consider the following context:
2 spring integration channels, they are each in separate database transactions. At the end of the first transaction, a message is put into the second channel. In the first channel, elements are created in the database that is later consumed by the corresponding message that has been sent from the first channel to the second channel.
To make sure that the transaction from channel 1 is fully committed before the second channel is triggered our subclass of the JpaTransactionManager
is registering a TransactionSynchronization
in the prepareForCommit
method it overrides from the JpaTransactionManager
The flow (channel 1) looks like this:
- Do all the message processing and database handling
- Last step of the flow registers a
TransactionSynchronization
that does aMessageChannel.send
in theafterCommit
phase to send the message to channel 2
My understanding is that at the time the message is sent to the second channel (in afterCommit
) all changes that have been done in the database transaction of channel 1 are flushed and committed.
Now the second channel does some work (like an MQ PUT) and later updates an entry that was created in the first flow. We have now observed that the repository method returned no entry in the database, but it is visible in the table at a later point. Other entries that were also created in the transaction of the first channel however are visible. This happens only once every few thousand messages, normally they are there but sometimes they are not visible for the second channel a few milliseconds after the transaction has been committed by channel 1.
I have created an image that should illustrate it:
The Chain 1
is the first chain that consists of multiple ServiceActivators
that perform database work, a splitter that generates more messages and then another ServiceActivator
that I named SENDER
which registers the TransactionSynchronization
that (so my understanding) should send the for example 3 generated messages to chain 2 after the red transaction is fully committed and therefore before the blue transaction begins.
One thing I have noticed is that the entries that were sometimes present and sometimes not are all in the one method that (not on purpose) uses javax.transaction.Transactional
instead of org.springframework.transaction.annotation.Transactional
. However, we are using spring core 5.0.8.RELEASE and in other questions I have seen that this should make 0 difference since spring 4.2.x.