|
Juergen, I think it can be related to the fact that JBoss doesn't seems to delist (call XAResource.end(xid, TMSUSPEND)) resources on TransactionManager.suspend() call, at least that't what they say in documentation: Actually, the same problem could be reproduced with this simple test (I beliebe that's exactly what's happening in Spring?): ================================================================== userTransaction.begin(); Connection connection = dataSource.getConnection(); doSmth(connection, "A"); // suspend // start another transaction doSmth(connection, "B"); userTransaction.rollback(); // resume first tx userTransaction.commit(); The result is 2 records in the table! This is indeed odd. However, it doesn't surprise me on JBoss: I recently had an issue in a project where JBoss did not enlist resources in a new transaction if you fetched the resources before transaction begin - at least not for more than one transaction. No suspension there, just a single Connection supposed to be used for multiple subsequent transactions. Not sure whether that still doesn't work on JBoss 4, but it's kind of consistent if transaction suspension doesn't work on the same Connection either then. I guess the only way to make this work on JBoss is to fetch the Connections only during the respective current transaction. So if your subtransaction would fetch a new Connection and perform its work on that, I suppose it would execute correctly. Juergen Juergen, I have opened a bug for JBoss, and it's been rejected, details are here: http://jira.jboss.com/jira/browse/JBAS-2080 Looks like JBoss guys thinks that this is correct behavior as per spec (which is indeed says that TransactionManager.suspend() just de-associates thread with transactional context without sending any commands to XAResources participating). What bothers me (again) is that Spring doesn't give you any warning that this is happening. Expected behaviour is not consistent across app. servers. Do you think it can be done better??? Does this mean that passing along a Connection doesn't work with JBoss EJB CMT RequiresNew either? I assume that JBoss EJB CMT just performs a TransactionManager.suspend() call as well... Do you have a chance to give that a try? I'm afraid we can't do much about that from the Spring side of things. Spring simply doesn't know whether TransactionManager.suspend() performs a full delistment of all resources as well. It can only assume that full delistment happened... Would it work for you to simply fetch a new Connection for every subtransaction, relying on DataSource.getConnection()? That should correctly work in JBoss as well, and is generally the recommended usage pattern. Juergen I realize that I can fetch fresh Connection in every (sub) transaction, and personally I always doing just that. This is not my use case but rather ongoing experiments with TransactionManager functionality in different containers. There is nothing wrong with passing Connection over tx boundaries, nothing in the spec is prohibiting this. I still think that even if Spring (obviously) cannot recover from this problem, it may know that such problem exists in certain containers and at least print warning, say on initialization time when there are proxies with REQUIRES_NEW or NOT_SUPPORTED defined in context being loaded and it runs under JBoss? That would lead to much nicer user experience for framework which suppose to 'simplify J2EE'. Don't you agree? Otherwise users could spend long time trying to understand why their transactions doesn't work as they should and would be left with a bad taste in their mouth even there is nothing really to blame Spring for. Same results when using Session Beans/CMT in JBoss Verified to be general JBoss behavior and thus a JBoss issue. Spring on JBoss is consistent with JBoss EJB CMT in that respect. JBoss's TransactionManager unfortunately doesn't deliver the resource enlistment/delistment semantics that one would expect here. Juergen |
|||||||||||||||||||||||||||||||||||||||||||
Test Case