On Jan 21, 2007, at 10:53 AM, James Richardson wrote:
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?
I find the text of the jta 1.0.1B spec somewhat unclear on this but I
notice on p. 63 in the change history for 1.0.1B they changed the
description of when to call Synchronization.beforeCompletion from
"before the start of the transaction completion process" to "before
the start of the two-phase transaction commit process" so I think
there's at least an implication that we shouldn't call
beforeCompletion when we know we're going to rollback.
I imagine the problem is that hibernate tries to use something that
objects because it's set rollbackOnly?
Which version of geronimo is your version of jencks using?
Would you like to file a jira issue for this?
thanks
david jencks
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]