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 251601ba28..5437f5e407 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 @@ -33,6 +33,7 @@ import org.springframework.batch.core.repository.support.JobRepositoryFactoryBea import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.support.AbstractPlatformTransactionManager; import org.springframework.util.StringUtils; /** @@ -40,6 +41,7 @@ import org.springframework.util.StringUtils; * * @author Dave Syer * @author Andy Wilkinson + * @author Kazuki Shimizu */ public class BasicBatchConfigurer implements BatchConfigurer { @@ -150,6 +152,12 @@ public class BasicBatchConfigurer implements BatchConfigurer { } protected PlatformTransactionManager createTransactionManager() { + AbstractPlatformTransactionManager transactionManager = createAppropriateTransactionManager(); + this.properties.getTransaction().applyTo(transactionManager); + return transactionManager; + } + + private AbstractPlatformTransactionManager createAppropriateTransactionManager() { if (this.entityManagerFactory != null) { return new JpaTransactionManager(this.entityManagerFactory); } 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 cb9c3515c8..2586c8621a 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 @@ -42,6 +42,7 @@ 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 +58,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,7 +135,8 @@ public class BatchAutoConfiguration { return factory; } - @ConditionalOnClass(name = "javax.persistence.EntityManagerFactory") + @EnableConfigurationProperties(BatchProperties.class) + @ConditionalOnClass(value = PlatformTransactionManager.class, name = "javax.persistence.EntityManagerFactory") @ConditionalOnMissingBean(BatchConfigurer.class) @Configuration protected static class JpaBatchConfiguration { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchProperties.java index 9582a05f34..998098416d 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchProperties.java @@ -16,7 +16,9 @@ package org.springframework.boot.autoconfigure.batch; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; /** * Configuration properties for Spring Batch. @@ -46,6 +48,9 @@ public class BatchProperties { private final Job job = new Job(); + @NestedConfigurationProperty + private final TransactionProperties transaction = new TransactionProperties(); + public String getSchema() { return this.schema; } @@ -54,6 +59,14 @@ public class BatchProperties { this.schema = schema; } + public String getTablePrefix() { + return this.tablePrefix; + } + + public void setTablePrefix(String tablePrefix) { + this.tablePrefix = tablePrefix; + } + public Initializer getInitializer() { return this.initializer; } @@ -62,12 +75,8 @@ public class BatchProperties { return this.job; } - public void setTablePrefix(String tablePrefix) { - this.tablePrefix = tablePrefix; - } - - public String getTablePrefix() { - return this.tablePrefix; + public TransactionProperties getTransaction() { + return this.transaction; } public class Initializer { 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 e5743e2595..f0a069b1b9 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 @@ -48,10 +48,11 @@ 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) @SuppressWarnings("deprecation") @@ -87,8 +88,12 @@ public class Neo4jDataAutoConfiguration { @Bean @ConditionalOnMissingBean(PlatformTransactionManager.class) - public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory) { - return new Neo4jTransactionManager(sessionFactory); + public Neo4jTransactionManager transactionManager(SessionFactory sessionFactory, + Neo4jProperties properties) { + Neo4jTransactionManager transactionManager = new Neo4jTransactionManager( + sessionFactory); + properties.getTransaction().applyTo(transactionManager); + return transactionManager; } private String[] getPackagesToScan(ApplicationContext applicationContext) { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jProperties.java index e58bda102b..030b69cee6 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/neo4j/Neo4jProperties.java @@ -23,7 +23,9 @@ import org.neo4j.ogm.config.Configuration; import org.neo4j.ogm.config.DriverConfiguration; import org.springframework.beans.BeansException; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.util.ClassUtils; @@ -69,6 +71,9 @@ public class Neo4jProperties implements ApplicationContextAware { private final Embedded embedded = new Embedded(); + @NestedConfigurationProperty + private final TransactionProperties transaction = new TransactionProperties(); + private ClassLoader classLoader = Neo4jProperties.class.getClassLoader(); public String getUri() { @@ -107,6 +112,10 @@ public class Neo4jProperties implements ApplicationContextAware { return this.embedded; } + public TransactionProperties getTransaction() { + return this.transaction; + } + @Override public void setApplicationContext(ApplicationContext ctx) throws BeansException { this.classLoader = ctx.getClassLoader(); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java index 6b79062f89..be1b5a130d 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceProperties.java @@ -27,7 +27,9 @@ import javax.sql.DataSource; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.InitializingBean; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.boot.jdbc.DatabaseDriver; import org.springframework.context.EnvironmentAware; import org.springframework.core.env.Environment; @@ -157,6 +159,9 @@ public class DataSourceProperties private String uniqueName; + @NestedConfigurationProperty + private final TransactionProperties transaction = new TransactionProperties(); + @Override public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; @@ -473,6 +478,10 @@ public class DataSourceProperties this.xa = xa; } + public TransactionProperties getTransaction() { + return this.transaction; + } + /** * XA Specific datasource settings. */ 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 d5feaf1352..931da19c9c 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,7 @@ 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.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; @@ -39,10 +40,12 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; * @author Dave Syer * @author Stephane Nicoll * @author Andy Wilkinson + * @author Kazuki Shimizu */ @Configuration @ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class }) @AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE) +@EnableConfigurationProperties(DataSourceProperties.class) public class DataSourceTransactionManagerAutoConfiguration { @Configuration @@ -57,8 +60,12 @@ public class DataSourceTransactionManagerAutoConfiguration { @Bean @ConditionalOnMissingBean(PlatformTransactionManager.class) - public DataSourceTransactionManager transactionManager() { - return new DataSourceTransactionManager(this.dataSource); + public DataSourceTransactionManager transactionManager( + DataSourceProperties properties) { + DataSourceTransactionManager transactionManager = new DataSourceTransactionManager( + this.dataSource); + properties.getTransaction().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 67d1ccbd96..48f79d2ff0 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 @@ -59,6 +59,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter * @author Dave Syer * @author Oliver Gierke * @author Andy Wilkinson + * @author Kazuki Shimizu */ @EnableConfigurationProperties(JpaProperties.class) @Import(DataSourceInitializedPublisher.Registrar.class) @@ -82,7 +83,9 @@ public abstract class JpaBaseConfiguration implements BeanFactoryAware { @Bean @ConditionalOnMissingBean(PlatformTransactionManager.class) public PlatformTransactionManager transactionManager() { - return new JpaTransactionManager(); + JpaTransactionManager transactionManager = new JpaTransactionManager(); + this.properties.getTransaction().applyTo(transactionManager); + return transactionManager; } @Bean diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaProperties.java index ecb118b4ff..aee5121b81 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/orm/jpa/JpaProperties.java @@ -22,6 +22,7 @@ import java.util.Map; import javax.sql.DataSource; import org.springframework.boot.autoconfigure.jdbc.EmbeddedDatabaseConnection; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.orm.jpa.vendor.Database; @@ -67,6 +68,9 @@ public class JpaProperties { private Hibernate hibernate = new Hibernate(); + @NestedConfigurationProperty + private final TransactionProperties transaction = new TransactionProperties(); + public Map getProperties() { return this.properties; } @@ -125,6 +129,10 @@ public class JpaProperties { return this.hibernate.getAdditionalProperties(this.properties, dataSource); } + public TransactionProperties getTransaction() { + return this.transaction; + } + public static class Hibernate { private static final String USE_NEW_ID_GENERATOR_MAPPINGS = "hibernate.id." 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 0000000000..619c368b84 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/TransactionProperties.java @@ -0,0 +1,69 @@ +/* + * 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.transaction.support.AbstractPlatformTransactionManager; + +/** + * Nested configuration properties that can be applied to an + * {@link AbstractPlatformTransactionManager}. + * + * @author Kazuki Shimizu + * @since 1.5.0 + */ +public class TransactionProperties { + + /** + * Default transaction timeout in seconds. + */ + private Integer defaultTimeout; + + /** + * Perform the rollback on commit failurures. + */ + 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 the specified transaction manager. + * @param transactionManager the target transaction manager + */ + public void applyTo(AbstractPlatformTransactionManager transactionManager) { + if (this.defaultTimeout != null) { + transactionManager.setDefaultTimeout(this.defaultTimeout); + } + if (this.rollbackOnCommitFailure != null) { + transactionManager.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 bde242ed0b..308fe36e7c 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 @@ -50,10 +50,11 @@ 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 }) @ConditionalOnClass({ JtaTransactionManager.class, UserTransactionManager.class }) @ConditionalOnMissingBean(PlatformTransactionManager.class) class AtomikosJtaConfiguration { @@ -111,7 +112,10 @@ class AtomikosJtaConfiguration { @Bean public JtaTransactionManager transactionManager(UserTransaction userTransaction, TransactionManager transactionManager) { - return new JtaTransactionManager(userTransaction, transactionManager); + JtaTransactionManager jtaTransactionManager = new JtaTransactionManager( + userTransaction, transactionManager); + this.jtaProperties.getTransaction().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 c10098ce14..36e27bc738 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 @@ -29,6 +29,7 @@ import org.springframework.boot.ApplicationHome; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 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,9 +47,11 @@ 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) @ConditionalOnClass({ JtaTransactionManager.class, BitronixContext.class }) @ConditionalOnMissingBean(PlatformTransactionManager.class) class BitronixJtaConfiguration { @@ -105,7 +108,10 @@ class BitronixJtaConfiguration { @Bean public JtaTransactionManager transactionManager( TransactionManager transactionManager) { - return new JtaTransactionManager(transactionManager); + JtaTransactionManager jtaTransactionManager = new JtaTransactionManager( + transactionManager); + this.jtaProperties.getTransaction().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 12f20dd39f..478a898a45 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 @@ -30,6 +30,7 @@ import org.springframework.transaction.jta.JtaTransactionManager; * * @author Phillip Webb * @author Stephane Nicoll + * @author Kazuki Shimizu * @since 1.2.0 */ @Configuration @@ -40,9 +41,18 @@ import org.springframework.transaction.jta.JtaTransactionManager; @ConditionalOnMissingBean(PlatformTransactionManager.class) class JndiJtaConfiguration { + private final JtaProperties jtaProperties; + + JndiJtaConfiguration(JtaProperties jtaProperties) { + this.jtaProperties = jtaProperties; + } + @Bean public JtaTransactionManager transactionManager() { - return new JtaTransactionManagerFactoryBean().getObject(); + JtaTransactionManager transactionManager = new JtaTransactionManagerFactoryBean() + .getObject(); + this.jtaProperties.getTransaction().applyTo(transactionManager); + return transactionManager; } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaProperties.java index 124bba9434..bbf63e4b53 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaProperties.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/transaction/jta/JtaProperties.java @@ -16,7 +16,9 @@ package org.springframework.boot.autoconfigure.transaction.jta; +import org.springframework.boot.autoconfigure.transaction.TransactionProperties; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.transaction.jta.JtaTransactionManager; /** @@ -42,6 +44,9 @@ public class JtaProperties { */ private String transactionManagerId; + @NestedConfigurationProperty + private final TransactionProperties transaction = new TransactionProperties(); + public void setLogDir(String logDir) { this.logDir = logDir; } @@ -58,4 +63,8 @@ public class JtaProperties { this.transactionManagerId = transactionManagerId; } + public TransactionProperties getTransaction() { + return this.transaction; + } + } 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 31394d6ed9..ec97194374 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,7 @@ 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.context.properties.EnableConfigurationProperties; import org.springframework.boot.jta.XAConnectionFactoryWrapper; import org.springframework.boot.jta.XADataSourceWrapper; import org.springframework.boot.jta.narayana.NarayanaBeanFactoryPostProcessor; @@ -47,12 +48,14 @@ 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) public class NarayanaJtaConfiguration { private final JtaProperties jtaProperties; @@ -116,7 +119,10 @@ public class NarayanaJtaConfiguration { @Bean public JtaTransactionManager transactionManager(UserTransaction userTransaction, TransactionManager transactionManager) { - return new JtaTransactionManager(userTransaction, transactionManager); + JtaTransactionManager jtaTransactionManager = new JtaTransactionManager( + userTransaction, transactionManager); + this.jtaProperties.getTransaction().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 c668df5019..327ee070ca 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; @@ -68,6 +70,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Dave Syer * @author Stephane Nicoll * @author Vedran Pavic + * @author Kazuki Shimizu */ public class BatchAutoConfigurationTests { @@ -267,6 +270,43 @@ public class BatchAutoConfigurationTests { .queryForList("select * from BATCH_JOB_EXECUTION"); } + @Test + public void testCustomizeJpaTransactionManagerUsingProperties() throws Exception { + this.context = new AnnotationConfigApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.batch.transaction.default-timeout:30", + "spring.batch.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.batch.transaction.default-timeout:30", + "spring.batch.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 25fc2b5662..38044b7488 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; @@ -53,6 +54,7 @@ import static org.mockito.Mockito.verify; * @author Michael Hunger * @author Vince Bickers * @author Andy Wilkinson + * @author Kazuki Shimizu */ @SuppressWarnings("deprecation") public class Neo4jDataAutoConfigurationTests { @@ -73,10 +75,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.data.neo4j.transaction.default-timeout=30", + "spring.data.neo4j.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 93b44a1414..16c331edc7 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,21 @@ public class DataSourceTransactionManagerAutoConfigurationTests { .isNotNull(); } + @Test + public void testCustomizeDataSourceTransactionManagerUsingProperties() + throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, + "spring.datasource.transaction.default-timeout:30", + "spring.datasource.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 1c2b4798ac..a45cbba8d5 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; @@ -48,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Dave Syer * @author Phillip Webb * @author Andy Wilkinson + * @author Kazuki Shimizu */ public class HibernateJpaAutoConfigurationTests extends AbstractJpaAutoConfigurationTests { @@ -171,6 +173,19 @@ public class HibernateJpaAutoConfigurationTests .isEqualTo(TestJtaPlatform.class.getName()); } + @Test + public void testCustomJpaTransactionManagerUsingProperties() throws Exception { + EnvironmentTestUtils.addEnvironment(this.context, + "spring.jpa.transaction.default-timeout:30", + "spring.jpa.transaction.rollback-on-commit-failure:true"); + setupTestConfiguration(); + this.context.refresh(); + JpaTransactionManager transactionManager = this.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 f57b84e2fa..70239874a6 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 @@ -69,6 +69,7 @@ import static org.mockito.Mockito.mock; * @author Josh Long * @author Phillip Webb * @author Andy Wilkinson + * @author Kazuki Shimizu */ public class JtaAutoConfigurationTests { @@ -245,6 +246,34 @@ public class JtaAutoConfigurationTests { assertThat(dataSource.getMaxPoolSize()).isEqualTo(10); } + @Test + public void atomikosCustomizeJtaTransactionManagerUsingProperties() throws Exception { + this.context = new AnnotationConfigApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.jta.transaction.default-timeout:30", + "spring.jta.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.jta.transaction.default-timeout:30", + "spring.jta.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 { diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 43267fbfce..196d51c2f4 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -582,6 +582,7 @@ content into your application; rather pick only the properties that you need. spring.data.neo4j.open-in-view=false # Register OpenSessionInViewInterceptor. Binds a Neo4j Session to the thread for the entire processing of the request. spring.data.neo4j.password= # Login password of the server. spring.data.neo4j.repositories.enabled=true # Enable Neo4j repositories. + spring.data.neo4j.transaction.*= # Transaction manager settings spring.data.neo4j.uri= # URI used by the driver. Auto-detected by default. spring.data.neo4j.username= # Login user of the server. @@ -623,6 +624,7 @@ content into your application; rather pick only the properties that you need. spring.datasource.separator=; # Statement separator in SQL initialization scripts. spring.datasource.sql-script-encoding= # SQL scripts encoding. spring.datasource.tomcat.*= # Tomcat datasource specific settings + spring.datasource.transaction.*= # Transaction manager settings spring.datasource.type= # Fully qualified name of the connection pool implementation to use. By default, it is auto-detected from the classpath. spring.datasource.url= # JDBC url of the database. spring.datasource.username= @@ -658,10 +660,12 @@ content into your application; rather pick only the properties that you need. spring.jpa.open-in-view=true # Register OpenEntityManagerInViewInterceptor. Binds a JPA EntityManager to the thread for the entire processing of the request. spring.jpa.properties.*= # Additional native properties to set on the JPA provider. spring.jpa.show-sql=false # Enable logging of SQL statements. + spring.jpa.transaction.*= # Transaction manager settings # JTA ({sc-spring-boot-autoconfigure}/transaction/jta/JtaAutoConfiguration.{sc-ext}[JtaAutoConfiguration]) spring.jta.enabled=true # Enable JTA support. spring.jta.log-dir= # Transaction logs directory. + spring.jta.transaction.*= # Transaction manager settings spring.jta.transaction-manager-id= # Transaction manager unique identifier. # ATOMIKOS ({sc-spring-boot}/jta/atomikos/AtomikosProperties.{sc-ext}[AtomikosProperties]) @@ -844,6 +848,7 @@ content into your application; rather pick only the properties that you need. spring.batch.job.names= # Comma-separated list of job names to execute on startup (For instance `job1,job2`). By default, all Jobs found in the context are executed. spring.batch.schema=classpath:org/springframework/batch/core/schema-@@platform@@.sql # Path to the SQL file to use to initialize the database schema. spring.batch.table-prefix= # Table prefix for all the batch meta-data tables. + spring.batch.transaction.*= # Transaction manager settings # JMS ({sc-spring-boot-autoconfigure}/jms/JmsProperties.{sc-ext}[JmsProperties]) spring.jms.jndi-name= # Connection factory JNDI name. When set, takes precedence to others connection factory auto-configurations.