diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java index 251601ba280..d8f07295fe1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BasicBatchConfigurer.java @@ -30,6 +30,7 @@ import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.support.SimpleJobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.transaction.PlatformTransactionManager; @@ -40,6 +41,7 @@ import org.springframework.util.StringUtils; * * @author Dave Syer * @author Andy Wilkinson + * @author Kazuki Shimizu */ public class BasicBatchConfigurer implements BatchConfigurer { @@ -47,6 +49,8 @@ public class BasicBatchConfigurer implements BatchConfigurer { private final BatchProperties properties; + private final TransactionProperties transactionProperties; + private final DataSource dataSource; private final EntityManagerFactory entityManagerFactory; @@ -62,21 +66,24 @@ public class BasicBatchConfigurer implements BatchConfigurer { /** * Create a new {@link BasicBatchConfigurer} instance. * @param properties the batch properties + * @param transactionProperties the transaction properties * @param dataSource the underlying data source */ - protected BasicBatchConfigurer(BatchProperties properties, DataSource dataSource) { - this(properties, dataSource, null); + protected BasicBatchConfigurer(BatchProperties properties, TransactionProperties transactionProperties, DataSource dataSource) { + this(properties, transactionProperties, dataSource, null); } /** * Create a new {@link BasicBatchConfigurer} instance. * @param properties the batch properties + * @param transactionProperties the transaction properties * @param dataSource the underlying data source * @param entityManagerFactory the entity manager factory (or {@code null}) */ - protected BasicBatchConfigurer(BatchProperties properties, DataSource dataSource, + protected BasicBatchConfigurer(BatchProperties properties, TransactionProperties transactionProperties, DataSource dataSource, EntityManagerFactory entityManagerFactory) { this.properties = properties; + this.transactionProperties = transactionProperties; this.entityManagerFactory = entityManagerFactory; this.dataSource = dataSource; } @@ -150,10 +157,15 @@ public class BasicBatchConfigurer implements BatchConfigurer { } protected PlatformTransactionManager createTransactionManager() { + PlatformTransactionManager txManager; if (this.entityManagerFactory != null) { - return new JpaTransactionManager(this.entityManagerFactory); + txManager = new JpaTransactionManager(this.entityManagerFactory); } - return new DataSourceTransactionManager(this.dataSource); + else { + txManager = new DataSourceTransactionManager(this.dataSource); + } + this.transactionProperties.applyTo(txManager); + return txManager; } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java index cb9c3515c8e..44eefb73f71 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java @@ -37,11 +37,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ResourceLoader; import org.springframework.jdbc.core.JdbcOperations; +import org.springframework.transaction.PlatformTransactionManager; import org.springframework.util.StringUtils; /** @@ -57,6 +59,7 @@ import org.springframework.util.StringUtils; * * @author Dave Syer * @author EddĂș MelĂ©ndez + * @author Kazuki Shimizu */ @Configuration @ConditionalOnClass({ JobLauncher.class, DataSource.class, JdbcOperations.class }) @@ -133,15 +136,18 @@ public class BatchAutoConfiguration { return factory; } - @ConditionalOnClass(name = "javax.persistence.EntityManagerFactory") + @EnableConfigurationProperties({BatchProperties.class, TransactionProperties.class}) + @ConditionalOnClass(value = PlatformTransactionManager.class, name = "javax.persistence.EntityManagerFactory") @ConditionalOnMissingBean(BatchConfigurer.class) @Configuration protected static class JpaBatchConfiguration { private final BatchProperties properties; + private final TransactionProperties transactionProperties; - protected JpaBatchConfiguration(BatchProperties properties) { + protected JpaBatchConfiguration(BatchProperties properties, TransactionProperties transactionProperties) { this.properties = properties; + this.transactionProperties = transactionProperties; } // The EntityManagerFactory may not be discoverable by type when this condition @@ -151,14 +157,14 @@ public class BatchAutoConfiguration { @ConditionalOnBean(name = "entityManagerFactory") public BasicBatchConfigurer jpaBatchConfigurer(DataSource dataSource, EntityManagerFactory entityManagerFactory) { - return new BasicBatchConfigurer(this.properties, dataSource, + return new BasicBatchConfigurer(this.properties, this.transactionProperties, dataSource, entityManagerFactory); } @Bean @ConditionalOnMissingBean(name = "entityManagerFactory") public BasicBatchConfigurer basicBatchConfigurer(DataSource dataSource) { - return new BasicBatchConfigurer(this.properties, dataSource); + return new BasicBatchConfigurer(this.properties, this.transactionProperties, dataSource); } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java index e5743e25959..19bbc4004ec 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfiguration.java @@ -29,6 +29,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.domain.EntityScanPackages; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -48,12 +49,13 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter * @author Josh Long * @author Vince Bickers * @author Stephane Nicoll + * @author Kazuki Shimizu * @since 1.4.0 */ @Configuration -@ConditionalOnClass(SessionFactory.class) +@ConditionalOnClass({SessionFactory.class, PlatformTransactionManager.class}) @ConditionalOnMissingBean(SessionFactory.class) -@EnableConfigurationProperties(Neo4jProperties.class) +@EnableConfigurationProperties({Neo4jProperties.class, TransactionProperties.class}) @SuppressWarnings("deprecation") public class Neo4jDataAutoConfiguration { @@ -87,8 +89,11 @@ public class Neo4jDataAutoConfiguration { @Bean @ConditionalOnMissingBean(PlatformTransactionManager.class) - public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory) { - return new Neo4jTransactionManager(sessionFactory); + public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory, + TransactionProperties transactionProperties) { + Neo4jTransactionManager transactionManager = new Neo4jTransactionManager(sessionFactory); + transactionProperties.applyTo(transactionManager); + return transactionManager; } private String[] getPackagesToScan(ApplicationContext applicationContext) { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java index d5feaf1352c..7632f161960 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfiguration.java @@ -23,6 +23,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; @@ -39,6 +41,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; * @author Dave Syer * @author Stephane Nicoll * @author Andy Wilkinson + * @author Kazuki Shimizu */ @Configuration @ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class }) @@ -47,6 +50,7 @@ public class DataSourceTransactionManagerAutoConfiguration { @Configuration @ConditionalOnSingleCandidate(DataSource.class) + @EnableConfigurationProperties(TransactionProperties.class) static class DataSourceTransactionManagerConfiguration { private final DataSource dataSource; @@ -57,8 +61,10 @@ public class DataSourceTransactionManagerAutoConfiguration { @Bean @ConditionalOnMissingBean(PlatformTransactionManager.class) - public DataSourceTransactionManager transactionManager() { - return new DataSourceTransactionManager(this.dataSource); + public DataSourceTransactionManager transactionManager(TransactionProperties transactionProperties) { + DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource); + transactionProperties.applyTo(transactionManager); + return transactionManager; } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java index 67d1ccbd962..a4d05fd6b83 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration.java @@ -34,6 +34,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.domain.EntityScanPackages; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; import org.springframework.context.annotation.Bean; @@ -59,8 +60,9 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter * @author Dave Syer * @author Oliver Gierke * @author Andy Wilkinson + * @author Kazuki Shimizu */ -@EnableConfigurationProperties(JpaProperties.class) +@EnableConfigurationProperties({JpaProperties.class, TransactionProperties.class}) @Import(DataSourceInitializedPublisher.Registrar.class) public abstract class JpaBaseConfiguration implements BeanFactoryAware { @@ -81,8 +83,10 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { @Bean @ConditionalOnMissingBean(PlatformTransactionManager.class) - public PlatformTransactionManager transactionManager() { - return new JpaTransactionManager(); + public PlatformTransactionManager transactionManager(TransactionProperties transactionProperties) { + JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionProperties.applyTo(transactionManager); + return transactionManager; } @Bean diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionProperties.java new file mode 100644 index 00000000000..41a3499080c --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionProperties.java @@ -0,0 +1,79 @@ +/* + * Copyright 2012-2016 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.transaction; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.support.AbstractPlatformTransactionManager; + +/** + * External configuration properties for a {@link org.springframework.transaction.PlatformTransactionManager} created by + * Spring. All {@literal spring.transaction.} properties are also applied to the {@code PlatformTransactionManager}. + * + * @author Kazuki Shimizu + * @since 1.5.0 + */ +@ConfigurationProperties(prefix = "spring.transaction") +public class TransactionProperties { + + /** + * The default transaction timeout (sec). + */ + private Integer defaultTimeout; + + /** + * The indicating flag whether perform the rollback processing on commit failure (If perform rollback, set to the true). + */ + private Boolean rollbackOnCommitFailure; + + public Integer getDefaultTimeout() { + return this.defaultTimeout; + } + + public void setDefaultTimeout(Integer defaultTimeout) { + this.defaultTimeout = defaultTimeout; + } + + public Boolean getRollbackOnCommitFailure() { + return this.rollbackOnCommitFailure; + } + + public void setRollbackOnCommitFailure(Boolean rollbackOnCommitFailure) { + this.rollbackOnCommitFailure = rollbackOnCommitFailure; + } + + /** + * Apply all transaction custom properties to a specified {@link PlatformTransactionManager} instance. + * + * @param transactionManager the target transaction manager + * @see AbstractPlatformTransactionManager#setDefaultTimeout(int) + * @see AbstractPlatformTransactionManager#setRollbackOnCommitFailure(boolean) + */ + public void applyTo(PlatformTransactionManager transactionManager) { + if (transactionManager instanceof AbstractPlatformTransactionManager) { + AbstractPlatformTransactionManager abstractPlatformTransactionManager = + (AbstractPlatformTransactionManager) transactionManager; + if (this.defaultTimeout != null) { + abstractPlatformTransactionManager.setDefaultTimeout(this.defaultTimeout); + } + if (this.rollbackOnCommitFailure != null) { + abstractPlatformTransactionManager.setRollbackOnCommitFailure(this.rollbackOnCommitFailure); + } + } + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java index bde242ed0be..e5b6d7b37cb 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/AtomikosJtaConfiguration.java @@ -30,6 +30,7 @@ import com.atomikos.icatch.jta.UserTransactionManager; import org.springframework.boot.ApplicationHome; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.jta.XAConnectionFactoryWrapper; import org.springframework.boot.jta.XADataSourceWrapper; @@ -50,18 +51,21 @@ import org.springframework.util.StringUtils; * @author Phillip Webb * @author Andy Wilkinson * @author Stephane Nicoll + * @author Kazuki Shimizu * @since 1.2.0 */ @Configuration -@EnableConfigurationProperties(AtomikosProperties.class) +@EnableConfigurationProperties({AtomikosProperties.class, JtaProperties.class, TransactionProperties.class}) @ConditionalOnClass({ JtaTransactionManager.class, UserTransactionManager.class }) @ConditionalOnMissingBean(PlatformTransactionManager.class) class AtomikosJtaConfiguration { private final JtaProperties jtaProperties; + private final TransactionProperties transactionProperties; - AtomikosJtaConfiguration(JtaProperties jtaProperties) { + AtomikosJtaConfiguration(JtaProperties jtaProperties, TransactionProperties transactionProperties) { this.jtaProperties = jtaProperties; + this.transactionProperties = transactionProperties; } @Bean(initMethod = "init", destroyMethod = "shutdownForce") @@ -111,7 +115,9 @@ class AtomikosJtaConfiguration { @Bean public JtaTransactionManager transactionManager(UserTransaction userTransaction, TransactionManager transactionManager) { - return new JtaTransactionManager(userTransaction, transactionManager); + JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(userTransaction, transactionManager); + this.transactionProperties.applyTo(jtaTransactionManager); + return jtaTransactionManager; } @Configuration diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/BitronixJtaConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/BitronixJtaConfiguration.java index c10098ce14a..efcb403b94f 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/BitronixJtaConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/BitronixJtaConfiguration.java @@ -28,7 +28,9 @@ import bitronix.tm.jndi.BitronixContext; import org.springframework.boot.ApplicationHome; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.jta.XAConnectionFactoryWrapper; import org.springframework.boot.jta.XADataSourceWrapper; import org.springframework.boot.jta.bitronix.BitronixDependentBeanFactoryPostProcessor; @@ -46,17 +48,21 @@ import org.springframework.util.StringUtils; * @author Josh Long * @author Phillip Webb * @author Andy Wilkinson + * @author Kazuki Shimizu * @since 1.2.0 */ @Configuration +@EnableConfigurationProperties({JtaProperties.class, TransactionProperties.class}) @ConditionalOnClass({ JtaTransactionManager.class, BitronixContext.class }) @ConditionalOnMissingBean(PlatformTransactionManager.class) class BitronixJtaConfiguration { private final JtaProperties jtaProperties; + private final TransactionProperties transactionProperties; - BitronixJtaConfiguration(JtaProperties jtaProperties) { + BitronixJtaConfiguration(JtaProperties jtaProperties, TransactionProperties transactionProperties) { this.jtaProperties = jtaProperties; + this.transactionProperties = transactionProperties; } @Bean @@ -105,7 +111,9 @@ class BitronixJtaConfiguration { @Bean public JtaTransactionManager transactionManager( TransactionManager transactionManager) { - return new JtaTransactionManager(transactionManager); + JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(transactionManager); + this.transactionProperties.applyTo(jtaTransactionManager); + return jtaTransactionManager; } @ConditionalOnClass(Message.class) diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JndiJtaConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JndiJtaConfiguration.java index 12f20dd39fa..c35c62db5b5 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JndiJtaConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JndiJtaConfiguration.java @@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.transaction.jta; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnJndi; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.transaction.PlatformTransactionManager; @@ -30,6 +32,7 @@ import org.springframework.transaction.jta.JtaTransactionManager; * * @author Phillip Webb * @author Stephane Nicoll + * @author Kazuki Shimizu * @since 1.2.0 */ @Configuration @@ -38,11 +41,20 @@ import org.springframework.transaction.jta.JtaTransactionManager; "java:comp/TransactionManager", "java:appserver/TransactionManager", "java:pm/TransactionManager", "java:/TransactionManager" }) @ConditionalOnMissingBean(PlatformTransactionManager.class) +@EnableConfigurationProperties(TransactionProperties.class) class JndiJtaConfiguration { + private final TransactionProperties transactionProperties; + + JndiJtaConfiguration(TransactionProperties transactionProperties) { + this.transactionProperties = transactionProperties; + } + @Bean public JtaTransactionManager transactionManager() { - return new JtaTransactionManagerFactoryBean().getObject(); + JtaTransactionManager transactionManager = new JtaTransactionManagerFactoryBean().getObject(); + this.transactionProperties.applyTo(transactionManager); + return transactionManager; } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/NarayanaJtaConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/NarayanaJtaConfiguration.java index 31394d6ed93..99c98f7f8f3 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/NarayanaJtaConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/NarayanaJtaConfiguration.java @@ -28,6 +28,8 @@ import org.jboss.tm.XAResourceRecoveryRegistry; import org.springframework.boot.ApplicationHome; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.jta.XAConnectionFactoryWrapper; import org.springframework.boot.jta.XADataSourceWrapper; import org.springframework.boot.jta.narayana.NarayanaBeanFactoryPostProcessor; @@ -47,18 +49,22 @@ import org.springframework.util.StringUtils; * JTA Configuration for Narayana. * * @author Gytis Trikleris + * @author Kazuki Shimizu * @since 1.4.0 */ @Configuration @ConditionalOnClass({ JtaTransactionManager.class, com.arjuna.ats.jta.UserTransaction.class, XAResourceRecoveryRegistry.class }) @ConditionalOnMissingBean(PlatformTransactionManager.class) +@EnableConfigurationProperties({JtaProperties.class, TransactionProperties.class}) public class NarayanaJtaConfiguration { private final JtaProperties jtaProperties; + private final TransactionProperties transactionProperties; - public NarayanaJtaConfiguration(JtaProperties jtaProperties) { + public NarayanaJtaConfiguration(JtaProperties jtaProperties, TransactionProperties transactionProperties) { this.jtaProperties = jtaProperties; + this.transactionProperties = transactionProperties; } @Bean @@ -116,7 +122,9 @@ public class NarayanaJtaConfiguration { @Bean public JtaTransactionManager transactionManager(UserTransaction userTransaction, TransactionManager transactionManager) { - return new JtaTransactionManager(userTransaction, transactionManager); + JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(userTransaction, transactionManager); + this.transactionProperties.applyTo(jtaTransactionManager); + return jtaTransactionManager; } @Bean diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java index c668df50198..e793ef3e44a 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java @@ -58,6 +58,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import static org.assertj.core.api.Assertions.assertThat; @@ -267,6 +269,42 @@ public class BatchAutoConfigurationTests { .queryForList("select * from BATCH_JOB_EXECUTION"); } + @Test + public void testCustomizeJpaTransactionManagerUsingProperties() throws Exception { + this.context = new AnnotationConfigApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.transaction.default-timeout:30", + "spring.transaction.rollback-on-commit-failure:true"); + this.context.register(TestConfiguration.class, + EmbeddedDataSourceConfiguration.class, + HibernateJpaAutoConfiguration.class, BatchAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + this.context.getBean(BatchConfigurer.class); + JpaTransactionManager transactionManager = JpaTransactionManager.class.cast( + this.context.getBean(BatchConfigurer.class).getTransactionManager()); + assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); + assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); + } + + @Test + public void testCustomizeDataSourceTransactionManagerUsingProperties() throws Exception { + this.context = new AnnotationConfigApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.transaction.default-timeout:30", + "spring.transaction.rollback-on-commit-failure:true"); + this.context.register(TestConfiguration.class, + EmbeddedDataSourceConfiguration.class, + BatchAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + this.context.getBean(BatchConfigurer.class); + DataSourceTransactionManager transactionManager = DataSourceTransactionManager.class.cast( + this.context.getBean(BatchConfigurer.class).getTransactionManager()); + assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); + assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); + } + @Configuration protected static class EmptyConfiguration { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java index 25fc2b5662a..49031a48bd8 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jDataAutoConfigurationTests.java @@ -37,6 +37,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.neo4j.mapping.Neo4jMappingContext; import org.springframework.data.neo4j.template.Neo4jOperations; +import org.springframework.data.neo4j.transaction.Neo4jTransactionManager; import org.springframework.data.neo4j.web.support.OpenSessionInViewInterceptor; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; @@ -73,10 +74,21 @@ public class Neo4jDataAutoConfigurationTests { .hasSize(1); assertThat(this.context.getBeansOfType(SessionFactory.class)).hasSize(1); assertThat(this.context.getBeansOfType(Neo4jOperations.class)).hasSize(1); + assertThat(this.context.getBeansOfType(Neo4jTransactionManager.class)).hasSize(1); assertThat(this.context.getBeansOfType(OpenSessionInViewInterceptor.class)) .isEmpty(); } + @Test + public void customNeo4jTransactionManagerUsingProperties() { + load(null, + "spring.transaction.default-timeout=30", + "spring.transaction.rollback-on-commit-failure:true"); + Neo4jTransactionManager transactionManager = this.context.getBean(Neo4jTransactionManager.class); + assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); + assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); + } + @Test public void customSessionFactory() { load(CustomSessionFactory.class); diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfigurationTests.java index 93b44a1414d..70ea23679ef 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceTransactionManagerAutoConfigurationTests.java @@ -20,6 +20,7 @@ import javax.sql.DataSource; import org.junit.Test; +import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -106,6 +107,19 @@ public class DataSourceTransactionManagerAutoConfigurationTests { .isNotNull(); } + @Test + public void testCustomizeDataSourceTransactionManagerUsingProperties() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, + "spring.transaction.default-timeout:30", + "spring.transaction.rollback-on-commit-failure:true"); + this.context.register(EmbeddedDataSourceConfiguration.class, + DataSourceTransactionManagerAutoConfiguration.class); + this.context.refresh(); + DataSourceTransactionManager transactionManager = this.context.getBean(DataSourceTransactionManager.class); + assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); + assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); + } + @EnableTransactionManagement protected static class SwitchTransactionsOn { diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java index 1c2b4798acc..ff67fcf2461 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfigurationTests.java @@ -38,6 +38,7 @@ import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfigurati import org.springframework.boot.orm.jpa.hibernate.SpringJtaPlatform; import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import static org.assertj.core.api.Assertions.assertThat; @@ -171,6 +172,18 @@ public class HibernateJpaAutoConfigurationTests .isEqualTo(TestJtaPlatform.class.getName()); } + @Test + public void testCustomJpaTransactionManagerUsingProperties() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, + "spring.transaction.default-timeout:30", + "spring.transaction.rollback-on-commit-failure:true"); + setupTestConfiguration(); + this.context.refresh(); + JpaTransactionManager transactionManager = context.getBean(JpaTransactionManager.class); + assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); + assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); + } + public static class TestJtaPlatform implements JtaPlatform { @Override diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfigurationTests.java index f57b84e2fa2..2193e59155d 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/transaction/jta/JtaAutoConfigurationTests.java @@ -245,6 +245,32 @@ public class JtaAutoConfigurationTests { assertThat(dataSource.getMaxPoolSize()).isEqualTo(10); } + @Test + public void atomikosCustomizeJtaTransactionManagerUsingProperties() throws Exception { + this.context = new AnnotationConfigApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.transaction.default-timeout:30", + "spring.transaction.rollback-on-commit-failure:true"); + this.context.register(AtomikosJtaConfiguration.class); + this.context.refresh(); + JtaTransactionManager transactionManager = this.context.getBean(JtaTransactionManager.class); + assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); + assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); + } + + @Test + public void bitronixCustomizeJtaTransactionManagerUsingProperties() throws Exception { + this.context = new AnnotationConfigApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.transaction.default-timeout:30", + "spring.transaction.rollback-on-commit-failure:true"); + this.context.register(BitronixJtaConfiguration.class); + this.context.refresh(); + JtaTransactionManager transactionManager = this.context.getBean(JtaTransactionManager.class); + assertThat(transactionManager.getDefaultTimeout()).isEqualTo(30); + assertThat(transactionManager.isRollbackOnCommitFailure()).isTrue(); + } + @Configuration @EnableConfigurationProperties(JtaProperties.class) public static class JtaPropertiesConfiguration {