Hi,
I recently posted the following to the Spring Support Forum. I wondered
if you Geronimo guys would be interested too. I solved the issue by
using the JOTM transaction manager, it worked immediately with no
problems. - I do need to use Jencks though for its pooled managed
connection classes so it would be nice to use the geronimo transaction
manager to keep from using so many different packages...
Is the behaviour here compliant, or is is a spring misinterpretation?
Thanks!
James
--------------------------------
Hi there,
Would really appreciate a little bit of direction on a problem that has
completely got me stuck.
I'm trying to implement Jencks, ActiveMQ, and Hibernate using the Spring
HibernateTemplate. I have successfully got activemq delivering messages
to the application.
However, when rolling back the transactionmanager's transaction, only
the activemq transaction seems to be rolled back, not the hibernate one.
Having spent quite some time looking at this, I find the following
behaviour:
I realise that there is a two-phase commit process happening, but am
seeing something that doesn't quite seem to look right. Perhaps this is
a red herring...
Within a JCA transaction, I call rollback() or setRollbackOnly().
Eventually the thread's stack looks like this:
beforeCommit (SpringSessionSynchronization)
beforeCompletion (SessionFactoryUtils$StateSessionSynchronization)
beforeCompletion (SessionFactoryUtils$JtaSessionSynchronization)
beforeCompletion (org.apache.geronimo.transaction.manager.Transacti onImpl)
rollback (org.apache.geronimo.transaction.manager.Transacti onManagerImpl)
So, it looks like on a rollback(), the beforeCompletion() method is
being called... Geronimo is doing this. Is it doing the right thing?
Thanks for any help!
James
---------------------------------
Without posting all the configuration - which is a little complex to
extract (but can do later if needs be) - it seems that the comments in
the SessionFactoryUtils$JtaSessionSynchronization do not match up with
observed behaviour. I'm wondering if this is why the hibernate session
gets committed, when the transaction is in rollback mode.
I wrote a little testcase to show how what happens when the transaction
is rolled back, and can't match this up with the Spring behaviour. I am
not an expert on any of this by a long way - so may be missing the point
completely.
So I guess I'm asking, does this seem like a misconfiguration on my part
- or does it look like a bug (either in spring or geronimo)?
Thanks once again.
James
From [B]SessionFactoryUtils$JtaSessionSynchronization[/B]
[code]
/**
* JTA beforeCompletion callback: just invoked on commit.
* <p>In case of an exception, the JTA transaction gets set to
rollback-only.
* (Synchronization.beforeCompletion is not supposed to throw an
exception.)
* @see SpringSessionSynchronization#beforeCommit
*/
public void beforeCompletion() {
try {
boolean readOnly =
TransactionSynchronizationManager.isCurrentTransactionReadOnly();
this.springSessionSynchronization.beforeCommit(readOnly);
}
catch (Throwable ex) {
logger.error("beforeCommit callback threw exception", ex);
try {
this.jtaTransactionManager.setRollbackOnly();
}
catch (SystemException ex2) {
logger.error("Could not set JTA transaction
rollback-only", ex2);
}
}
// Unbind the SessionHolder from the thread early, to avoid
issues
// with strict JTA implementations that issue warnings when
doing JDBC
// operations after transaction completion (e.g.
Connection.getWarnings).
this.beforeCompletionCalled = true;
this.springSessionSynchronization.beforeCompletion();
}
[/code]
[B]Testcase [/B]
[code]
public void testFindOutHowSynchronizationWorks() throws Exception {
final GeronimoTransactionManager transactionManager =
createTxManager();
transactionManager.begin();
Transaction transaction = transactionManager.getTransaction();
transaction.registerSynchronization(new Synchronization() {
public void beforeCompletion() {
System.out.println("HibernateTransactionsTest.beforeCompletion");
printStatus(transactionManager);
}
public void afterCompletion(int i) {
System.out.println("HibernateTransactionsTest.afterCompletion");
printStatus(transactionManager);
}
});
transactionManager.rollback();
}
private void printStatus(TransactionManager transactionManager) {
int status = 0;
try {
status = transactionManager.getTransaction().getStatus();
} catch (SystemException e) {
System.out.println("???" + e.toString());
}
switch (status) {
case Status.STATUS_ACTIVE:
System.out.println("active");
break;
case Status.STATUS_ROLLEDBACK:
case Status.STATUS_ROLLING_BACK:
case Status.STATUS_MARKED_ROLLBACK:
System.out.println("rolling back");
break;
case Status.STATUS_COMMITTED:
case Status.STATUS_COMMITTING:
System.out.println("committing");
break;
default:
System.out.println("something else " + status );
}
}
private GeronimoTransactionManager createTxManager() throws Exception {
XidFactoryImpl xidFactory = new XidFactoryImpl();
int transactionTimoutSeconds = 10;
return new
GeronimoPlatformTransactionManager(transactionTimoutSeconds, xidFactory,
GeronimoDefaults.createTransactionLog(xidFactory, null), null);
}
[/code]