From 7c8fb172a7cfb8d61d54f530c564b836d83d0a21 Mon Sep 17 00:00:00 2001 From: Mahmoud Ben Hassine Date: Fri, 2 Sep 2022 10:35:02 +0200 Subject: [PATCH] Move the transaction manager configuration to AbstractTaskletStepBuilder Before this commit, the transaction manager was configurable at the StepBuilder level, which is inconsistent with the XML config style in addition to be not needed for most step types. This commit moves the configuration of the transaction manager from the StepBuilder down to the AbstractTaskletStepBuilder, which is the level where the transaction manager is needed. Resolves #4130 --- .../AbstractBatchConfiguration.java | 3 +- .../annotation/StepBuilderFactory.java | 20 ++++------ .../xml/StepParserStepFactoryBean.java | 4 +- .../builder/AbstractTaskletStepBuilder.java | 21 ++++++++++ .../core/step/builder/SimpleStepBuilder.java | 2 + .../core/step/builder/StepBuilderHelper.java | 28 +------------ .../JobBuilderConfigurationTests.java | 23 +++++++++-- .../JobLoaderConfigurationTests.java | 9 +++-- .../core/job/builder/FlowJobBuilderTests.java | 17 ++++++-- .../core/job/builder/JobBuilderTests.java | 13 ++++++- .../core/listener/ItemListenerErrorTests.java | 19 ++++++--- .../core/observability/BatchMetricsTests.java | 17 +++++++- .../FaultTolerantStepBuilderTests.java | 5 ++- .../builder/RegisterMultiListenerTests.java | 20 ++++++++-- .../core/step/builder/StepBuilderTests.java | 39 ++++++++++--------- .../ConcurrentTransactionTests.java | 31 +++++++++------ .../Db2JobRepositoryIntegrationTests.java | 13 ++++++- .../DerbyJobRepositoryIntegrationTests.java | 13 ++++++- ...lityModeJobRepositoryIntegrationTests.java | 13 ++++++- .../H2JobRepositoryIntegrationTests.java | 13 ++++++- .../HSQLDBJobRepositoryIntegrationTests.java | 13 ++++++- ...ySQLJdbcJobRepositoryIntegrationTests.java | 12 +++++- .../MySQLJobRepositoryIntegrationTests.java | 13 ++++++- ...stgreSQLJobRepositoryIntegrationTests.java | 13 ++++++- ...QLServerJobRepositoryIntegrationTests.java | 13 ++++++- .../SQLiteJobRepositoryIntegrationTests.java | 13 ++++++- .../FaultTolerantStepIntegrationTests.java | 16 ++++---- .../BatchIntegrationConfiguration.java | 6 +-- .../RemotePartitioningManagerStepBuilder.java | 6 --- ...PartitioningManagerStepBuilderFactory.java | 12 ++---- .../RemotePartitioningWorkerStepBuilder.java | 6 --- ...ePartitioningWorkerStepBuilderFactory.java | 12 ++---- .../config/DataSourceConfiguration.java | 8 +++- .../config/RetrySampleConfiguration.java | 10 +++-- .../aggregating/WorkerConfiguration.java | 5 ++- .../polling/WorkerConfiguration.java | 6 ++- .../sample/skip/DataSourceConfiguration.java | 8 +++- ...SkippableExceptionDuringProcessSample.java | 14 ++++--- .../SkippableExceptionDuringReadSample.java | 14 ++++--- .../SkippableExceptionDuringWriteSample.java | 14 ++++--- .../ValidationSampleConfiguration.java | 12 ++++-- .../sample/JsonSupportIntegrationTests.java | 9 ++++- .../batch/test/JobLauncherTestUtilsTests.java | 8 +++- .../test/SpringBatchTestJUnit4Tests.java | 13 ++++++- .../test/SpringBatchTestJUnit5Tests.java | 12 +++++- ...copeAnnotatedListenerIntegrationTests.java | 13 ++++++- 46 files changed, 409 insertions(+), 195 deletions(-) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java index 5b744e77b..4d75da6ac 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/AbstractBatchConfiguration.java @@ -127,8 +127,7 @@ public abstract class AbstractBatchConfiguration implements InitializingBean { public void afterPropertiesSet() throws Exception { BatchConfigurer batchConfigurer = getOrCreateConfigurer(); this.jobBuilderFactory = new JobBuilderFactory(batchConfigurer.getJobRepository()); - this.stepBuilderFactory = new StepBuilderFactory(batchConfigurer.getJobRepository(), - batchConfigurer.getTransactionManager()); + this.stepBuilderFactory = new StepBuilderFactory(batchConfigurer.getJobRepository()); } /** diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java index aa3a8179e..ea56a6ee8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/StepBuilderFactory.java @@ -21,8 +21,8 @@ import org.springframework.transaction.PlatformTransactionManager; import org.springframework.util.Assert; /** - * Convenient factory for a {@link StepBuilder} which sets the {@link JobRepository} and - * {@link PlatformTransactionManager} automatically. + * Convenient factory for a {@link StepBuilder} which sets the {@link JobRepository} + * automatically. * * @author Dave Syer * @author Mahmoud Ben Hassine @@ -32,31 +32,25 @@ public class StepBuilderFactory { private JobRepository jobRepository; - private PlatformTransactionManager transactionManager; - /** * Constructor for the {@link StepBuilderFactory}. * @param jobRepository The {@link JobRepository} to be used by the builder factory. * Must not be {@code null}. - * @param transactionManager The {@link PlatformTransactionManager} to be used by the - * builder factory. Must not be {@code null}. */ - public StepBuilderFactory(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + public StepBuilderFactory(JobRepository jobRepository) { Assert.notNull(jobRepository, "JobRepository must not be null"); - Assert.notNull(transactionManager, "transactionManager must not be null"); this.jobRepository = jobRepository; - this.transactionManager = transactionManager; } /** - * Creates a step builder and initializes its job repository and transaction manager. - * Note that, if the builder is used to create a @Bean definition, the name of the - * step and the bean name might be different. + * Creates a step builder and initializes its job repository. Note that, if the + * builder is used to create a @Bean definition, the name of the step and the bean + * name might be different. * @param name the name of the step * @return a step builder */ public StepBuilder get(String name) { - return new StepBuilder(name).repository(this.jobRepository).transactionManager(this.transactionManager); + return new StepBuilder(name).repository(this.jobRepository); } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java index c3e08bf6d..6c505cf20 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StepParserStepFactoryBean.java @@ -275,7 +275,6 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN builder.startLimit(startLimit); } builder.repository(jobRepository); - builder.transactionManager(transactionManager); for (Object listener : stepExecutionListeners) { if (listener instanceof StepExecutionListener) { builder.listener((StepExecutionListener) listener); @@ -454,7 +453,8 @@ public class StepParserStepFactoryBean implements FactoryBean, BeanN * @return a new {@link TaskletStep} */ protected TaskletStep createTaskletStep() { - TaskletStepBuilder builder = new StepBuilder(name).tasklet(tasklet); + TaskletStepBuilder builder = new TaskletStepBuilder(new StepBuilder(name)) + .transactionManager(transactionManager).tasklet(tasklet); enhanceTaskletStepBuilder(builder); return builder.build(); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java index 231e8508d..31697bc3f 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/AbstractTaskletStepBuilder.java @@ -38,6 +38,7 @@ import org.springframework.batch.repeat.support.TaskExecutorRepeatTemplate; import org.springframework.batch.support.ReflectionUtils; import org.springframework.core.task.SyncTaskExecutor; import org.springframework.core.task.TaskExecutor; +import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.interceptor.TransactionAttribute; /** @@ -57,6 +58,8 @@ public abstract class AbstractTaskletStepBuilder streams = new LinkedHashSet<>(); @@ -89,6 +92,10 @@ public abstract class AbstractTaskletStepBuilder extends AbstractTaskletStepBuilder faultTolerant() { diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java index a2f63f0f9..1d2c05cdf 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/builder/StepBuilderHelper.java @@ -36,10 +36,11 @@ import java.util.Set; /** * A base class and utility for other step builders providing access to common properties - * like job repository and transaction manager. + * like job repository and listeners. * * @author Dave Syer * @author Michael Minella + * @author Mahmoud Ben Hassine * @since 2.2 */ public abstract class StepBuilderHelper> { @@ -67,11 +68,6 @@ public abstract class StepBuilderHelper> { return self(); } - public B transactionManager(PlatformTransactionManager transactionManager) { - properties.transactionManager = transactionManager; - return self(); - } - public B startLimit(int startLimit) { properties.startLimit = startLimit; return self(); @@ -116,10 +112,6 @@ public abstract class StepBuilderHelper> { return properties.jobRepository; } - protected PlatformTransactionManager getTransactionManager() { - return properties.transactionManager; - } - protected boolean isAllowStartIfComplete() { return properties.allowStartIfComplete != null ? properties.allowStartIfComplete : false; } @@ -145,11 +137,6 @@ public abstract class StepBuilderHelper> { } - if (target instanceof TaskletStep) { - TaskletStep step = (TaskletStep) target; - step.setTransactionManager(properties.transactionManager); - } - } public static class CommonStepProperties { @@ -162,8 +149,6 @@ public abstract class StepBuilderHelper> { private JobRepository jobRepository; - private PlatformTransactionManager transactionManager; - public CommonStepProperties() { } @@ -172,7 +157,6 @@ public abstract class StepBuilderHelper> { this.startLimit = properties.startLimit; this.allowStartIfComplete = properties.allowStartIfComplete; this.jobRepository = properties.jobRepository; - this.transactionManager = properties.transactionManager; this.stepExecutionListeners = new ArrayList<>(properties.stepExecutionListeners); } @@ -184,14 +168,6 @@ public abstract class StepBuilderHelper> { this.jobRepository = jobRepository; } - public PlatformTransactionManager getTransactionManager() { - return transactionManager; - } - - public void setTransactionManager(PlatformTransactionManager transactionManager) { - this.transactionManager = transactionManager; - } - public String getName() { return name; } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java index b10ef54d6..97e539689 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobBuilderConfigurationTests.java @@ -41,6 +41,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.lang.Nullable; /** @@ -114,6 +115,9 @@ public class JobBuilderConfigurationTests { @Autowired private StepBuilderFactory steps; + @Autowired + private JdbcTransactionManager transactionManager; + @Bean public Job testJob() throws Exception { SimpleJobBuilder builder = jobs.get("test").start(step1()).next(step2()); @@ -122,12 +126,12 @@ public class JobBuilderConfigurationTests { @Bean protected Step step1() throws Exception { - return steps.get("step1").tasklet(tasklet()).build(); + return steps.get("step1").tasklet(tasklet()).transactionManager(this.transactionManager).build(); } @Bean protected Step step2() throws Exception { - return steps.get("step2").tasklet(tasklet()).build(); + return steps.get("step2").tasklet(tasklet()).transactionManager(this.transactionManager).build(); } @Bean @@ -157,6 +161,9 @@ public class JobBuilderConfigurationTests { @Autowired private StepBuilderFactory steps; + @Autowired + private JdbcTransactionManager transactionManager; + @Autowired private Tasklet tasklet; @@ -168,7 +175,7 @@ public class JobBuilderConfigurationTests { @Bean protected Step step3() throws Exception { - return steps.get("step3").tasklet(tasklet).build(); + return steps.get("step3").tasklet(tasklet).transactionManager(this.transactionManager).build(); } } @@ -217,6 +224,9 @@ public class JobBuilderConfigurationTests { @Autowired private StepBuilderFactory steps; + @Autowired + private JdbcTransactionManager transactionManager; + @Bean public Job beansConfigurerJob() throws Exception { SimpleJobBuilder builder = jobs.get("beans").start(step1()); @@ -232,7 +242,7 @@ public class JobBuilderConfigurationTests { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { return null; } - }).build(); + }).transactionManager(this.transactionManager).build(); } @Bean @@ -252,6 +262,11 @@ public class JobBuilderConfigurationTests { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java index e98f46492..864cc0889 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/configuration/annotation/JobLoaderConfigurationTests.java @@ -37,6 +37,7 @@ import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.scope.context.ChunkContext; import org.springframework.batch.core.step.tasklet.Tasklet; import org.springframework.batch.repeat.RepeatStatus; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; @@ -135,12 +136,14 @@ class JobLoaderConfigurationTests { @Bean protected Step step1() throws Exception { - return steps.get("step1").tasklet(tasklet()).build(); + return steps.get("step1").tasklet(tasklet()).transactionManager(new ResourcelessTransactionManager()) + .build(); } @Bean protected Step step2() throws Exception { - return steps.get("step2").tasklet(tasklet()).build(); + return steps.get("step2").tasklet(tasklet()).transactionManager(new ResourcelessTransactionManager()) + .build(); } @Bean @@ -179,7 +182,7 @@ class JobLoaderConfigurationTests { public RepeatStatus execute(StepContribution contribution, ChunkContext context) throws Exception { return RepeatStatus.FINISHED; } - }).build(); + }).transactionManager(new ResourcelessTransactionManager()).build(); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java index 7feb030a2..800dca4d7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/FlowJobBuilderTests.java @@ -55,6 +55,7 @@ import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.lang.Nullable; +import org.springframework.transaction.PlatformTransactionManager; /** * @author Dave Syer @@ -289,16 +290,19 @@ class FlowJobBuilderTests { @Bean @JobScope - public Step step(StepBuilderFactory stepBuilderFactory, + public Step step(StepBuilderFactory stepBuilderFactory, PlatformTransactionManager transactionManager, @Value("#{jobParameters['chunkSize']}") Integer chunkSize) { return stepBuilderFactory.get("step").chunk(chunkSize) - .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4))).writer(items -> { + .transactionManager(transactionManager).reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4))) + .writer(items -> { }).build(); } @Bean - public Job job(JobBuilderFactory jobBuilderFactory) { - return jobBuilderFactory.get("job").flow(step(null, null)).build().build(); + public Job job(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, + PlatformTransactionManager transactionManager) { + Step step = step(stepBuilderFactory, transactionManager, null); + return jobBuilderFactory.get("job").flow(step).build().build(); } @Bean @@ -307,6 +311,11 @@ class FlowJobBuilderTests { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/JobBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/JobBuilderTests.java index 5cd6f159f..7b5a3f19e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/JobBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/builder/JobBuilderTests.java @@ -36,6 +36,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.support.JdbcTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -68,10 +70,12 @@ class JobBuilderTests { static class MyJobConfiguration { @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job").listener(new InterfaceBasedJobExecutionListener()) .listener(new AnnotationBasedJobExecutionListener()) - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } @@ -81,6 +85,11 @@ class JobBuilderTests { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } static class InterfaceBasedJobExecutionListener implements JobExecutionListener { diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ItemListenerErrorTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ItemListenerErrorTests.java index 50ca6bc75..666352d8e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ItemListenerErrorTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/listener/ItemListenerErrorTests.java @@ -46,9 +46,11 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.lang.Nullable; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; /** * BATCH-2322 @@ -134,13 +136,13 @@ class ItemListenerErrorTests { } @Bean - public Step step1(StepBuilderFactory stepBuilderFactory, ItemReader fakeItemReader, - ItemProcessor fakeProcessor, ItemWriter fakeItemWriter, - ItemProcessListener itemProcessListener) { + public Step step1(StepBuilderFactory stepBuilderFactory, PlatformTransactionManager transactionManager, + ItemReader fakeItemReader, ItemProcessor fakeProcessor, + ItemWriter fakeItemWriter, ItemProcessListener itemProcessListener) { - return stepBuilderFactory.get("testStep").chunk(10).reader(fakeItemReader) - .processor(fakeProcessor).writer(fakeItemWriter).listener(itemProcessListener).faultTolerant() - .skipLimit(50).skip(RuntimeException.class).build(); + return stepBuilderFactory.get("testStep").chunk(10).transactionManager(transactionManager) + .reader(fakeItemReader).processor(fakeProcessor).writer(fakeItemWriter) + .listener(itemProcessListener).faultTolerant().skipLimit(50).skip(RuntimeException.class).build(); } @Bean @@ -149,6 +151,11 @@ class ItemListenerErrorTests { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + @Bean public FailingListener itemListener() { return new FailingListener(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/observability/BatchMetricsTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/observability/BatchMetricsTests.java index 5aee7586a..09c6ae22a 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/observability/BatchMetricsTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/observability/BatchMetricsTests.java @@ -46,6 +46,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.support.JdbcTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -224,20 +226,25 @@ class BatchMetricsTests { private StepBuilderFactory stepBuilderFactory; - public MyJobConfiguration(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) { + private PlatformTransactionManager transactionManager; + + public MyJobConfiguration(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, + PlatformTransactionManager transactionManager) { this.jobBuilderFactory = jobBuilderFactory; this.stepBuilderFactory = stepBuilderFactory; + this.transactionManager = transactionManager; } @Bean public Step step1() { return stepBuilderFactory.get("step1").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) - .build(); + .transactionManager(this.transactionManager).build(); } @Bean public Step step2() { return stepBuilderFactory.get("step2").chunk(2) + .transactionManager(this.transactionManager) .reader(new ListItemReader<>(Arrays.asList(1, 2, 3, 4, 5))) .writer(items -> items.forEach(System.out::println)).build(); } @@ -245,6 +252,7 @@ class BatchMetricsTests { @Bean public Step step3() { return stepBuilderFactory.get("step3").chunk(2) + .transactionManager(this.transactionManager) .reader(new ListItemReader<>(Arrays.asList(6, 7, 8, 9, 10))) .writer(items -> items.forEach(System.out::println)).faultTolerant().skip(Exception.class) .skipLimit(3).build(); @@ -266,6 +274,11 @@ class BatchMetricsTests { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilderTests.java index 833eb1cf9..d00efa350 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/FaultTolerantStepBuilderTests.java @@ -38,8 +38,9 @@ class FaultTolerantStepBuilderTests { void testAnnotationBasedStepExecutionListenerRegistration() { // given FaultTolerantStepBuilder faultTolerantStepBuilder = new StepBuilder("myStep") - .repository(new DummyJobRepository()).transactionManager(new ResourcelessTransactionManager()) - .chunk(5).reader(new DummyItemReader()).writer(new DummyItemWriter()).faultTolerant() + .repository(new DummyJobRepository()).chunk(5) + .transactionManager(new ResourcelessTransactionManager()).reader(new DummyItemReader()) + .writer(new DummyItemWriter()).faultTolerant() .listener(new StepBuilderTests.AnnotationBasedStepExecutionListener()); // when diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java index cc0da6966..2bd23d213 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/RegisterMultiListenerTests.java @@ -52,6 +52,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.support.GenericApplicationContext; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.lang.Nullable; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -201,11 +202,17 @@ class RegisterMultiListenerTests { .setType(EmbeddedDatabaseType.HSQL).generateUniqueName(true).build()); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + @Override @Bean public Step step() { - return stepBuilders.get("step").listener(listener()).chunk(2).reader(reader()) - .writer(writer()).faultTolerant().skipLimit(1).skip(MySkippableException.class) + return stepBuilders.get("step").listener(listener()).chunk(2) + .transactionManager(transactionManager(dataSource())).reader(reader()).writer(writer()) + .faultTolerant().skipLimit(1).skip(MySkippableException.class) // ChunkListener registered twice for checking BATCH-2149 .listener((ChunkListener) listener()).build(); } @@ -224,11 +231,16 @@ class RegisterMultiListenerTests { .setType(EmbeddedDatabaseType.HSQL).generateUniqueName(true).build()); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + @Override @Bean public Step step() { - return stepBuilders.get("step").listener(listener()).chunk(2).reader(reader()) - .writer(writer()).build(); + return stepBuilders.get("step").listener(listener()).chunk(2) + .transactionManager(transactionManager(dataSource())).reader(reader()).writer(writer()).build(); } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java index 3df90204b..e5360173d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/builder/StepBuilderTests.java @@ -95,7 +95,7 @@ class StepBuilderTests { @Test void test() throws Exception { TaskletStepBuilder builder = new StepBuilder("step").repository(jobRepository) - .transactionManager(transactionManager).tasklet((contribution, chunkContext) -> null); + .tasklet((contribution, chunkContext) -> null).transactionManager(transactionManager); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); } @@ -103,8 +103,9 @@ class StepBuilderTests { @Test void testListeners() throws Exception { TaskletStepBuilder builder = new StepBuilder("step").repository(jobRepository) - .transactionManager(transactionManager).listener(new InterfaceBasedStepExecutionListener()) - .listener(new AnnotationBasedStepExecutionListener()).tasklet((contribution, chunkContext) -> null); + .listener(new InterfaceBasedStepExecutionListener()) + .listener(new AnnotationBasedStepExecutionListener()).tasklet((contribution, chunkContext) -> null) + .transactionManager(transactionManager); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(1, InterfaceBasedStepExecutionListener.beforeStepCount); @@ -118,7 +119,7 @@ class StepBuilderTests { @Test void testAnnotationBasedChunkListenerForTaskletStep() throws Exception { TaskletStepBuilder builder = new StepBuilder("step").repository(jobRepository) - .transactionManager(transactionManager).tasklet((contribution, chunkContext) -> null) + .tasklet((contribution, chunkContext) -> null).transactionManager(transactionManager) .listener(new AnnotationBasedChunkListener()); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); @@ -128,9 +129,9 @@ class StepBuilderTests { @Test void testAnnotationBasedChunkListenerForSimpleTaskletStep() throws Exception { - SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository) - .transactionManager(transactionManager).chunk(5).reader(new DummyItemReader()) - .writer(new DummyItemWriter()).listener(new AnnotationBasedChunkListener()); + SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository).chunk(5) + .transactionManager(transactionManager).reader(new DummyItemReader()).writer(new DummyItemWriter()) + .listener(new AnnotationBasedChunkListener()); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(1, AnnotationBasedChunkListener.beforeChunkCount); @@ -139,13 +140,13 @@ class StepBuilderTests { @Test void testAnnotationBasedChunkListenerForFaultTolerantTaskletStep() throws Exception { - SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository) - .transactionManager(transactionManager).chunk(5).reader(new DummyItemReader()) - .writer(new DummyItemWriter()).faultTolerant().listener(new AnnotationBasedChunkListener()); // TODO// - // should - // this - // return - // FaultTolerantStepBuilder? + SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository).chunk(5) + .transactionManager(transactionManager).reader(new DummyItemReader()).writer(new DummyItemWriter()) + .faultTolerant().listener(new AnnotationBasedChunkListener()); // TODO// + // should + // this + // return + // FaultTolerantStepBuilder? builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals(1, AnnotationBasedChunkListener.beforeChunkCount); @@ -156,8 +157,8 @@ class StepBuilderTests { void testAnnotationBasedChunkListenerForJobStepBuilder() throws Exception { SimpleJob job = new SimpleJob("job"); job.setJobRepository(jobRepository); - JobStepBuilder builder = new StepBuilder("step").repository(jobRepository) - .transactionManager(transactionManager).job(job).listener(new AnnotationBasedChunkListener()); + JobStepBuilder builder = new StepBuilder("step").repository(jobRepository).job(job) + .listener(new AnnotationBasedChunkListener()); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); @@ -174,7 +175,7 @@ class StepBuilderTests { ItemReader reader = new ListItemReader<>(items); SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository) - .transactionManager(transactionManager).chunk(3).reader(reader) + .chunk(3).transactionManager(transactionManager).reader(reader) .processor(new PassThroughItemProcessor<>()).writer(new DummyItemWriter()) .listener(new AnnotationBasedStepExecutionListener()); builder.build().execute(execution); @@ -209,7 +210,7 @@ class StepBuilderTests { ListItemWriter itemWriter = new ListItemWriter<>(); SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository) - .transactionManager(transactionManager).chunk(3).reader(reader) + .chunk(3).transactionManager(transactionManager).reader(reader) .processor(Object::toString).writer(itemWriter).listener(new AnnotationBasedStepExecutionListener()); if (faultTolerantStep) { @@ -291,7 +292,7 @@ class StepBuilderTests { ItemReader reader = new ListItemReader<>(items); SimpleStepBuilder builder = new StepBuilder("step").repository(jobRepository) - .transactionManager(transactionManager).chunk(3).reader(reader) + .chunk(3).transactionManager(transactionManager).reader(reader) .writer(new DummyItemWriter()); configurer.apply(builder).listener(new InterfaceBasedItemReadListenerListener()).build().execute(execution); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java index 107ea8dda..0e76e6716 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/concurrent/ConcurrentTransactionTests.java @@ -53,9 +53,11 @@ import org.springframework.jdbc.datasource.embedded.ConnectionProperties; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseConfigurer; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseFactory; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.lang.Nullable; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Isolation; import org.springframework.util.ClassUtils; @@ -94,8 +96,8 @@ class ConcurrentTransactionTests { @Autowired private StepBuilderFactory stepBuilderFactory; - public ConcurrentJobConfiguration(DataSource dataSource) { - super(dataSource); + public ConcurrentJobConfiguration(DataSource dataSource, PlatformTransactionManager transactionManager) { + super(dataSource, transactionManager); } @Bean @@ -111,13 +113,15 @@ class ConcurrentTransactionTests { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { return RepeatStatus.FINISHED; } - }).build()).next(stepBuilderFactory.get("flow.step2").tasklet(new Tasklet() { - @Nullable - @Override - public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { - return RepeatStatus.FINISHED; - } - }).build()).build(); + }).transactionManager(getTransactionManager()).build()) + .next(stepBuilderFactory.get("flow.step2").tasklet(new Tasklet() { + @Nullable + @Override + public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) + throws Exception { + return RepeatStatus.FINISHED; + } + }).transactionManager(getTransactionManager()).build()).build(); } @Bean @@ -129,7 +133,7 @@ class ConcurrentTransactionTests { System.out.println(">> Beginning concurrent job test"); return RepeatStatus.FINISHED; } - }).build(); + }).transactionManager(getTransactionManager()).build(); } @Bean @@ -141,7 +145,7 @@ class ConcurrentTransactionTests { System.out.println(">> Ending concurrent job test"); return RepeatStatus.FINISHED; } - }).build(); + }).transactionManager(getTransactionManager()).build(); } @Bean @@ -223,6 +227,11 @@ class ConcurrentTransactionTests { return embeddedDatabaseFactory.getDatabase(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/Db2JobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/Db2JobRepositoryIntegrationTests.java index bcf3e9fd4..53894fbcf 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/Db2JobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/Db2JobRepositoryIntegrationTests.java @@ -40,7 +40,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -105,9 +107,16 @@ class Db2JobRepositoryIntegrationTests { } @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job") - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/DerbyJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/DerbyJobRepositoryIntegrationTests.java index 9b069a7cc..ec505b1b6 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/DerbyJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/DerbyJobRepositoryIntegrationTests.java @@ -34,7 +34,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -75,9 +77,16 @@ class DerbyJobRepositoryIntegrationTests { } @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job") - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2CompatibilityModeJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2CompatibilityModeJobRepositoryIntegrationTests.java index f21c62a55..de54ec273 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2CompatibilityModeJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2CompatibilityModeJobRepositoryIntegrationTests.java @@ -39,12 +39,15 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.SimpleDriverDataSource; import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.support.JdbcTransactionManager; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; /** * @author Henning Pƶttker + * @author Mahmoud Ben Hassine */ class H2CompatibilityModeJobRepositoryIntegrationTests { @@ -83,9 +86,15 @@ class H2CompatibilityModeJobRepositoryIntegrationTests { static class TestConfiguration { @Bean - Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + Job job(JobBuilderFactory jobs, StepBuilderFactory steps, PlatformTransactionManager transactionManager) { return jobs.get("job") - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2JobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2JobRepositoryIntegrationTests.java index 3f55519e4..7281108cf 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2JobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/H2JobRepositoryIntegrationTests.java @@ -34,7 +34,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -75,9 +77,16 @@ class H2JobRepositoryIntegrationTests { } @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job") - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HSQLDBJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HSQLDBJobRepositoryIntegrationTests.java index eecdd73aa..d65085fab 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HSQLDBJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/HSQLDBJobRepositoryIntegrationTests.java @@ -34,7 +34,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -75,9 +77,16 @@ class HSQLDBJobRepositoryIntegrationTests { } @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job") - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJdbcJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJdbcJobRepositoryIntegrationTests.java index a73f8f347..6eba4326d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJdbcJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJdbcJobRepositoryIntegrationTests.java @@ -47,7 +47,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -131,10 +133,16 @@ class MySQLJdbcJobRepositoryIntegrationTests { } @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job").start(steps.get("step").tasklet((contribution, chunkContext) -> { throw new Exception("expected failure"); - }).build()).build(); + }).transactionManager(transactionManager).build()).build(); } @Bean diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJobRepositoryIntegrationTests.java index 524e586e0..2f19a4cc7 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/MySQLJobRepositoryIntegrationTests.java @@ -40,7 +40,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -102,9 +104,16 @@ class MySQLJobRepositoryIntegrationTests { } @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job") - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/PostgreSQLJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/PostgreSQLJobRepositoryIntegrationTests.java index 7ba2d27bc..7ea53c9e1 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/PostgreSQLJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/PostgreSQLJobRepositoryIntegrationTests.java @@ -40,7 +40,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -101,9 +103,16 @@ class PostgreSQLJobRepositoryIntegrationTests { } @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job") - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLServerJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLServerJobRepositoryIntegrationTests.java index 1c9d8b312..26387f6e8 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLServerJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLServerJobRepositoryIntegrationTests.java @@ -40,7 +40,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -102,9 +104,16 @@ class SQLServerJobRepositoryIntegrationTests { } @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job") - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLiteJobRepositoryIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLiteJobRepositoryIntegrationTests.java index 2aa5a4d6c..05a76fe17 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLiteJobRepositoryIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/repository/SQLiteJobRepositoryIntegrationTests.java @@ -35,7 +35,9 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -82,9 +84,16 @@ class SQLiteJobRepositoryIntegrationTests { } @Bean - public Job job(JobBuilderFactory jobs, StepBuilderFactory steps) { + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + + @Bean + public Job job(JobBuilderFactory jobs, StepBuilderFactory steps, + PlatformTransactionManager transactionManager) { return jobs.get("job") - .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()) + .start(steps.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager).build()) .build(); } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java index 14611d328..4eb34611e 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/test/step/FaultTolerantStepIntegrationTests.java @@ -77,8 +77,8 @@ class FaultTolerantStepIntegrationTests { } }; skipPolicy = new SkipIllegalArgumentExceptionSkipPolicy(); - stepBuilder = new StepBuilderFactory(jobRepository, transactionManager).get("step") - .chunk(CHUNK_SIZE).reader(itemReader).processor(item -> item > 20 ? null : item) + stepBuilder = new StepBuilderFactory(jobRepository).get("step").chunk(CHUNK_SIZE) + .transactionManager(transactionManager).reader(itemReader).processor(item -> item > 20 ? null : item) .writer(itemWriter).faultTolerant(); } @@ -178,9 +178,9 @@ class FaultTolerantStepIntegrationTests { } }; - Step step = new StepBuilderFactory(jobRepository, transactionManager).get("step").chunk(5) - .reader(itemReader).processor(itemProcessor).writer(itemWriter).faultTolerant().skip(Exception.class) - .skipLimit(3).build(); + Step step = new StepBuilderFactory(jobRepository).get("step").chunk(5) + .transactionManager(transactionManager).reader(itemReader).processor(itemProcessor).writer(itemWriter) + .faultTolerant().skip(Exception.class).skipLimit(3).build(); // When StepExecution stepExecution = execute(step); @@ -218,9 +218,9 @@ class FaultTolerantStepIntegrationTests { } }; - Step step = new StepBuilderFactory(jobRepository, transactionManager).get("step").chunk(5) - .reader(itemReader).processor(itemProcessor).writer(itemWriter).faultTolerant() - .skipPolicy(new AlwaysSkipItemSkipPolicy()).build(); + Step step = new StepBuilderFactory(jobRepository).get("step").chunk(5) + .transactionManager(transactionManager).reader(itemReader).processor(itemProcessor).writer(itemWriter) + .faultTolerant().skipPolicy(new AlwaysSkipItemSkipPolicy()).build(); // When StepExecution stepExecution = execute(step); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/BatchIntegrationConfiguration.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/BatchIntegrationConfiguration.java index 192adb107..7e16563d9 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/BatchIntegrationConfiguration.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/config/annotation/BatchIntegrationConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 the original author or authors. + * Copyright 2018-2022 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. @@ -85,9 +85,9 @@ public class BatchIntegrationConfiguration implements InitializingBean { this.transactionManager); this.remoteChunkingWorkerBuilder = new RemoteChunkingWorkerBuilder<>(); this.remotePartitioningManagerStepBuilderFactory = new RemotePartitioningManagerStepBuilderFactory( - this.jobRepository, this.jobExplorer, this.transactionManager); + this.jobRepository, this.jobExplorer); this.remotePartitioningWorkerStepBuilderFactory = new RemotePartitioningWorkerStepBuilderFactory( - this.jobRepository, this.jobExplorer, this.transactionManager); + this.jobRepository, this.jobExplorer); } } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java index 46118d485..f34d7fdfb 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilder.java @@ -234,12 +234,6 @@ public class RemotePartitioningManagerStepBuilder extends PartitionStepBuilder { return this; } - @Override - public RemotePartitioningManagerStepBuilder transactionManager(PlatformTransactionManager transactionManager) { - super.transactionManager(transactionManager); - return this; - } - @Override public RemotePartitioningManagerStepBuilder partitioner(String workerStepName, Partitioner partitioner) { super.partitioner(workerStepName, partitioner); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderFactory.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderFactory.java index 1f3b4afc1..37d54ca82 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderFactory.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningManagerStepBuilderFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 the original author or authors. + * Copyright 2019-2022 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. @@ -39,20 +39,15 @@ public class RemotePartitioningManagerStepBuilderFactory implements BeanFactoryA final private JobRepository jobRepository; - final private PlatformTransactionManager transactionManager; - /** * Create a new {@link RemotePartitioningManagerStepBuilderFactory}. * @param jobRepository the job repository to use * @param jobExplorer the job explorer to use - * @param transactionManager the transaction manager to use */ - public RemotePartitioningManagerStepBuilderFactory(JobRepository jobRepository, JobExplorer jobExplorer, - PlatformTransactionManager transactionManager) { + public RemotePartitioningManagerStepBuilderFactory(JobRepository jobRepository, JobExplorer jobExplorer) { this.jobRepository = jobRepository; this.jobExplorer = jobExplorer; - this.transactionManager = transactionManager; } @Override @@ -68,8 +63,7 @@ public class RemotePartitioningManagerStepBuilderFactory implements BeanFactoryA */ public RemotePartitioningManagerStepBuilder get(String name) { return new RemotePartitioningManagerStepBuilder(name).repository(this.jobRepository) - .jobExplorer(this.jobExplorer).beanFactory(this.beanFactory) - .transactionManager(this.transactionManager); + .jobExplorer(this.jobExplorer).beanFactory(this.beanFactory); } } diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java index 999afa25b..d207fa3ff 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilder.java @@ -150,12 +150,6 @@ public class RemotePartitioningWorkerStepBuilder extends StepBuilder { return this; } - @Override - public RemotePartitioningWorkerStepBuilder transactionManager(PlatformTransactionManager transactionManager) { - super.transactionManager(transactionManager); - return this; - } - @Override public RemotePartitioningWorkerStepBuilder startLimit(int startLimit) { super.startLimit(startLimit); diff --git a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderFactory.java b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderFactory.java index 601d878ef..cd2c0d6e0 100644 --- a/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderFactory.java +++ b/spring-batch-integration/src/main/java/org/springframework/batch/integration/partition/RemotePartitioningWorkerStepBuilderFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 the original author or authors. + * Copyright 2018-2022 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. @@ -39,20 +39,15 @@ public class RemotePartitioningWorkerStepBuilderFactory implements BeanFactoryAw final private JobRepository jobRepository; - final private PlatformTransactionManager transactionManager; - /** * Create a new {@link RemotePartitioningWorkerStepBuilderFactory}. * @param jobRepository the job repository to use * @param jobExplorer the job explorer to use - * @param transactionManager the transaction manager to use */ - public RemotePartitioningWorkerStepBuilderFactory(JobRepository jobRepository, JobExplorer jobExplorer, - PlatformTransactionManager transactionManager) { + public RemotePartitioningWorkerStepBuilderFactory(JobRepository jobRepository, JobExplorer jobExplorer) { this.jobExplorer = jobExplorer; this.jobRepository = jobRepository; - this.transactionManager = transactionManager; } @Override @@ -68,8 +63,7 @@ public class RemotePartitioningWorkerStepBuilderFactory implements BeanFactoryAw */ public RemotePartitioningWorkerStepBuilder get(String name) { return new RemotePartitioningWorkerStepBuilder(name).repository(this.jobRepository) - .jobExplorer(this.jobExplorer).beanFactory(this.beanFactory) - .transactionManager(this.transactionManager); + .jobExplorer(this.jobExplorer).beanFactory(this.beanFactory); } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/DataSourceConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/DataSourceConfiguration.java index 758bb2a4b..a21d44871 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/DataSourceConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/DataSourceConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -28,6 +28,7 @@ import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils; import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.jdbc.support.JdbcTransactionManager; /** * @author Dave Syer @@ -62,4 +63,9 @@ public class DataSourceConfiguration { return dataSource; } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } \ No newline at end of file diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/RetrySampleConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/RetrySampleConfiguration.java index 717fc850e..eb38f8a10 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/RetrySampleConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/config/RetrySampleConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -28,6 +28,7 @@ import org.springframework.batch.sample.support.RetrySampleItemWriter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.PlatformTransactionManager; /** * @author Dave Syer @@ -44,6 +45,9 @@ public class RetrySampleConfiguration { @Autowired private StepBuilderFactory steps; + @Autowired + private PlatformTransactionManager transactionManager; + @Bean public Job retrySample() { return jobs.get("retrySample").start(step()).build(); @@ -51,8 +55,8 @@ public class RetrySampleConfiguration { @Bean protected Step step() { - return steps.get("step").chunk(1).reader(reader()).writer(writer()).faultTolerant() - .retry(Exception.class).retryLimit(3).build(); + return steps.get("step").chunk(1).transactionManager(this.transactionManager).reader(reader()) + .writer(writer()).faultTolerant().retry(Exception.class).retryLimit(3).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/WorkerConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/WorkerConfiguration.java index d372fe61f..b0306f1c5 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/WorkerConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/aggregating/WorkerConfiguration.java @@ -33,6 +33,7 @@ import org.springframework.context.annotation.Import; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.dsl.IntegrationFlow; import org.springframework.integration.jms.dsl.Jms; +import org.springframework.transaction.PlatformTransactionManager; /** * This configuration class is for the worker side of the remote partitioning sample. Each @@ -84,9 +85,9 @@ public class WorkerConfiguration { * Configure the worker step */ @Bean - public Step workerStep() { + public Step workerStep(PlatformTransactionManager transactionManager) { return this.workerStepBuilderFactory.get("workerStep").inputChannel(requests()).outputChannel(replies()) - .tasklet(tasklet(null)).build(); + .tasklet(tasklet(null)).transactionManager(transactionManager).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/WorkerConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/WorkerConfiguration.java index 8b9fe42b4..e4e146daf 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/WorkerConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/remotepartitioning/polling/WorkerConfiguration.java @@ -33,6 +33,7 @@ import org.springframework.context.annotation.Import; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.dsl.IntegrationFlow; import org.springframework.integration.jms.dsl.Jms; +import org.springframework.transaction.PlatformTransactionManager; /** * This configuration class is for the worker side of the remote partitioning sample. Each @@ -70,8 +71,9 @@ public class WorkerConfiguration { * Configure the worker step */ @Bean - public Step workerStep() { - return this.workerStepBuilderFactory.get("workerStep").inputChannel(requests()).tasklet(tasklet(null)).build(); + public Step workerStep(PlatformTransactionManager transactionManager) { + return this.workerStepBuilderFactory.get("workerStep").inputChannel(requests()).tasklet(tasklet(null)) + .transactionManager(transactionManager).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/DataSourceConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/DataSourceConfiguration.java index 2feaa1c8e..0cddf5004 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/DataSourceConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/DataSourceConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 the original author or authors. + * Copyright 2021-2022 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. @@ -20,6 +20,7 @@ import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.support.JdbcTransactionManager; @Configuration public class DataSourceConfiguration { @@ -30,4 +31,9 @@ public class DataSourceConfiguration { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } \ No newline at end of file diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringProcessSample.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringProcessSample.java index 2609fdb10..c330b89a7 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringProcessSample.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringProcessSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 the original author or authors. + * Copyright 2019-2022 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. @@ -30,6 +30,7 @@ import org.springframework.batch.item.support.ListItemReader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.transaction.PlatformTransactionManager; /** * @author Mahmoud Ben Hassine @@ -43,10 +44,13 @@ public class SkippableExceptionDuringProcessSample { private final StepBuilderFactory stepBuilderFactory; + private final PlatformTransactionManager transactionManager; + public SkippableExceptionDuringProcessSample(JobBuilderFactory jobBuilderFactory, - StepBuilderFactory stepBuilderFactory) { + StepBuilderFactory stepBuilderFactory, PlatformTransactionManager transactionManager) { this.jobBuilderFactory = jobBuilderFactory; this.stepBuilderFactory = stepBuilderFactory; + this.transactionManager = transactionManager; } @Bean @@ -85,9 +89,9 @@ public class SkippableExceptionDuringProcessSample { @Bean public Step step() { - return this.stepBuilderFactory.get("step").chunk(3).reader(itemReader()) - .processor(itemProcessor()).writer(itemWriter()).faultTolerant().skip(IllegalArgumentException.class) - .skipLimit(3).build(); + return this.stepBuilderFactory.get("step").chunk(3) + .transactionManager(this.transactionManager).reader(itemReader()).processor(itemProcessor()) + .writer(itemWriter()).faultTolerant().skip(IllegalArgumentException.class).skipLimit(3).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringReadSample.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringReadSample.java index 8f15f901e..64220bcd6 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringReadSample.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringReadSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 the original author or authors. + * Copyright 2019-2022 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. @@ -30,6 +30,7 @@ import org.springframework.batch.item.support.ListItemReader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.transaction.PlatformTransactionManager; /** * @author Mahmoud Ben Hassine @@ -43,10 +44,13 @@ public class SkippableExceptionDuringReadSample { private final StepBuilderFactory stepBuilderFactory; + private final PlatformTransactionManager transactionManager; + public SkippableExceptionDuringReadSample(JobBuilderFactory jobBuilderFactory, - StepBuilderFactory stepBuilderFactory) { + StepBuilderFactory stepBuilderFactory, PlatformTransactionManager transactionManager) { this.jobBuilderFactory = jobBuilderFactory; this.stepBuilderFactory = stepBuilderFactory; + this.transactionManager = transactionManager; } @Bean @@ -85,9 +89,9 @@ public class SkippableExceptionDuringReadSample { @Bean public Step step() { - return this.stepBuilderFactory.get("step").chunk(3).reader(itemReader()) - .processor(itemProcessor()).writer(itemWriter()).faultTolerant().skip(IllegalArgumentException.class) - .skipLimit(3).build(); + return this.stepBuilderFactory.get("step").chunk(3) + .transactionManager(this.transactionManager).reader(itemReader()).processor(itemProcessor()) + .writer(itemWriter()).faultTolerant().skip(IllegalArgumentException.class).skipLimit(3).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringWriteSample.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringWriteSample.java index b4298051c..3db58e398 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringWriteSample.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/skip/SkippableExceptionDuringWriteSample.java @@ -1,5 +1,5 @@ /* - * Copyright 2019-2021 the original author or authors. + * Copyright 2019-2022 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. @@ -30,6 +30,7 @@ import org.springframework.batch.item.support.ListItemReader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.transaction.PlatformTransactionManager; /** * @author Mahmoud Ben Hassine @@ -43,10 +44,13 @@ public class SkippableExceptionDuringWriteSample { private final StepBuilderFactory stepBuilderFactory; + private final PlatformTransactionManager transactionManager; + public SkippableExceptionDuringWriteSample(JobBuilderFactory jobBuilderFactory, - StepBuilderFactory stepBuilderFactory) { + StepBuilderFactory stepBuilderFactory, PlatformTransactionManager transactionManager) { this.jobBuilderFactory = jobBuilderFactory; this.stepBuilderFactory = stepBuilderFactory; + this.transactionManager = transactionManager; } @Bean @@ -85,9 +89,9 @@ public class SkippableExceptionDuringWriteSample { @Bean public Step step() { - return this.stepBuilderFactory.get("step").chunk(3).reader(itemReader()) - .processor(itemProcessor()).writer(itemWriter()).faultTolerant().skip(IllegalArgumentException.class) - .skipLimit(3).build(); + return this.stepBuilderFactory.get("step").chunk(3) + .transactionManager(this.transactionManager).reader(itemReader()).processor(itemProcessor()) + .writer(itemWriter()).faultTolerant().skip(IllegalArgumentException.class).skipLimit(3).build(); } @Bean diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/ValidationSampleConfiguration.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/ValidationSampleConfiguration.java index 50c38f1de..d33163668 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/ValidationSampleConfiguration.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/validation/ValidationSampleConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021 the original author or authors. + * Copyright 2018-2022 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. @@ -33,6 +33,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.support.JdbcTransactionManager; /** * @author Mahmoud Ben Hassine @@ -70,8 +71,8 @@ public class ValidationSampleConfiguration { @Bean public Step step() throws Exception { - return this.steps.get("step").chunk(1).reader(itemReader()).processor(itemValidator()) - .writer(itemWriter()).build(); + return this.steps.get("step").chunk(1).transactionManager(transactionManager(dataSource())) + .reader(itemReader()).processor(itemValidator()).writer(itemWriter()).build(); } @Bean @@ -85,4 +86,9 @@ public class ValidationSampleConfiguration { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } diff --git a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JsonSupportIntegrationTests.java b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JsonSupportIntegrationTests.java index 7445594e3..a3205bdb3 100644 --- a/spring-batch-samples/src/test/java/org/springframework/batch/sample/JsonSupportIntegrationTests.java +++ b/spring-batch-samples/src/test/java/org/springframework/batch/sample/JsonSupportIntegrationTests.java @@ -49,6 +49,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.FileSystemResource; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.util.DigestUtils; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -94,7 +95,8 @@ class JsonSupportIntegrationTests { @Bean public Step step() { - return steps.get("step").chunk(2).reader(itemReader()).writer(itemWriter()).build(); + return steps.get("step").chunk(2).transactionManager(transactionManager(dataSource())) + .reader(itemReader()).writer(itemWriter()).build(); } @Bean @@ -108,6 +110,11 @@ class JsonSupportIntegrationTests { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } @Test diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/JobLauncherTestUtilsTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/JobLauncherTestUtilsTests.java index 947188027..3e37b7de0 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/JobLauncherTestUtilsTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/JobLauncherTestUtilsTests.java @@ -35,6 +35,7 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.lang.Nullable; import java.util.HashSet; @@ -92,7 +93,7 @@ class JobLauncherTestUtilsTests { public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception { return null; } - }).build(); + }).transactionManager(transactionManager(dataSource())).build(); } @Bean @@ -114,6 +115,11 @@ class JobLauncherTestUtilsTests { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").generateUniqueName(true).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + } } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit4Tests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit4Tests.java index 338cf2aa2..25534fd2b 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit4Tests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit4Tests.java @@ -42,6 +42,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -130,6 +131,11 @@ public class SpringBatchTestJUnit4Tests { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + @Bean @StepScope public ItemReader stepScopedItemReader(@Value("#{stepExecutionContext['input.data']}") String data) { @@ -144,8 +150,11 @@ public class SpringBatchTestJUnit4Tests { @Bean public Job job() { - return this.jobBuilderFactory.get("job").start(this.stepBuilderFactory.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()).build(); + return this.jobBuilderFactory.get("job") + .start(this.stepBuilderFactory.get("step") + .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager(dataSource())).build()) + .build(); } } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit5Tests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit5Tests.java index d7d4e6766..e9e3ff484 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit5Tests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SpringBatchTestJUnit5Tests.java @@ -43,6 +43,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -124,6 +125,11 @@ public class SpringBatchTestJUnit5Tests { .addScript("/org/springframework/batch/core/schema-hsqldb.sql").build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + @Bean @StepScope public ItemReader stepScopedItemReader(@Value("#{stepExecutionContext['input.data']}") String data) { @@ -138,8 +144,10 @@ public class SpringBatchTestJUnit5Tests { @Bean public Job job(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) { - return jobBuilderFactory.get("job").start(stepBuilderFactory.get("step") - .tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED).build()).build(); + return jobBuilderFactory.get("job") + .start(stepBuilderFactory.get("step").tasklet((contribution, chunkContext) -> RepeatStatus.FINISHED) + .transactionManager(transactionManager(dataSource())).build()) + .build(); } } diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeAnnotatedListenerIntegrationTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeAnnotatedListenerIntegrationTests.java index 33bdbfaec..278da2a27 100644 --- a/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeAnnotatedListenerIntegrationTests.java +++ b/spring-batch-test/src/test/java/org/springframework/batch/test/StepScopeAnnotatedListenerIntegrationTests.java @@ -43,8 +43,10 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.lang.Nullable; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.transaction.PlatformTransactionManager; @SpringJUnitConfig class StepScopeAnnotatedListenerIntegrationTests { @@ -103,6 +105,9 @@ class StepScopeAnnotatedListenerIntegrationTests { @Autowired private StepBuilderFactory stepBuilder; + @Autowired + private PlatformTransactionManager transactionManager; + @Bean JobLauncherTestUtils jobLauncherTestUtils() { return new JobLauncherTestUtils(); @@ -116,6 +121,11 @@ class StepScopeAnnotatedListenerIntegrationTests { .setType(EmbeddedDatabaseType.HSQL).build(); } + @Bean + public JdbcTransactionManager transactionManager(DataSource dataSource) { + return new JdbcTransactionManager(dataSource); + } + @Bean public Job jobUnderTest() { return jobBuilder.get("job-under-test").start(stepUnderTest()).build(); @@ -123,7 +133,8 @@ class StepScopeAnnotatedListenerIntegrationTests { @Bean public Step stepUnderTest() { - return stepBuilder.get("step-under-test").chunk(1).reader(reader()).processor(processor()) + return stepBuilder.get("step-under-test").chunk(1) + .transactionManager(this.transactionManager).reader(reader()).processor(processor()) .writer(writer()).build(); }