The following issue was discovered while doing some work with hibernate, but it boils down to the following scenario:
1. start a transaction
2. create a prepared statement (and keep a reference to it for later use)
3. execute the statement
4. suspend the transaction
5. resume the transaction
6. execute the prepared statement a second time
By doing some debugging I saw that suspend will call xaresource.end(tmsuccess) for all resources in the transaction, but resume won’t start them again. (probably because they will be lazily started with a tmjoin later when they are used – via JdbcConnectionHandle)
But in this case, the second execution of that prepared statement is not “intercepted” by bitronix, and it will execute on a connection that was previously ended. From my observations results may vary: sometimes the statement execution just blocks, other times it is successful but done in a new transaction.
I did a wild guess :) and added the following line:
in XAResourceManager# resume() right before the end of the loop and things seem to work, but I really don’t know if it’s the right thing to do.
Strictly speaking this isn't a bug but a limitation of the current connection pool but I agree the result is the same: it does not work as you expect it to.
Your patch is just going to work in this exact situation and only if the underlying database properly supports transaction joining. I've searched for the best way to cope with that problem and the only proper way is to wrap the driver's Statement / PreparedStatement / CallableStatement objects and trigger enlistment from there which is quite a serious change.
A simpler (but largely less elegant) fix XAResourceManager#resume() could re-enlist the resource. This isn't as easy as it sounds as some logic to check if TMJOIN is disabled or not must be added and some internal safeguards must be relaxed.
I'll try to build a patched version with those changes in over the weekend, I'd be glad if you could open an issue in JIRA in the meantime.
Sorry for my delayed response, finally I was able to try the fix.
I did find a problem:
The XAResourceManager#resume method iterates over resources (type Scheduler) and in the same time the enlist method will remove and add objects into the resources collection (a case of concurrent modification).
In my particular case, I had two resources to be resumed and only one of them got re-enlisted. The iterator from the resume method returned twice the same object.