Dynamic Selection of TransactionManager Spring Boot

Multi tool use
Dynamic Selection of TransactionManager Spring Boot
I am converting my existing Spring Application to a Spring Boot Application. In my existing application, we have the need to connect to multiple databases and we had achieved this by having multiple data sources defined and fetching the corresponding bean based on the condition. The transaction manager were also selected using a custom implementation of TransactionInterceptor.
@Override
public TransactionAttributeSource getTransactionAttributeSource() {
final TransactionAttributeSource origTxAttrSource = super.getTransactionAttributeSource();
return new TransactionAttributeSource() {
@Override
public TransactionAttribute getTransactionAttribute(final Method method, final Class<?> targetClass) {
TransactionAttribute txAttr = origTxAttrSource.getTransactionAttribute(method, targetClass);
String database = (String) ThreadContext.get("database");
if (database != null && StringUtils.isNotBlank(database)) {
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setQualifier("txManager" + database);
}
}
return txAttr;
}
};
}
Through a BeanFactoryPostProcessor
we were including this interceptor
BeanFactoryPostProcessor
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String names = beanFactory.getBeanNamesForType(TransactionInterceptor.class);
for (String name : names) {
BeanDefinition bd = beanFactory.getBeanDefinition(name);
bd.setBeanClassName(MyTransactionInterceptor.class.getName());
}
}
This worked perfectly fine in Spring 4.X.
Now that we are moving towards Spring Boot, I am trying to convert the same approach. I can see that the bean factory is getting called but I don't find calls happening to the Custom Interceptor class. This results in my @Transactional
to fail as there are more than one qualifying bean.
@Transactional
Am I missing something with regards to the Spring Boot Configuration?
(This approach of dynamic transaction management was through a reference blog http://blog.tirasa.net/dynamic-springs--at-transactional.html)
EnableTransactionManagementConfiguration
@EnableTransactionManagement
@EnableTransactionManagement annotation is not present. Basically, I have two transaction managers define (one for PostGre and another for MySQL). The exception I get is when the Transaction Proxy is being executed that there were two qualifying beans. Will post the stacktrace shortly.
– Aravind
Jun 29 at 0:55
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available: expected single matching bean but found 2: postgreTxManager,mysqlTxManager at (so on until ) org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
– Aravind
Jun 29 at 2:29
1 Answer
1
The final answer turned out to be setting the factory classes and the factory bean name to null which resulted in the transaction interceptor being invoked. I am yet to figure out how this affects the interceptor call as with the values in these fields (they point to the ProxyTransaction classes as transactionInterceptor bean is created by it).
The final code was of the form -
TransactionInterceptor Class
@Component
public class TransactionInterceptorReplacer implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(final ConfigurableListableBeanFactory factory) throws BeansException {
String names = factory.getBeanNamesForType(TransactionInterceptor.class);
for (String name : names) {
BeanDefinition bd = factory.getBeanDefinition(name);
bd.setBeanClassName(MyTransactionInterceptor.class.getName());
bd.setFactoryBeanName(null);
bd.setFactoryMethodName(null);
}
}
}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Add the exception and you might want do exclude the
EnableTransactionManagementConfiguration
from kicking in as that enables transaction management. Although it should already backoff if you yourself add@EnableTransactionManagement
.– M. Deinum
Jun 28 at 17:10