Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreSpring Integration 2.2 introduces extended support for synchronizing non-transactional resources with transactions.
It is often used, for example, to synchronize a JMS commit with a JDBC commit.
Spring Integration has long supported this feature, by defining a <transactional/>
element on a poller. This release takes this feature one step further, by allowing synchronization of non-transactional resources with a transaction.
For example, consider a <file:inbound-channel-adapter/>
and an Integration application that reads a file when it appears in a directory, and updates a database. This feature allows us to configure different actions to be taken if the transaction commits or rolls back.
We will also show how these "post processing" actions can be configured to occur, even if there is not a real transactional resource involved.
The feature does NOT make an inherently non-transaction resource (such as a simple file system) transactional; rather, it simply allows us to synchronize file system (or other) activities with a transaction.
The fundamental component of the Spring transaction synchronization feature is an object that implements TransactionSynchronization
. Such an object has a number of callbacks that the framework invokes during synchronization (examples include afterCommit
, afterRollback
).
Spring Integration 2.2 introduces the concept of a TransactionSynchronizationFactory
. This factory is responsible for creating a TransactionSynchronization
object for each message. A default implementation is provided that allows the execution of SpEL expressions against the message as part of transaction synchronization.
Let's continue with the file system example. In order to enable transaction synchronization, we simply add a reference to a TransactionSynchronizationFactory
on the <transactional/>
element, and define a factory along with the SpEL expressions we wish to evaluate during transaction synchronization.
<int-file:inbound-channel-adaper ...>
<poller fixed-rate="1000">
<transactional synchronization-factory="syncFactory"/>
</poller>
</int-file:inbound-channel-adapter>
<int:transaction-synchronization-factory id="syncFactory">
<int:after-commit expression="payload.renameTo('/successful/' + payload.name" />
<int:after-rollback expression="payload.renameTo('/failed'/ + payload.name" />
</int:transaction-synchronization-factory>
As you can see, we rename the original inbound file, putting the file into a different directory, depending on whether the associated transaction commits or rolls back. Optionally, the result of the evaluation can be sent to a channel
defined using the 'channel' attribute on the child elements of the transaction-synchronization-factory.
(Note: The "before-commit" element is also available which can also be used to affect whether the commit is actually completed or not).
As can be seen above, we now have a convenient mechanism to perform some action before or after a transaction commits, or after it rolls back. But, what if we have a flow that does not involve a transactional resource at all? For example: file:inbound-adapter<-poller->transformer->ftp:outbound adapter
.
Let's say we want to rename the input file, depending on success or failure of the ftp file transfer of the transformed file. In order to accommodate this use case, we have introduced the PseudoTransactionManager
. This class implements PlatformTransactionManager
for the sole purpose of allowing the use of the above synchronization techniques, even if there is no real transaction involved. Simply add the <transactional/>
element as before, giving it a reference to a PseudoTransactionManager
(or use the default bean id of 'transactionManager').
With Spring Integration 2.2, users now have the ability to perform appropriate actions, normally affecting the original input source, after a flow completes (either successfully, or otherwise). This can be synchronized with a transaction on some other transactional resource, or even in cases where there is no real transaction involved.
A sample application exploring these features is provided here.