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.
After some experiments I seem to have found the answer myself:
@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.@Import
declaration so
that PersistenceConfig
that holds @EnableTransactionManagement
is the
first. After this beans from other pieces can use AOP declarative
transaction.@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!