@EnableTransactionManagement annotation with 2 transaction managers

Mital Pritmani picture Mital Pritmani · Nov 8, 2011 · Viewed 45.8k times · Source

I am using @Configuration annotation for configuration of spring instead of xml file. I am configuring 2 datasources with different session factory and different transaction managers. I am stuck with a problem here for @EnableTransactionManagement annotation. I read in its documentation that,

@EnableTransactionManagement is more flexible; it will fall back to a by-type lookup for any PlatformTransactionManager bean in the container. Thus the name can be "txManager", "transactionManager", or "tm": it simply does not matter.

This means whatever name I give to method, it will always search for the method which returns PlatformTransactionManager object while I have 2 transactionmanagers. Now the problem is, when I test this class, it gives me error:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single bean but found 2

I even tried to have 2 different Configuration classes but in vain. In xml configuration, this was not the case. I registered my both transaction managers with two <tx:annotation-driven transaction-manager="" /> tag and it worked fine. But not able to do same here with annotations.

What should I do if I want to configure 2 datasources with 2 different transaction managers in Spring annotated configuration class?

Answer

Angad picture Angad · Dec 27, 2013

In your configuration class, use @EnableTransactionManagement annotation.

Define a transaction manager in this class as:

    @Bean(name="txName")
    public HibernateTransactionManager txName() throws IOException{
        HibernateTransactionManager txName= new HibernateTransactionManager();
        txName.setSessionFactory(...);
        txName.setDataSource(...);
        return txName;
   }

There on, in your class/method that executes transactional job(s), annotate as follows:

@Transactional("txName")

or

@Transactional(value = "txName")

This is how you would tie a name qualified transaction manager to wherever you need it. You can now have as many transaction managers as you want and use it accordingly wherever you need.