Posts Tagged JTA

Hibernate One-to-Many Foray

We’re experiencing an issue where saving a GreetingSetPO does not result in the contained GreetingPO being saved with it — instead, we get an IllegalArgumentException deep in the guts of Hibernate.

The problem only happens when we use the JTA transaction manager along with envers (which makes use of beforeCompletion() Synchronization hooks).

I’ve posted to the envers forum already, and I’d like to post to the Hibernate forum, but I see that the Hibernate forum has a How To Ask For Help page.  Let’s go through that and make sure we’re doing the research they ask us to do, before posting.

Well, I see several interesting items in the Common Problems FAQ:

I saved a parent object but its associated objects weren’t saved to the database.

Associated objects must be saved explicitly by calling (or Session.persist()) or the association must be mapped with cascade="all" or cascade="save-update" (or cascade="persist").

Now GreetingSetPO.getMembers() method is declared with cascade=all:

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "greetingSet")
    public Set<GreetingPO> getMembers() {
        return members;

But GreetingPO.getGreetingSet() is not:

    public GreetingSetPO getGreetingSet() {
        return greetingSet;

I wonder if that’s a problem?

I’m having trouble with a bidirectional association.

When you update a bidirectional association you must update both ends.


It’s best to do this in an association management method of your persistent class.

Ok, we’re doing something like this… only we’re setting the whole set.  That is, instead of


I’m doing

        Set<GreetingPO> greetings = new HashSet<GreetingPO>();

I wonder if that would make a difference?

I’m still having trouble!

Read the documentation! There’s a detailed section about “Parent/Child Relationships” in chapter 16 of the reference documentation including code examples.

I need to read that chapter.

But first…

I’m getting ahead of myself though.  The Hibernate How To Ask For Help page has an ordering to it, and the first item is the road map for new users/Getting Started/I want to learn Hibernate for Java! page, and the first item there (after downloading Hibernate) is to do the tutorial.

The tutorial

So I’m reading through the tutorial in the Hibernate reference documentation. The examples are use the .hbm.xml configuration files rather than the class annotations we’re using — I’m trying to understand some concepts to apply later when I read about the annotations.

I did come to this, though: in section 1.3.6. Working bi-directional links

What about the inverse mapping attribute? For you, and for Java, a bi-directional link is simply a matter of setting the references on both sides correctly. Hibernate however doesn’t have enough information to correctly arrange SQL INSERT and UPDATE statements (to avoid constraint violations), and needs some help to handle bi-directional associations properly. Making one side of the association inverse tells Hibernate to basically ignore it, to consider it a mirror of the other side. That’s all that is necessary for Hibernate to work out all of the issues when transformation a directional navigation model to a SQL database schema. The rules you have to remember are straightforward: All bi-directional associations need one side as inverse. In a one-to-many association it has to be the many-side, in many-to-many association you can pick either side, there is no difference.

(Bold emphasis mine.)  And the Hibernate Annotations FAQ explains inverse this way:

How can I set inverse=”true”?

The semantic equivalent is mappedBy in the association annotations. Have a look at the reference guide for a complete explaination.

Now, our GreetingSetPO.getMembers()’ @OneToMany annotation does have the mappedBy attribute:

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "greetingSet")
    public Set<GreetingPO> getMembers() {
        return members;

I’m still not sure if it should be here or in GreetingPO…

I’m wanting to read that chapter about parent/child relationships the documentation pointed me to earlier.

Chapter 1621

It looks like the former chapter 16 is now chapter 21. Chapter 21. Example: Parent/Child starts out like this:

One of the very first things that new users try to do with Hibernate is to model a parent / child type relationship. There are two different approaches to this. For various reasons the most convenient approach, especially for new users, is to model both Parent and Child as entity classes with a <one-to-many> association from Parent to Child. (The alternative approach is to declare the Child as a <composite-element>.)

Gulp! That sounds like us!  Reading on…

Now, it turns out that default semantics of a one to many association (in Hibernate) are much less close to the usual semantics of a parent / child relationship than those of a composite element mapping. We will explain how to use a bidirectional one to many association with cascades to model a parent / child relationship efficiently and elegantly. It’s not at all difficult!

And a bit later:

[A]dding an entity to a collection does not cause that entity to become persistent, by default.

Instead, the default behaviour is that adding an entity to a collection merely creates a link between the two entities, while removing it removes the link. This is very appropriate for all sorts of cases. Where it is not appropriate at all is the case of a parent / child relationship, where the life of the child is bound to the life cycle of the parent.

(Emphasis mine.)  Sounds like I need to keep reading.  Section 21.2. Bidirectional one-to-many has this:

The underlying cause of this behaviour is that the link (the foreign key parent_id) from p to c is not considered part of the state of the Child object…


Now that the Child entity is managing the state of the link, we tell the collection not to update the link. We use the inverse attribute.

<set name="children" inverse="true">
    <key column="parent_id"/>
    <one-to-many class="Child"/>

The following code would be used to add a new Child

Parent p = (Parent) session.load(Parent.class, pid);
Child c = new Child();

Saving the Child Yields Unsaved Transient Instance

Notice in that last code snippet, it’s the child PO that we pass to  (We’ve been passing the parent — the greeting set.)
Changing our test to the GreetingPO instead of the GreetingSetPO, now we get a different error:

org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: com.ontsys.db.GreetingSetPO; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.ontsys.db.GreetingSetPO
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(
    at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(
    at com.ontsys.db.GreetingDAO$$EnhancerByCGLIB$$8fe200fc.create(<generated>)
    at com.ontsys.db.EnversWithCollectionsTest.testComplexCreate(
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(
    at java.lang.reflect.Method.invoke(
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(
    at org.junit.internal.runners.statements.RunBefores.evaluate(
    at org.junit.internal.runners.statements.RunAfters.evaluate(
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(
    at org.junit.runners.ParentRunner.runChildren(
    at org.junit.runners.ParentRunner.access$000(
    at org.junit.runners.ParentRunner$1.evaluate(
    at org.junit.internal.runners.statements.RunBefores.evaluate(
    at org.junit.internal.runners.statements.RunAfters.evaluate(
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.ontsys.db.GreetingSetPO
    at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(
    at org.hibernate.type.EntityType.getIdentifier(
    at org.hibernate.type.ManyToOneType.isDirty(
    at org.hibernate.type.TypeFactory.findDirty(
    at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(
    at org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck(
    at org.hibernate.event.def.DefaultFlushEntityEventListener.isUpdateNecessary(
    at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(
    at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(
    at org.hibernate.impl.SessionImpl.flush(
    at org.springframework.orm.hibernate3.SpringSessionSynchronization.beforeCommit(
    ... 36 more

Looks Right

The Hibernate Annotations Reference Guide says this in Section Bidirectional Collections:

Since many to one are (almost) always the owner side of a bidirectional relationship in the EJB3 spec, the one to many association is annotated by @OneToMany( mappedBy=... )

public class Troop {
    public Set<Soldier> getSoldiers() {

public class Soldier {
    public Troop getTroop() {

Troop has a bidirectional one to many relationship with Soldier through the troop property.


I added a @Cascade annotation to GreetingSetPO.getMembers() as suggested by Section 2.4.7. Cascade, yielding this:

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "greetingSet")
    @Cascade( { org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE_ORPHAN })
    public Set<GreetingPO> getMembers() {
        return members;

…but I still get the unsaved transient instance error.

In case it was the way I was setting the greeting set

I even changed my GreetingSetPO to instantiate its Set<GreetingPO> internally, and updated my test from

        Set<GreetingPO> greetings = new HashSet<GreetingPO>();



…but I still get the unsaved transient instance exception when I try to save the GreetingPO record and have it cascade-save the associated GreetingSetPO.


[Update 2/9/2009: This post to the Hibernate Users forum may describe the same issue or a similar one… ]

[Update 3/26/2009: I logged issue HHH-3782 to the Envers bug tracker, with a sample project showing the error.  Adam said:

What you are missing, is the cascade on GreetingPO.getGreetingSet: the annotation there should be for example @ManyToOne(cascade = CascadeType.ALL).

With the cascade turned on, the test passes with and without Envers.

If I add the @ManyToOne annotation I still get the error, so I still don’t know what the issue is.  I think this is as likely me not knowing what I’m doing with Hibernate as an issue in Envers. ]



Why envers was blowing up

We’re experiencing an issue when we try to use envers to version a persistent object that holds a set of other persistent objects, when we’re using Spring’s JTA transaction manager.  (It doesn’t happen when we use hibernate local transactions using Spring’s HibernateTransactionManager.)  The commit of a one-to-many relationship (a Product and a Product Set), blows up with a weird error.

I had made a little test project with a greeting and a greeting set, to try to duplicate the issue apart from all the domain code.  I was not able to duplicate the issue — my greeting and greeting set committed fine, and the versioning records were created normally.

My test was set up like this:

     * This test commits an empty greeting set, then commits a new greeting to the set.      * The envers versioning works. 
    public void testSimpleCreate() {
        final String greeting = "Hola";

        final String setName = "Saludos";
        GreetingSetPO greetingSet = new GreetingSetPO();

        GreetingPO greetingPO = new GreetingPO();
        Long greetingId = greetingDao.create(greetingPO);

        GreetingPO greetingId2 = greetingDao.findByGreeting(greeting);
        assertEquals(greetingId, greetingId2.getId());

Notice that I’m committing the (empty) greeting set, then pointing the greeting to it and committing the greeting — two create() calls.

Today I talked with the domain guy and found out that the domain code is doing it a little differently:

     * This test creates a transient greeting set and a transient greeting, points them to each other, and then commits the
     * set-with-the-greeting-in-it. This blows up.
    public void testComplexCreate() {
        final String greeting = "Quid est nomen tibi?";
        final String setName = "Latin greetings";

        GreetingSetPO greetingSetPO = new GreetingSetPO();

        GreetingPO greetingPO = new GreetingPO();

        // Point the GreetingPO to its GreetingSetPO and vice versa

        Set<GreetingPO> greetings = new HashSet<GreetingPO>();



Notice that this time, instead of committing the empty greeting set, we create the greeting set and greeting, point them to each other, then commit the set-with-the-greeting-in-it.

This blows up just like the domain code. Yeah!

So now my questions are:

  1. Should this single-create() version work?
  2. If not, why does it work when we’re using Hibernate local transactions?

Update: I’ve posted my question to the envers forum.

, ,

Leave a comment

Blowing up in test mode

This is the final post in a 9-part series on Envers, Spring, and JTA. The previous post is The final answer.

Setting the hibernate.transaction.manager_lookup_class and org.hibernate.transaction.JTATransactionFactory properties in the Hibernate config:

<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>

fixed my issue where the envers beforeCompletion synchronization wasn’t-getting-called-when-we’re-in-JTA-mode… but with this change, the integration test stopped working — it now couldn’t find the JTA transaction manager by JNDI lookup.

Ah, yes — we’d need a JTA transaction manager to actually be available at integration test time — looks like another job for Bitronix Transaction Manager.

1. How I Set Up BTM

So, I put a file in the root of the classpath under src/test/java/ …

java.naming.factory.initial =

…put a file beside it… = hibernate-support-module-btm-server = target/btm1.log = target/btm2.log

…and added a bitronixTransactionManager bean to the beans file under src/test/resources…

<bean id="bitronixTransactionManager" factory-method="getTransactionManager" class="" destroy-method="shutdown"/>

2. One More Piece

The transaction manager JNDI lookup still was failing though, with this error:

org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.TransactionException: Naming service lookup for UserTransaction returned null [UserTransaction]

Caused by: org.hibernate.TransactionException: Naming service lookup for UserTransaction returned null [UserTransaction]

The BTM Hibernate documentation pointed out that I can set the

hibernate.transaction.manager_lookup_class to Hibernate’s BTMTransactionManagerLookup class.  (Huh!)

<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.BTMTransactionManagerLookup</prop>

When I do this, the integration test now works again.

3. Now the Deploy to JBoss Fails

I was pretty sure that deploying to JBoss with the transaction manager lookup setting pointing to a BTMTransactionManagerLookup wasn’t going to work, and sure enough, on deploy I get this:

org.hibernate.HibernateException: Could not obtain BTM transaction manager instance

Caused by: java.lang.ClassNotFoundException:

Right, this error is because we aren’t including BTM in the production war project (and we don’t want to).

4. Test and Production Both Need To Work At Once

So now we can run our tests if we specify the BTMTransactionManagerLookup, and we can run in production if we specify the JBossTransactionManagerLookup.  We need to find a configuration that will work both in test and production modes.

Another nagging issue is that we don’t want to hardcode our production configuration to be specific to JBoss — ideally we’d like the application server to be auto-detected; if we need to we could make it manually configurable.  Hardcoded JBossTransactionManagerLookup won’t do.

5. Spring to the Rescue?

Thinking of auto-detecting the application server reminds me of what Spring’s JtaTransactionManager does — it tries various JNDI lookups for the JTA TransactionManager and UserTransaction until it finds ones that work, so you’re not hardcoding support for only one app server and there is no user configuration needed .  I wonder if Spring has a TransactionManagerLookup that does that sort of thing to avoid  — is Spring’s LocalTransactionManagerLookup what we need?

When I switch the transaction manager lookup line to that:

<prop key="hibernate.transaction.manager_lookup_class">org.springframework.orm.hibernate3.LocalTransactionManagerLookup</prop>

…I get this error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sessionFactory’ defined in class path resource [com/ontsys/fw/hibernatesupport/startup/hibernate-support-beans.spring.xml]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Could not instantiate TransactionManagerLookup ‘org.springframework.orm.hibernate3.LocalTransactionManagerLookup’

Come to think of it, the javadoc for LocalTransactionManagerLookup does say:

Implementation of Hibernate’s TransactionManagerLookup interface that returns a Spring-managed JTA TransactionManager, determined by LocalSessionFactoryBean’s “jtaTransactionManager” property.

(Emphasis mine.)  My Hibernate configuration configures an AnnotationSessionFactoryBean (which is a LocalSessionFactoryBean), and I didn’t set the jtaTransactionManager property there.

5.1. Setting the jtaTransactionManager Property

As a first attempt, I set

<property name="jtaTransactionManager" ref="transactionManager" />

where the transactionManager reference refers to my

<tx:jta-transaction-manager />

bean.  I get:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘sessionFactory’ defined in class path resource [com/ontsys/fw/hibernatesupport/startup/hibernate-support-beans.spring.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type [org.springframework.transaction.jta.JtaTransactionManager] to required type [javax.transaction.TransactionManager] for property ‘jtaTransactionManager’; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [org.springframework.transaction.jta.JtaTransactionManager] to required type [javax.transaction.TransactionManager] for property ‘jtaTransactionManager’: no matching editors or conversion strategy found

So the Spring JtaTransactionManager isn’t a javax.transaction.TransactionManager.  What do you specify for the jtaTransactionManager property, then?

In a helpful post from 2004, Juergen Hoeller speaks to Spring’s support for, and the limits of, container-independent JTA configuration:

…Spring’s JtaTransactionManager itself works just nicely in a container-independent fashion – in typical usage scenarios where you could use a plain JTA javax.transaction.UserTransaction too…you just need container-specific configuration for more advanced usage, namely transaction suspension and Hibernate cache completion callbacks. The simple reason for this is that you need the JTA javax.transaction.TransactionManager to suspend/resume transactions and register transaction synchronizations; the UserTransaction interface does not support that functionality.

Unfortunately, J2EE does not specify how to access the JTA TransactionManager, just the common JNDI location of the JTA UserTransaction – so the lookup of the JTA TransactionManager has to be container-specific. This is the case with Hibernate (see TransactionManagerLookup), this is the case with Spring, this is the case with any such tool.

For Hibernate cache completion callbacks with JTA, you need to specify a corresponding TransactionManagerLookup in the Hibernate properties. As an alternative, Spring allows you to pass a JTA TransactionManager into LocalSessionFactoryBean’s “jtaTransactionManager” property, to reuse a centrally defined TransactionManager reference that can be shared with JtaTransactionManager’s “transactionManager” property.

(Emphasis mine.) Juergen goes on to mention that as another alternative, Hibernate’s cache-completion callbacks are taken care of if you use Spring’s own transaction synchronization mechanism — this avoids the need for a container-specific TransactionManagerLookup.  I don’t think Spring’s synchronization mechanism is sufficient for what we need here though, because it looks like it only supports the afterCompletion() callback, and we (through envers) are making use of the beforeCompletion() callback.

6. A Table of Our Apparent Options

Opt # Configuration Viable Option? Comments
1 Plain ol’ Spring JtaTransactionManager and Hibernate LocalSessionFactoryBean without additional configuration No Hibernate doesn’t know about Spring JTA transaction manager, synchronizations get registered wrong and are not called
2 Use Spring’s synchonization mechanism No Appears to only support afterCompletion() synchronization callback, and envers needs and uses the beforeCompletion() one
3 Have a separate javax.transaction.TransactionManager that the Hibernate LocalSessionFactoryBean and Spring’s JtaTransactionManager both reference Yes The javax.transaction.TransactionManager may have to be defined in a container-specific way
4 Specify hibernate.transaction.manager_lookup_class to Hibernate’s LocalSessionFactoryBean config Yes Which TransactionManagerLookup class is needed is container-specific, so we’d need to abstract the choice out to a configuration property somehow

I’m leaning toward going with option #4 without even trying option #3 since I can see how we would do #4 and I’m afraid that even with #3’s greater complexity it still wouldn’t get us container-independent JTA configuration.

Update (1/2/2009): Yep, option #4 is what we went with.   To abstract away the container-specificness, we maintain a list of org.hibernate.transaction.*TransactionManagerLookup classes and iterate through the list trying getTransactionManager() on each until we find one that doesn’t return null — then we populate the hibernate.transaction.factory_class configuration property with that class name.  The org.hibernate.transaction.BTMTransactionManagerLookup last in the list, and the org.hibernate.transaction.JBossTransactionManagerLookup is currently the only other lookup class in the list; but as we add support more app servers, the idea is we can just add more of the specific org.hibernate.transaction.*TransactionManagerLookup classes to the list.

, , ,

1 Comment

Why we’d want at least version 1.3.1

Bitronix Transaction Manager has been helpful for our integration tests, which can then run outside the app server and have a JTA transaction manager and enough of a JNDI provider to get by.

We have been using version 1.3, since that’s the version that first had the JNDI server.  But we had to specify disableJmx=true in the Configuration object so that the java: prefix could work.

This limitation has been removed as of BTM 1.3.1.  I’m BTM-enabling another module — maybe now’s the time to update to the current version of BTM…

, ,

Leave a comment

The final answer

This post is part 8 in a 9-part series on Envers, Spring, and JTA. The next post is Blowing up in test mode, and the previous post is An answer.

The story thus far:

The envers beforeCompletion() hook was not running when I switched from using Spring’s HibernateTransactionManager to using its JtaTransactionManager.  I had done some digging on my own, then made a long post to the Spring Data Access forum (after an initial post to the envers forum).

The long post apparently scared everybody off ;) , so I wrote a much shorter, more focused post.

A reply to the shorter post pointed me to the SessionFactoryUtils javadoc, where I read:

Note that for non-Spring JTA transactions, a JTA TransactionManagerLookup has to be specified in the Hibernate configuration.

On the trail of how to specify a TransactionManagerLookup, I found the hibernate.transaction.manager_lookup_class setting in the Using JTA section of the Hibernate Reference Guide — but unbeknownst to me, another setting was needed…

Final Answer

A Hibernate Users forum post titled How can i use JTA with Hibernate? points to the Transaction demarcation with JTA section of the Sessions and transactions Wiki page, where we see:

  • set hibernate.transaction.manager_lookup_class to a lookup strategy for your JEE container
  • set hibernate.transaction.factory_class to org.hibernate.transaction.JTATransactionFactory

So, adding these two lines to my Hibernate spring beans file (lines 6 and 7 below) fixed the issue:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="hibernateProperties">
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</prop>

NOW the envers beforeCompletion() hook gets called when using the JTA transaction manager.


, , ,


An answer

This post is part 7 in a 9-part series on Envers, Spring, and JTA. The next post is The final answer, and the previous post is beforeCompletion, I need to figure this out.

A kind soul answered my second post to the Spring Data Access forum in which I had asked, “Does JtaTransactionManager support beforeCompletion synchronization?

He said, “Look at: SessionFactoryUtils#getJtaSynchronizedSession”.

The getJtaSynchronizedSession() method didn’t appear in org.springframework.orm.hibernate3.SessionFactoryUtils’ javadoc, so I pulled up the Spring source code I had checked out earlier and there it is (it’s a private method).

I right-clicked the method name in the editor and selected Open Call Hierarchy (have I mentioned that I’m loving the tool support these days?!)  The only three places it’s called from (another layer or two down) are the two getSession() methods and the one public doGetSession() method…

When I had initially pulled up  SessionFactoryUtils’ javadoc this had immediately jumped out at me:

Note that for non-Spring JTA transactions, a JTA TransactionManagerLookup has to be specified in the Hibernate configuration.

Aha: We’re not specifying a JTA TransactionManagerLookup in our Hibernate configuration.  Looks like that would be the next thing to look at.

Update: Here’s help for someone who had a similar issue.  Also, the Using JTA section of the Hibernate Reference Guide…

, ,

1 Comment

beforeCompletion, I need to figure this out

This post is part 6 in a 9-part series on Envers, Spring, and JTA. The next post is An answer, and the previous post is The versioning isn’t happening, part 4a: phone a friend.

I’m just getting back to the envers-JTA-hooks-not-getting-called thing — the following is from work I did last Wednesday —

A post to the Spring Data Access forum had this interesting line:

DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Triggering beforeCompletion synchronization

Hey!  Just when I was beginning to worry that Spring’s JtaTransactionManager had never heard of beforeCompletion and didn’t intend to call that callback.  So… where is that line of code, and who calls it?

Where It Is, and Who Calls It

Back at, this calls its own internal processCommit() method, which — why did we not notice this before? — does these things (among others):


TriggerBeforeCompletion() ?!  Firing up the ol’ debugger, I do make it in there.  So it *is* trying to run the beforeCompletion Synchronizations, methinks.  Perhaps they aren’t being registered?

triggerBeforeCompletion() calls TransactionSynchronizationUtils.triggerBeforeCompletion(), which calls  (The TransactionSynchronizationManager is also the class that has a registerSynchronization(TransactionSynchronization) method — but instead of taking a javax.transaction.Synchronization, it takes a

The only TransactionSynchronization that’s in there currently is a org.springframework.orm.hibernate3.SpringSessionSynchronization.

Envers’ org.jboss.envers.synchronization.VersionsSyncManager.get(EventSource session) calls session.getTransaction().registerSynchronization().  The getTransaction() call returns an org.hibernate.transaction.JDBCTransaction.

Next step: Can we get at that JDBCTransaction from JtaTransactionManager’s doCommit()?  Or alternatively, can the thing passed as an EventSource to VersionsSyncManager.get() be something that wraps a JDBCTransaction and also registers with the Spring TransactionSynchronizationManager?

, ,

1 Comment