The versioning isn’t happening, part 3: it’s in UserTransaction?

This post is part 3 in a 9-part series on Envers, Spring, and JTA. The next post is The versioning isn’t happening, part 4: Registering with the wrong transaction?, and the previous post is The versioning isn’t happening, part 2: beforeCompletion.


We’re trying to figure out why the envers versioning records are not created when our project uses a JTA transaction manager — it creates the versioning records just fine when we’re using local Hibernate transactions.

In part 2, we discovered that while org.jboss.envers.synchronization.VersionsSync.beforeCompletion() is called when we’re running in Hibernate mode, it is not getting called when we’re in JTA mode, even though onPostInsert is being called just like in Hibernate mode.

To dig farther toward the root of this, let’s see where the call to beforeCompletion() comes from when we’re in Hibernate mode…

1. Hibernate mode

I deployed the hibernate-mode version again and sent a message with a method-entry breakpoint on the VersionsSync beforeCompletion() call.  This time, I set breakpoints on the lines farther up the call stack — the last six entries in the chain of calls yielding the call to beforeCompletion().  My list of breakpoints now looks like this:

AbstractPlatformTransactionManager [line: 678] - commit(TransactionStatus)
AbstractPlatformTransactionManager [line: 709] - processCommit(DefaultTransactionStatus)
HibernateTransactionManager [line: 655] - doCommit(DefaultTransactionStatus)
JDBCTransaction [line: 109] - commit()
JDBCTransaction [line: 228] - notifyLocalSynchsBeforeTransactionCompletion()
TransactionAspectSupport [line: 321] - commitTransactionAfterReturning(TransactionInfo)
VersionsSync [entry] - beforeCompletion()

Now we’ll run it in jta mode and see if we get to any of these breakpoints.

2. JTA mode

We do break at TransactionInterceptor(TransactionAspectSupport).commitTransactionAfterReturning(TransactionAspectSupport$TransactionInfo) line: 321 (but… ohhhh, I stepped too slowly and the transaction timed out, yielding a stack trace!  Trying again…)

We’re at JtaTransactionManager(AbstractPlatformTransactionManager).commit(TransactionStatus) line: 678 and then JtaTransactionManager.doCommit(DefaultTransactionStatus)… so far this is just like Hibernate mode.  org.springframework.transaction.jta.JtaTransactionManager.doCommit(DefaultTransactionStatus) mainly just does txObjext.getUserTransaction().commit() (line 1028) — this is still analogous to what we see on the Hibernate-mode side (there, it’s org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(DefaultTransactionStatus), which mainly just calls txObject.getSessionHolder().getTransaction().commit() (line 655).)

2.1. A closer look at the Hibernate-mode commit() call

Let’s look more closely at this call:

txObject.getSessionHolder().getTransaction().commit()

The getTransaction() call returns a org.hibernate.transaction.JDBCTransaction object, which we then call commit() on.  And it is this commit() method that calls org.hibernate.transaction.JDBCTransaction.notifyLocalSynchsBeforeTransactionCompletion(), which calls the beforeCompletion() method.

2.2. The Difference on the JTA Side

The call mentioned in step 1.2.1. is what causes beforeCompletion() to be called (which creates the envers versioning records) when we’re in Hibernate mode.  The analogous call when we’re in JTA mode is:

txObjext.getUserTransaction().commit();

(Called by org.springframework.transaction.jta.JtaTransactionManager.doCommit(DefaultTransactionStatus) on line 1028.)

Now, getUserTransaction() returns the javax.transaction.UserTransaction from JBoss; and then we call commit() on that.  Somewhere inside that commit() call, javax.transaction.Synchronization.beforeCompletion()* is not being called.

*VersionsSync implements javax.transaction.Synchronization; any beforeCompletion() call in an app server’s UserTransaction would reference the javax.transaction.Synchronization interface rather than org.jboss.envers.synchronization.VersionsSync, I’m sure!

In our next installment, let’s look into why UserTransaction is not calling beforeCompletion().

Advertisements

, , , ,

  1. #1 by Amin Mohammed-Coleman on October 8, 2009 - 4:54 am

    Hi there

    I am now experiencing the same problem with Hibernate Search and the event listeners for doing indxexing when using Spring managed JTA. Have you managed to resolve your issue and get it working with Spring JTA?

    Cheers

  2. #2 by danielmeyer on October 8, 2009 - 10:30 am

    Amin,
    This post is part 3 in a 9-part series… I’ve just added better navigation at the top of this post. I was able to get to a better resolution, which I’ve documented later in the series. Hope this helps!

    -Daniel-

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s