Adapt auto-configurations to back-off in presence of TransactionManager
Previous to this commit, an auto-configuration would create a PlatformTransactionManager if none is present and others conditions are met. Spring Framework now has the notion of TransactionManager, a parent interface that gathers both PlatformTransactionManager and ReactiveTransactionManager. Spring Boot should not be in a situation where both managers are defined out-of-the-box. This commit makes sure to back-off if any TransactionManager is available. Closes gh-22851
This commit is contained in:
parent
f191b7513d
commit
085091dbe3
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -31,7 +31,7 @@ import org.springframework.context.annotation.Configuration;
|
|||
import org.springframework.core.Ordered;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionManager;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for
|
||||
|
|
@ -44,7 +44,7 @@ import org.springframework.transaction.PlatformTransactionManager;
|
|||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
|
||||
@ConditionalOnClass({ JdbcTemplate.class, TransactionManager.class })
|
||||
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
|
||||
@EnableConfigurationProperties(DataSourceProperties.class)
|
||||
public class DataSourceTransactionManagerAutoConfiguration {
|
||||
|
|
@ -54,7 +54,7 @@ public class DataSourceTransactionManagerAutoConfiguration {
|
|||
static class DataSourceTransactionManagerConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
@ConditionalOnMissingBean(TransactionManager.class)
|
||||
DataSourceTransactionManager transactionManager(DataSource dataSource,
|
||||
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
|
||||
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -54,6 +54,7 @@ import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
|
|||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
|
||||
import org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionManager;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
|
@ -92,7 +93,7 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware {
|
|||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@ConditionalOnMissingBean(TransactionManager.class)
|
||||
public PlatformTransactionManager transactionManager(
|
||||
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
|
||||
JpaTransactionManager transactionManager = new JpaTransactionManager();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -41,7 +41,6 @@ import org.springframework.boot.jta.atomikos.AtomikosXADataSourceWrapper;
|
|||
import org.springframework.boot.system.ApplicationHome;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -57,7 +56,7 @@ import org.springframework.util.StringUtils;
|
|||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties({ AtomikosProperties.class, JtaProperties.class })
|
||||
@ConditionalOnClass({ JtaTransactionManager.class, UserTransactionManager.class })
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
@ConditionalOnMissingBean(org.springframework.transaction.TransactionManager.class)
|
||||
class AtomikosJtaConfiguration {
|
||||
|
||||
@Bean(initMethod = "init", destroyMethod = "shutdownWait")
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ import org.springframework.boot.jms.XAConnectionFactoryWrapper;
|
|||
import org.springframework.boot.system.ApplicationHome;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -54,7 +53,7 @@ import org.springframework.util.StringUtils;
|
|||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(JtaProperties.class)
|
||||
@ConditionalOnClass({ JtaTransactionManager.class, BitronixContext.class })
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
@ConditionalOnMissingBean(org.springframework.transaction.TransactionManager.class)
|
||||
class BitronixJtaConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -23,7 +23,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
|||
import org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.config.JtaTransactionManagerFactoryBean;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
|
||||
|
|
@ -38,7 +37,7 @@ import org.springframework.transaction.jta.JtaTransactionManager;
|
|||
@ConditionalOnClass(JtaTransactionManager.class)
|
||||
@ConditionalOnJndi({ JtaTransactionManager.DEFAULT_USER_TRANSACTION_NAME, "java:comp/TransactionManager",
|
||||
"java:appserver/TransactionManager", "java:pm/TransactionManager", "java:/TransactionManager" })
|
||||
@ConditionalOnMissingBean(PlatformTransactionManager.class)
|
||||
@ConditionalOnMissingBean(org.springframework.transaction.TransactionManager.class)
|
||||
class JndiJtaConfiguration {
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
|
|||
import org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
|
@ -54,7 +54,7 @@ class DataSourceTransactionManagerAutoConfigurationTests {
|
|||
void transactionManagerWithExistingDataSourceIsConfigured() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class))
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(PlatformTransactionManager.class)
|
||||
assertThat(context).hasSingleBean(TransactionManager.class)
|
||||
.hasSingleBean(DataSourceTransactionManager.class);
|
||||
assertThat(context.getBean(DataSourceTransactionManager.class).getDataSource())
|
||||
.isSameAs(context.getBean(DataSource.class));
|
||||
|
|
@ -67,7 +67,7 @@ class DataSourceTransactionManagerAutoConfigurationTests {
|
|||
.withPropertyValues("spring.transaction.default-timeout=1m",
|
||||
"spring.transaction.rollback-on-commit-failure=true")
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(PlatformTransactionManager.class)
|
||||
assertThat(context).hasSingleBean(TransactionManager.class)
|
||||
.hasSingleBean(DataSourceTransactionManager.class);
|
||||
DataSourceTransactionManager transactionManager = context
|
||||
.getBean(DataSourceTransactionManager.class);
|
||||
|
|
@ -79,22 +79,21 @@ class DataSourceTransactionManagerAutoConfigurationTests {
|
|||
@Test
|
||||
void transactionManagerWithExistingTransactionManagerIsNotOverridden() {
|
||||
this.contextRunner
|
||||
.withBean("myTransactionManager", PlatformTransactionManager.class,
|
||||
() -> mock(PlatformTransactionManager.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(PlatformTransactionManager.class)
|
||||
.withBean("myTransactionManager", TransactionManager.class, () -> mock(TransactionManager.class))
|
||||
.run((context) -> assertThat(context).hasSingleBean(TransactionManager.class)
|
||||
.hasBean("myTransactionManager"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void transactionWithMultipleDataSourcesIsNotConfigured() {
|
||||
this.contextRunner.withUserConfiguration(MultiDataSourceConfiguration.class)
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(PlatformTransactionManager.class));
|
||||
.run((context) -> assertThat(context).doesNotHaveBean(TransactionManager.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void transactionWithMultipleDataSourcesAndPrimaryCandidateIsConfigured() {
|
||||
this.contextRunner.withUserConfiguration(MultiDataSourceUsingPrimaryConfiguration.class).run((context) -> {
|
||||
assertThat(context).hasSingleBean(PlatformTransactionManager.class)
|
||||
assertThat(context).hasSingleBean(TransactionManager.class)
|
||||
.hasSingleBean(DataSourceTransactionManager.class);
|
||||
assertThat(context.getBean(DataSourceTransactionManager.class).getDataSource())
|
||||
.isSameAs(context.getBean("test1DataSource"));
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2019 the original author or authors.
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -49,6 +49,7 @@ import org.springframework.orm.jpa.persistenceunit.PersistenceUnitManager;
|
|||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;
|
||||
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
|
@ -93,7 +94,7 @@ abstract class AbstractJpaAutoConfigurationTests {
|
|||
return (context) -> {
|
||||
assertThat(context).hasNotFailed();
|
||||
assertThat(context).hasSingleBean(JpaProperties.class);
|
||||
assertThat(context).doesNotHaveBean(PlatformTransactionManager.class);
|
||||
assertThat(context).doesNotHaveBean(TransactionManager.class);
|
||||
assertThat(context).doesNotHaveBean(EntityManagerFactory.class);
|
||||
};
|
||||
}
|
||||
|
|
@ -117,7 +118,7 @@ abstract class AbstractJpaAutoConfigurationTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void jtaTransactionManagerTakesPrecedence() {
|
||||
void jpaTransactionManagerTakesPrecedenceOverSimpleDataSourceOne() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(DataSourceTransactionManagerAutoConfiguration.class))
|
||||
.run((context) -> {
|
||||
assertThat(context).hasSingleBean(DataSource.class);
|
||||
|
|
@ -211,7 +212,8 @@ abstract class AbstractJpaAutoConfigurationTests {
|
|||
@Test
|
||||
void usesManuallyDefinedTransactionManagerBeanIfAvailable() {
|
||||
this.contextRunner.withUserConfiguration(TestConfigurationWithTransactionManager.class).run((context) -> {
|
||||
PlatformTransactionManager txManager = context.getBean(PlatformTransactionManager.class);
|
||||
assertThat(context).hasSingleBean(TransactionManager.class);
|
||||
TransactionManager txManager = context.getBean(TransactionManager.class);
|
||||
assertThat(txManager).isInstanceOf(CustomJpaTransactionManager.class);
|
||||
});
|
||||
}
|
||||
|
|
@ -360,7 +362,7 @@ abstract class AbstractJpaAutoConfigurationTests {
|
|||
static class TestConfigurationWithTransactionManager {
|
||||
|
||||
@Bean
|
||||
PlatformTransactionManager transactionManager() {
|
||||
TransactionManager testTransactionManager() {
|
||||
return new CustomJpaTransactionManager();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ import org.springframework.boot.test.util.TestPropertyValues;
|
|||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
|
@ -81,7 +80,7 @@ class JtaAutoConfigurationTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
void customPlatformTransactionManager() {
|
||||
void customTransactionManager() {
|
||||
this.context = new AnnotationConfigApplicationContext(CustomTransactionManagerConfig.class,
|
||||
JtaAutoConfiguration.class);
|
||||
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
|
||||
|
|
@ -240,8 +239,8 @@ class JtaAutoConfigurationTests {
|
|||
static class CustomTransactionManagerConfig {
|
||||
|
||||
@Bean
|
||||
PlatformTransactionManager transactionManager() {
|
||||
return mock(PlatformTransactionManager.class);
|
||||
org.springframework.transaction.TransactionManager testTransactionManager() {
|
||||
return mock(org.springframework.transaction.TransactionManager.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue