Closed fabienfleureau closed 10 months ago
Hi fabien,
This happens because we register an internal transaction manager for the secondary data source. I think the issue should go away if you specify which transaction manager to use, like:
@Transactional("transactionManager") // This is the "default" one, registered by your application
I'd ask you to try this and see if it goes away. I'm not sure how to apply this setting globally/by default in order not to have to change all @Transactional
, but if this solution works I can investigate.
EDIT: Another solution could be to use the @Primary
annotation on the default transaction manager, but since usually the transaction manager is not defined in the code but instantiated automatically by Spring I'm not sure how to apply that yet (but if you defined the transactionManager bean this should be applicable).
Hello, indeed it works like this, but I would be nice that integrating dbadmin would not require any modification in existing bean configuration. (I have a lot of existing @Transactional, I won't modify all of them) As a workaround I did anotate with @Primary annotation
@Bean
@Primary
@ConditionalOnMissingBean(TransactionManager::class)
fun transactionManager(
transactionManagerCustomizers: ObjectProvider<TransactionManagerCustomizers>
): PlatformTransactionManager {
return JpaTransactionManager()
.apply { transactionManagerCustomizers.ifAvailable {
it.customize(this)
}
}
}
Yes, indeed it's ideal to not require any modification. But I think at least adding @Primary
is required. Are you aware of any other possibility I can look into to avoid having to add that too?
I've read a little bit more about this. Ideally I would need something like a @Secondary
/@NotPrimary
annotation, in order to make the other bean @Primary
"by default" without having the user specify it.
From my limited knowledge such an annotation doesn't exist. These issues might be related so I'm saving them for future reference:
https://github.com/spring-projects/spring-framework/issues/26528#issuecomment-1149741516
https://github.com/spring-projects/spring-framework/issues/26241
There are way to instantiate the JPARepository programmatically without the needs of beans. Be doing there will be no conflicts with the main application beans. Also one possibility to could be not to use JPA at all for the internal processes and use jdbc related (you only have less than 5 different requests to write)
The previous version was using JdbcTemplate
indeed, but this brings many problems because table/field names can vary a lot with annotations, naming strategies, etc... and it's hard to get a solid result since you have to specify the field names "manually" if writing queries.
There might be a way to get the correct names by querying some Spring class, but I then decided to rewrite using JPA and solve all of this at once.
I will look into instantiating them without making them beans.
This should be fixed with this latest commit on the dev
branch. If you can confirm it as well on your side it would be great, @fabienfleureau ! (You should be able to remove the @Primary
annotation and it should keep working)
Describe the bug When we use the @Transactional annotation, it fails at runtime saying there are two TransactionManager available (NoUniqueBeanDefinitionException)
Is the bug at startup before you perform any action? No, it's at runtime when going to a @Transactional annotated method
Stacktrace No qualifying bean of type 'org.springframework.transaction.TransactionManager' available: expected single matching bean but found 2: transactionManager,internalTransactionManager