23 Aug 2015
 

Dynamic Spring's @Transactional

Written by ilgrosso

Declarative transaction management, available since longtime in Spring, is somehow addictive, and can be counted among the gifts that AOP brings to modern developers. Once used to that, it is very hard to go back to traditional transaction handling, especially when coping with databases and distributed transactions. Such great power comes naturally at a price, but we are not going to discuss this point: if interested, google around or take a look at this post.

We are instead about to introduce a simple extension to Spring's transaction management that allows to overcome one of its (few) limitations.

As you probably already know - since you are reading this post - putting Spring transactions at work is fairly easy.

First, configure

<bean id="domain1" class="some.transaction.TransactionManager"/>
<tx:annotation-driven transaction-manager="domain1"/>

Then, annotate

    @Transactional
    public void transactionalMethod() {
        // ...
    }

@Transactional offers a wide set of configuration options to customìze the transactional behavior: isolation, propagation, which exception(s) to rollback and which don't; as any other Java annotation, though, everything needs to be statically defined.

Among other things, this implies that you need to establish in advance all the characteristics of the future transactions; while this works for most of the cases, what about having a configuration like as

<bean id="domain1" class="some.transaction.TransactionManager"/>
<bean id="domain2" class="some.transaction.TransactionManager"/>
<tx:annotation-driven transaction-manager="domain1"/>
<tx:annotation-driven transaction-manager="domain2"/>

e.g. two different transaction managers?

You can, naturally, write something like as

    @Transactional("domain2")
    public void transactionalMethod() {
        // ...
    }

but this again will enforce the 'domain2' transaction manager to handle all the transactions involving the method above.

What about deciding at runtime which transaction manager to work with?

This github repo of mine shows a simple approach for achieving this by extending Spring's TransactionInerceptor.

...and if you are wondering about a real use case, please take a look at recently introduced multi-tenancy in Apache Syncope, where each domain is mapped to a different JPA persistence-unit, which features in turn a separate transaction manager. Overall, this allows the very same JPA-powered code to transparently handle entities for different domains in distinct databases (even from heterogeneous database engines, by the way).

       

« Return