From 9e391e49df782592ae25f80dcc68b5beff5513b8 Mon Sep 17 00:00:00 2001 From: BenchmarkingBuffalo <46448799+benchmarkingbuffalo@users.noreply.github.com> Date: Fri, 9 Feb 2024 09:37:36 +0100 Subject: [PATCH] Add BatchTransactionManager Add a new annotation for marking a second PlatformTransactionManager to be used in batch processing. See gh-37650 --- .../batch/BatchAutoConfiguration.java | 7 ++- .../batch/BatchTransactionManager.java | 44 +++++++++++++++++++ .../batch/BatchAutoConfigurationTests.java | 36 +++++++++++++++ .../src/docs/asciidoc/howto/batch.adoc | 5 +++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchTransactionManager.java diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java index 22d3ffb19b34..7a2e4e2a5eb3 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java @@ -65,6 +65,7 @@ * @author Kazuki Shimizu * @author Mahmoud Ben Hassine * @author Lars Uffmann + * @author Lasse Wulff * @since 1.0.0 */ @AutoConfiguration(after = { HibernateJpaAutoConfiguration.class, TransactionAutoConfiguration.class }) @@ -108,11 +109,13 @@ static class SpringBootBatchConfiguration extends DefaultBatchConfiguration { private final ExecutionContextSerializer executionContextSerializer; SpringBootBatchConfiguration(DataSource dataSource, @BatchDataSource ObjectProvider batchDataSource, - PlatformTransactionManager transactionManager, BatchProperties properties, + PlatformTransactionManager transactionManager, + @BatchTransactionManager ObjectProvider batchTransactionManager, + BatchProperties properties, ObjectProvider batchConversionServiceCustomizers, ObjectProvider executionContextSerializer) { this.dataSource = batchDataSource.getIfAvailable(() -> dataSource); - this.transactionManager = transactionManager; + this.transactionManager = batchTransactionManager.getIfAvailable(() -> transactionManager); this.properties = properties; this.batchConversionServiceCustomizers = batchConversionServiceCustomizers.orderedStream().toList(); this.executionContextSerializer = executionContextSerializer diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchTransactionManager.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchTransactionManager.java new file mode 100644 index 000000000000..a2ec189a10ea --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchTransactionManager.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012-2014 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 + * + * https://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.batch; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Primary; +import org.springframework.transaction.PlatformTransactionManager; + +/** + * Qualifier annotation for a {@link PlatformTransactionManager + * PlatformTransactionManager} to be injected into Batch auto-configuration. Can be used + * on a secondary {@link PlatformTransactionManager PlatformTransactionManager}, if there + * is another one marked as {@link Primary @Primary}. + * + * @author Lasse Wulff + * @since 3.3.0 + */ +@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Qualifier +public @interface BatchTransactionManager { + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java index 16b1c2353031..ddc298d7a41c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfigurationTests.java @@ -80,6 +80,7 @@ import org.springframework.context.annotation.Primary; import org.springframework.core.annotation.Order; import org.springframework.core.convert.support.ConfigurableConversionService; +import org.springframework.integration.transaction.PseudoTransactionManager; import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; @@ -102,6 +103,7 @@ * @author Kazuki Shimizu * @author Mahmoud Ben Hassine * @author Lars Uffmann + * @author Lasse Wulff */ @ExtendWith(OutputCaptureExtension.class) class BatchAutoConfigurationTests { @@ -351,6 +353,18 @@ void testBatchDataSource() { }); } + @Test + void testBatchTransactionManager() { + this.contextRunner.withUserConfiguration(TestConfiguration.class, BatchTransactionManagerConfiguration.class) + .run((context) -> { + assertThat(context).hasSingleBean(SpringBootBatchConfiguration.class); + PlatformTransactionManager batchTransactionManager = context.getBean("batchTransactionManager", + PlatformTransactionManager.class); + assertThat(context.getBean(SpringBootBatchConfiguration.class).getTransactionManager()) + .isEqualTo(batchTransactionManager); + }); + } + @Test void jobRepositoryBeansDependOnBatchDataSourceInitializer() { this.contextRunner.withUserConfiguration(TestConfiguration.class, EmbeddedDataSourceConfiguration.class) @@ -519,6 +533,28 @@ public DataSource batchDataSource() { } + @Configuration(proxyBeanMethods = false) + protected static class BatchTransactionManagerConfiguration { + + @Bean + public DataSource dataSource() { + return DataSourceBuilder.create().url("jdbc:hsqldb:mem:database").username("sa").build(); + } + + @Bean + @Primary + public PlatformTransactionManager normalTransactionManager() { + return new PseudoTransactionManager(); + } + + @BatchTransactionManager + @Bean + public PlatformTransactionManager batchTransactionManager() { + return new PseudoTransactionManager(); + } + + } + @Configuration(proxyBeanMethods = false) static class EmptyConfiguration { diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/batch.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/batch.adoc index c03c81520509..4d88b6ff79c3 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/batch.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/howto/batch.adoc @@ -17,6 +17,11 @@ and {spring-batch-api}/core/configuration/support/DefaultBatchConfiguration.html For more info about Spring Batch, see the {spring-batch}[Spring Batch project page]. +=== Specifying a Batch Transaction Manager +Similar to <> you can also define a `PlatformTransactionManager` +for use in the batch processing by marking it as `@BatchTransactionManager`. +If you do so and want two transaction managers, remember to mark the other one as `@Primary`. + [[howto.batch.running-jobs-on-startup]]