What is the scope of @EnableTransactionManagement?

Vadym S. Khondar picture Vadym S. Khondar · Sep 23, 2014 · Viewed 16.3k times · Source

I'm trying to understand where is the right place to put @EnableTransactionManagement annotation in case of multiple JavaConfig contexts?

Consider following scenario: I have JPA config in JPAConfig.java and AppConfig.java with set of service beans. Then I compose overall application config in RootConfig.java.

I define transaction manager within JPAConfig.java as well as enable scanning for JPA repositories - as those expose transactional behavior, I put @EnableTransactionManagement over JPAConfig and it works.

However, some of service beans also need to have transactional methods e.g. accessing several repositories within single transaction. Should I also put @EnableTransactionManagement over AppConfig as well? Looking into implementation of this annotation is seems to me that such approach would cause redefinition of some beans. And actually doing so doesn't seem to work for me.

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("com.mypackage.repositories")
public class JPAConfig {
 // ... here are EntityManager and PlatformTransactionManager beans
}


@Configuration
@ComponentScan("com.mypackage.services")
// @EnableTransactionManagement // - ???
public class AppConfig {
}

@Configuration
@Import({AppConfig.class, JPAConfig.class})
public class RootConfig {
}

Appreciate any advices.

Answer

Vadym S. Khondar picture Vadym S. Khondar · Sep 28, 2014

After some experiments I seem to have found the answer myself:

  • There is no need to configure @EnableTransactionManagement on each piece of context configuration although it does matter how early this annotation is discovered as it registers internalTransactionAdvisor which actually processes @Transactional annotations on created beans.
  • In my case, I changed the order of contexts in @Import declaration so that PersistenceConfig that holds @EnableTransactionManagement is the first. After this beans from other pieces can use AOP declarative transaction.
  • Another caveat relates to simultaneous use of @EnableTransactionManagement and @EnableGlobalMethodSecurity. Global method security uses bean post processing which seems to require whole security configuration to be wired. BeanPostProcessors are created early on context start-up so you can't use declarative @Transactional in any bean that would be needed to bootstrap spring security (in my case UserDetailsContextMapper) - advisor is not yet created then!