I'm hoping to discover if I am using the DataSourceTransactionManager in the proper way, as a base class to support long transactions that exist in our legacy system. Please don't tell me not to support long transactions across multiple requests, as this is not an option.
This class also must support a time out mechanism; we have a subscriber that relies on a timeout implemented in our current architecture.
My approach so far was to create a new Interface called SuspendablePlatformTransactionManager. (Perhaps this is not be the correct metaphor, since the original concept of transaction suspension, is to start a new transaction within the same workflow, and then resume the suspended transaction later down the line).
The interface extends PlatformTransactionManager and has two additional methods
This gives the hooks available to the caller (a Servlet in the simplest case) to suspend, and later resume, in another thread, the transaction.Code:package com.choicehotels.cis.infrastructure; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionStatus; public interface SuspendablePlatformTransactionManager extends PlatformTransactionManager { public DefaultTransactionStatus suspendTransaction(DefaultTransactionStatus status); public DefaultTransactionStatus resumeTransaction(DefaultTransactionStatus status); }
I then created an extension to the DataSourceTransactionManager that also implements the interface.
This class overrides doCommit, doRollback, doResume, doSuspend, and newTransactionStatus.
At first I misunderstood the suspension process, and thought the suspend would occur on the currently running transaction, but this is not the case.
It is the new transaction that has not "begun" yet that is the target in the doSuspend call.
This led to a problem, in my code that would cause an NPE upon resumption of the existing transaction, since I was suspending the existing transaction object (which removes the connection holder from the transaction object)
My workaround is to reattach the connection holder to the "suspended" transaction upon resumption, but I'm really hoping there is a better and more elegant way.
Attached is the relevant code if anyone is interested in offering suggestions or alternatives.
Thanks in advance
Dan Shaw


Reply With Quote
