diff --git a/pom.xml b/pom.xml index d44b836607..ca55866a42 100644 --- a/pom.xml +++ b/pom.xml @@ -759,6 +759,7 @@ javafx spring-batch + spring-batch-2 spring-boot-rest spring-drools spring-exceptions @@ -781,7 +782,6 @@ server-modules apache-cxf-modules - spring-aop jmeter spring-aop-2 @@ -928,7 +928,6 @@ spring-5-webflux spring-5-webflux-2 spring-activiti - spring-batch-2 spring-core-2 spring-core-3 spring-core-5 @@ -1012,6 +1011,7 @@ javafx spring-batch + spring-batch-2 spring-boot-rest spring-drools spring-exceptions @@ -1180,7 +1180,6 @@ spring-5-webflux spring-5-webflux-2 spring-activiti - spring-batch-2 spring-core-2 spring-core-3 spring-core-5 diff --git a/spring-batch-2/pom.xml b/spring-batch-2/pom.xml index 12d31aca14..378191c91c 100644 --- a/spring-batch-2/pom.xml +++ b/spring-batch-2/pom.xml @@ -11,9 +11,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 @@ -51,8 +51,9 @@ - 4.3.0 - 3.1.1 + 5.0.0 + 4.2.0 + com.baeldung.batch.SpringBootBatchProcessingApplication \ No newline at end of file diff --git a/spring-batch-2/src/main/java/com/baeldung/batch/BatchConfiguration.java b/spring-batch-2/src/main/java/com/baeldung/batch/BatchConfiguration.java index 0c053dd86c..770b6330dd 100644 --- a/spring-batch-2/src/main/java/com/baeldung/batch/BatchConfiguration.java +++ b/spring-batch-2/src/main/java/com/baeldung/batch/BatchConfiguration.java @@ -4,31 +4,24 @@ import javax.sql.DataSource; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider; import org.springframework.batch.item.database.JdbcBatchItemWriter; import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; +import org.springframework.transaction.PlatformTransactionManager; @Configuration -@EnableBatchProcessing public class BatchConfiguration { - - @Autowired - public JobBuilderFactory jobBuilderFactory; - - @Autowired - public StepBuilderFactory stepBuilderFactory; @Value("${file.input}") private String fileInput; @@ -59,8 +52,8 @@ public class BatchConfiguration { } @Bean - public Job importUserJob(JobCompletionNotificationListener listener, Step step1) { - return jobBuilderFactory.get("importUserJob") + public Job importUserJob(JobRepository jobRepository, JobCompletionNotificationListener listener, Step step1) { + return new JobBuilder("importUserJob", jobRepository) .incrementer(new RunIdIncrementer()) .listener(listener) .flow(step1) @@ -69,9 +62,9 @@ public class BatchConfiguration { } @Bean - public Step step1(JdbcBatchItemWriter writer) { - return stepBuilderFactory.get("step1") - . chunk(10) + public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, JdbcBatchItemWriter writer) { + return new StepBuilder("step1", jobRepository) + . chunk(10, transactionManager) .reader(reader()) .processor(processor()) .writer(writer) diff --git a/spring-batch-2/src/main/java/com/baeldung/batch/CoffeeItemProcessor.java b/spring-batch-2/src/main/java/com/baeldung/batch/CoffeeItemProcessor.java index b154b80453..bd4173e9ed 100644 --- a/spring-batch-2/src/main/java/com/baeldung/batch/CoffeeItemProcessor.java +++ b/spring-batch-2/src/main/java/com/baeldung/batch/CoffeeItemProcessor.java @@ -10,7 +10,7 @@ public class CoffeeItemProcessor implements ItemProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(CoffeeItemProcessor.class); @Override - public Coffee process(final Coffee coffee) throws Exception { + public Coffee process(final Coffee coffee) { String brand = coffee.getBrand().toUpperCase(); String origin = coffee.getOrigin().toUpperCase(); String chracteristics = coffee.getCharacteristics().toUpperCase(); diff --git a/spring-batch-2/src/main/java/com/baeldung/batch/JobCompletionNotificationListener.java b/spring-batch-2/src/main/java/com/baeldung/batch/JobCompletionNotificationListener.java index ca1de40aea..b61faeb13b 100644 --- a/spring-batch-2/src/main/java/com/baeldung/batch/JobCompletionNotificationListener.java +++ b/spring-batch-2/src/main/java/com/baeldung/batch/JobCompletionNotificationListener.java @@ -4,13 +4,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.JobExecution; -import org.springframework.batch.core.listener.JobExecutionListenerSupport; +import org.springframework.batch.core.JobExecutionListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; @Component -public class JobCompletionNotificationListener extends JobExecutionListenerSupport { +public class JobCompletionNotificationListener implements JobExecutionListener { private static final Logger LOGGER = LoggerFactory.getLogger(JobCompletionNotificationListener.class); diff --git a/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java index c830a41855..dcb2bc5199 100644 --- a/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java +++ b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java @@ -7,15 +7,16 @@ import org.springframework.batch.core.Job; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @@ -24,17 +25,16 @@ import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.ScheduledMethodRunnable; +import org.springframework.transaction.PlatformTransactionManager; import java.util.Date; import java.util.IdentityHashMap; -import java.util.List; import java.util.Map; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @Configuration -@EnableBatchProcessing @EnableScheduling public class SpringBatchScheduler { @@ -46,21 +46,21 @@ public class SpringBatchScheduler { private final Map> scheduledTasks = new IdentityHashMap<>(); - @Autowired - private JobBuilderFactory jobBuilderFactory; - - @Autowired - private StepBuilderFactory stepBuilderFactory; - @Autowired private JobLauncher jobLauncher; + @Autowired + private JobRepository jobRepository; + + @Autowired + private PlatformTransactionManager transactionManager; + @Scheduled(fixedRate = 2000) public void launchJob() throws Exception { Date date = new Date(); logger.debug("scheduler starts at " + date); if (enabled.get()) { - JobExecution jobExecution = jobLauncher.run(job(), new JobParametersBuilder().addDate("launchDate", date) + JobExecution jobExecution = jobLauncher.run(job(jobRepository, transactionManager), new JobParametersBuilder().addDate("launchDate", date) .toJobParameters()); batchRunCounter.incrementAndGet(); logger.debug("Batch job ends with status as " + jobExecution.getStatus()); @@ -106,17 +106,16 @@ public class SpringBatchScheduler { } @Bean - public Job job() { - return jobBuilderFactory - .get("job") - .start(readBooks()) + public Job job(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new JobBuilder("job", jobRepository) + .start(readBooks(jobRepository, transactionManager)) .build(); } @Bean - protected Step readBooks() { - return stepBuilderFactory.get("readBooks") - . chunk(2) + protected Step readBooks(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new StepBuilder("readBooks", jobRepository) + . chunk(2, transactionManager) .reader(reader()) .writer(writer()) .build(); @@ -128,7 +127,7 @@ public class SpringBatchScheduler { .resource(new ClassPathResource("books.csv")) .delimited() .names(new String[] { "id", "name" }) - .fieldSetMapper(new BeanWrapperFieldSetMapper() { + .fieldSetMapper(new BeanWrapperFieldSetMapper<>() { { setTargetType(Book.class); } @@ -138,15 +137,10 @@ public class SpringBatchScheduler { @Bean public ItemWriter writer() { - return new ItemWriter() { - - @Override - public void write(List items) throws Exception { - logger.debug("writer..." + items.size()); - for (Book item : items) { - logger.debug(item.toString()); - } - + return items -> { + logger.debug("writer..." + items.size()); + for (Book item : items) { + logger.debug(item.toString()); } }; } diff --git a/spring-batch-2/src/test/java/com/baeldung/batch/SpringBootBatchIntegrationTest.java b/spring-batch-2/src/test/java/com/baeldung/batch/SpringBootBatchIntegrationTest.java index ba2b8a6a13..21fd7bf4b1 100644 --- a/spring-batch-2/src/test/java/com/baeldung/batch/SpringBootBatchIntegrationTest.java +++ b/spring-batch-2/src/test/java/com/baeldung/batch/SpringBootBatchIntegrationTest.java @@ -1,11 +1,10 @@ package com.baeldung.batch; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobInstance; @@ -13,16 +12,17 @@ import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.batch.test.JobRepositoryTestUtils; import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.PropertySource; import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; @SpringBatchTest -@SpringBootTest @DirtiesContext +@SpringJUnitConfig(BatchConfiguration.class) @PropertySource("classpath:application.properties") -@RunWith(SpringRunner.class) +@EnableAutoConfiguration public class SpringBootBatchIntegrationTest { @Autowired @@ -31,7 +31,10 @@ public class SpringBootBatchIntegrationTest { @Autowired private JobRepositoryTestUtils jobRepositoryTestUtils; - @After + @MockBean + private JobCompletionNotificationListener jobCompletionNotificationListener; + + @AfterEach public void cleanUp() { jobRepositoryTestUtils.removeJobExecutions(); } @@ -42,8 +45,8 @@ public class SpringBootBatchIntegrationTest { JobInstance jobInstance = jobExecution.getJobInstance(); ExitStatus jobExitStatus = jobExecution.getExitStatus(); - assertThat(jobInstance.getJobName(), is("importUserJob")); - assertThat(jobExitStatus.getExitCode(), is("COMPLETED")); + assertEquals("importUserJob", jobInstance.getJobName()); + assertEquals("COMPLETED", jobExitStatus.getExitCode()); } } diff --git a/spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java b/spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java index 61e5a1dd74..297e8d989f 100644 --- a/spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java +++ b/spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java @@ -1,28 +1,20 @@ package com.baeldung.batchscheduler; -import com.baeldung.batchscheduler.SpringBatchScheduler; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.batch.test.context.SpringBatchTest; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.PropertySource; import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor; import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.junit4.SpringRunner; import static org.awaitility.Awaitility.await; import static java.util.concurrent.TimeUnit.*; +import static org.junit.jupiter.api.Assertions.assertEquals; -@SpringBatchTest @SpringBootTest @DirtiesContext @PropertySource("classpath:application.properties") -@RunWith(SpringRunner.class) public class SpringBatchSchedulerIntegrationTest { @Autowired @@ -31,37 +23,36 @@ public class SpringBatchSchedulerIntegrationTest { @Test public void stopJobsWhenSchedulerDisabled() { SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); - await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() + await().untilAsserted(() -> assertEquals(2, schedulerBean.getBatchRunCounter() .get())); schedulerBean.stop(); await().atLeast(3, SECONDS); - Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get()); + assertEquals(2, schedulerBean.getBatchRunCounter().get()); } @Test - public void stopJobSchedulerWhenSchedulerDestroyed() throws Exception { + public void stopJobSchedulerWhenSchedulerDestroyed() { ScheduledAnnotationBeanPostProcessor bean = context.getBean(ScheduledAnnotationBeanPostProcessor.class); SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); - await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() + await().untilAsserted(() -> assertEquals(2, schedulerBean.getBatchRunCounter() .get())); bean.postProcessBeforeDestruction(schedulerBean, "SpringBatchScheduler"); await().atLeast(3, SECONDS); - Assert.assertEquals(2, schedulerBean.getBatchRunCounter() + assertEquals(2, schedulerBean.getBatchRunCounter() .get()); } @Test - public void stopJobSchedulerWhenFutureTasksCancelled() throws Exception { + public void stopJobSchedulerWhenFutureTasksCancelled() { SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); - await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() + await().untilAsserted(() -> assertEquals(2, schedulerBean.getBatchRunCounter() .get())); schedulerBean.cancelFutureSchedulerTasks(); await().atLeast(3, SECONDS); - Assert.assertEquals(2, schedulerBean.getBatchRunCounter() + assertEquals(2, schedulerBean.getBatchRunCounter() .get()); } diff --git a/spring-batch/pom.xml b/spring-batch/pom.xml index e9d3afa376..810ddcdcdd 100644 --- a/spring-batch/pom.xml +++ b/spring-batch/pom.xml @@ -11,9 +11,9 @@ com.baeldung - parent-boot-2 + parent-boot-3 0.0.1-SNAPSHOT - ../parent-boot-2 + ../parent-boot-3 @@ -22,25 +22,15 @@ jackson-datatype-jsr310 ${jackson-datatype.version} - - - javax.xml.bind - jaxb-api - ${jaxb.version} - + jakarta.xml.bind + jakarta.xml.bind-api + 4.0.0 org.glassfish.jaxb jaxb-runtime ${jaxb.version} - - - - - org.xerial - sqlite-jdbc - ${sqlite.version} org.springframework @@ -53,20 +43,9 @@ - - org.springframework - spring-jdbc - ${spring.version} - - - org.springframework.batch - spring-batch-core - ${spring.batch.version} - org.springframework.batch spring-batch-test - ${spring.batch.version} com.opencsv @@ -78,19 +57,29 @@ spring-boot-starter-batch - org.hsqldb - hsqldb - runtime + org.apache.httpcomponents + httpclient + ${http-client.version} + + + org.codehaus.jettison + jettison + ${jettison.version} + + + com.h2database + h2 - 5.3.0 - 4.3.0 - 3.15.1 - 4.1 - 2.3.1 - 2.12.3 + 6.0.6 + 5.7.1 + 4.0.2 + 2.14.2 + 4.5.14 + 1.5.3 + com.baeldung.batchtesting.SpringBatchApplication \ No newline at end of file diff --git a/spring-batch/repository.sqlite b/spring-batch/repository.sqlite index b6a954554c..ddf5d0c16f 100644 Binary files a/spring-batch/repository.sqlite and b/spring-batch/repository.sqlite differ diff --git a/spring-batch/src/main/java/com/baeldung/batch/App.java b/spring-batch/src/main/java/com/baeldung/batch/App.java index c2db446965..c5823590d8 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/App.java +++ b/spring-batch/src/main/java/com/baeldung/batch/App.java @@ -18,20 +18,19 @@ public class App { public static void main(final String[] args) { // Spring Java config final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(SpringConfig.class); + context.getEnvironment().addActiveProfile("spring"); context.register(SpringBatchConfig.class); context.register(SpringBatchRetryConfig.class); context.refresh(); // Spring xml config - // ApplicationContext context = new ClassPathXmlApplicationContext("spring-batch.xml"); + // ApplicationContext context = new ClassPathXmlApplicationContext("spring-batch-intro.xml"); runJob(context, "firstBatchJob"); runJob(context, "skippingBatchJob"); runJob(context, "skipPolicyBatchJob"); runJob(context, "retryBatchJob"); - } private static void runJob(AnnotationConfigApplicationContext context, String batchJobName) { diff --git a/spring-batch/src/main/java/com/baeldung/batch/SpringBatchConfig.java b/spring-batch/src/main/java/com/baeldung/batch/SpringBatchConfig.java index 5546df22fc..5d999c68e7 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/SpringBatchConfig.java +++ b/spring-batch/src/main/java/com/baeldung/batch/SpringBatchConfig.java @@ -1,5 +1,7 @@ package com.baeldung.batch; +import javax.sql.DataSource; + import com.baeldung.batch.model.Transaction; import com.baeldung.batch.service.CustomItemProcessor; import com.baeldung.batch.service.CustomSkipPolicy; @@ -7,10 +9,15 @@ import com.baeldung.batch.service.MissingUsernameException; import com.baeldung.batch.service.NegativeAmountException; import com.baeldung.batch.service.RecordFieldSetMapper; import com.baeldung.batch.service.SkippingItemProcessor; + import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.launch.support.TaskExecutorJobLauncher; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; @@ -19,24 +26,23 @@ import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.batch.item.xml.StaxEventItemWriter; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.core.io.Resource; +import org.springframework.core.io.WritableResource; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; import org.springframework.oxm.Marshaller; import org.springframework.oxm.jaxb.Jaxb2Marshaller; +import org.springframework.transaction.PlatformTransactionManager; -import java.text.ParseException; - +@Configuration @Profile("spring") public class SpringBatchConfig { - @Autowired - private JobBuilderFactory jobBuilderFactory; - - @Autowired - private StepBuilderFactory stepBuilderFactory; @Value("input/record.csv") private Resource inputCsv; @@ -45,9 +51,9 @@ public class SpringBatchConfig { private Resource invalidInputCsv; @Value("file:xml/output.xml") - private Resource outputXml; + private WritableResource outputXml; - public ItemReader itemReader(Resource inputData) throws UnexpectedInputException, ParseException { + public ItemReader itemReader(Resource inputData) throws UnexpectedInputException { FlatFileItemReader reader = new FlatFileItemReader<>(); DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); String[] tokens = {"username", "userid", "transactiondate", "amount"}; @@ -88,10 +94,10 @@ public class SpringBatchConfig { } @Bean - protected Step step1(@Qualifier("itemProcessor") ItemProcessor processor, ItemWriter writer) throws ParseException { - return stepBuilderFactory - .get("step1") - . chunk(10) + protected Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("itemProcessor") ItemProcessor processor, ItemWriter writer) { + return new StepBuilder("step1", jobRepository) + . chunk(10, transactionManager) .reader(itemReader(inputCsv)) .processor(processor) .writer(writer) @@ -99,16 +105,15 @@ public class SpringBatchConfig { } @Bean(name = "firstBatchJob") - public Job job(@Qualifier("step1") Step step1) { - return jobBuilderFactory.get("firstBatchJob").start(step1).build(); + public Job job(JobRepository jobRepository, @Qualifier("step1") Step step1) { + return new JobBuilder("firstBatchJob", jobRepository).preventRestart().start(step1).build(); } @Bean - public Step skippingStep(@Qualifier("skippingItemProcessor") ItemProcessor processor, - ItemWriter writer) throws ParseException { - return stepBuilderFactory - .get("skippingStep") - .chunk(10) + public Step skippingStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingItemProcessor") ItemProcessor processor, ItemWriter writer) { + return new StepBuilder("skippingStep", jobRepository) + .chunk(10, transactionManager) .reader(itemReader(invalidInputCsv)) .processor(processor) .writer(writer) @@ -120,19 +125,18 @@ public class SpringBatchConfig { } @Bean(name = "skippingBatchJob") - public Job skippingJob(@Qualifier("skippingStep") Step skippingStep) { - return jobBuilderFactory - .get("skippingBatchJob") + public Job skippingJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingStep") Step skippingStep) { + return new JobBuilder("skippingBatchJob", jobRepository) .start(skippingStep) + .preventRestart() .build(); } @Bean - public Step skipPolicyStep(@Qualifier("skippingItemProcessor") ItemProcessor processor, - ItemWriter writer) throws ParseException { - return stepBuilderFactory - .get("skipPolicyStep") - .chunk(10) + public Step skipPolicyStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingItemProcessor") ItemProcessor processor, + ItemWriter writer) { + return new StepBuilder("skipPolicyStep", jobRepository) + .chunk(10, transactionManager) .reader(itemReader(invalidInputCsv)) .processor(processor) .writer(writer) @@ -142,11 +146,44 @@ public class SpringBatchConfig { } @Bean(name = "skipPolicyBatchJob") - public Job skipPolicyBatchJob(@Qualifier("skipPolicyStep") Step skipPolicyStep) { - return jobBuilderFactory - .get("skipPolicyBatchJob") + public Job skipPolicyBatchJob(JobRepository jobRepository, @Qualifier("skipPolicyStep") Step skipPolicyStep) { + return new JobBuilder("skipPolicyBatchJob", jobRepository) .start(skipPolicyStep) + .preventRestart() .build(); } + public DataSource dataSource() { + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + return builder.setType(EmbeddedDatabaseType.H2) + .addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql") + .addScript("classpath:org/springframework/batch/core/schema-h2.sql") + .build(); + } + + @Bean(name = "transactionManager") + public PlatformTransactionManager getTransactionManager() { + return new ResourcelessTransactionManager(); + } + + @Bean(name = "jobRepository") + public JobRepository getJobRepository() throws Exception { + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(dataSource()); + factory.setTransactionManager(getTransactionManager()); + // JobRepositoryFactoryBean's methods Throws Generic Exception, + // it would have been better to have a specific one + factory.afterPropertiesSet(); + return factory.getObject(); + } + + @Bean(name = "jobLauncher") + public JobLauncher getJobLauncher() throws Exception { + TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher(); + // TaskExecutorJobLauncher's methods Throws Generic Exception, + // it would have been better to have a specific one + jobLauncher.setJobRepository(getJobRepository()); + jobLauncher.afterPropertiesSet(); + return jobLauncher; + } } diff --git a/spring-batch/src/main/java/com/baeldung/batch/SpringBatchRetryConfig.java b/spring-batch/src/main/java/com/baeldung/batch/SpringBatchRetryConfig.java index a329df3016..4b6246c074 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/SpringBatchRetryConfig.java +++ b/spring-batch/src/main/java/com/baeldung/batch/SpringBatchRetryConfig.java @@ -1,17 +1,18 @@ package com.baeldung.batch; +import com.baeldung.batch.model.Transaction; +import com.baeldung.batch.service.RecordFieldSetMapper; +import com.baeldung.batch.service.RetryItemProcessor; + import org.apache.http.client.config.RequestConfig; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; -import com.baeldung.batch.model.Transaction; -import com.baeldung.batch.service.RecordFieldSetMapper; -import com.baeldung.batch.service.RetryItemProcessor; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; @@ -19,38 +20,30 @@ import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.batch.item.xml.StaxEventItemWriter; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; +import org.springframework.core.io.WritableResource; import org.springframework.dao.DeadlockLoserDataAccessException; import org.springframework.oxm.Marshaller; import org.springframework.oxm.jaxb.Jaxb2Marshaller; - -import java.text.ParseException; +import org.springframework.transaction.PlatformTransactionManager; @Configuration -@EnableBatchProcessing public class SpringBatchRetryConfig { - + private static final String[] tokens = { "username", "userid", "transactiondate", "amount" }; private static final int TWO_SECONDS = 2000; - @Autowired - private JobBuilderFactory jobBuilderFactory; - - @Autowired - private StepBuilderFactory stepBuilderFactory; - @Value("input/recordRetry.csv") private Resource inputCsv; @Value("file:xml/retryOutput.xml") - private Resource outputXml; + private WritableResource outputXml; - public ItemReader itemReader(Resource inputData) throws ParseException { + public ItemReader itemReader(Resource inputData) { DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); tokenizer.setNames(tokens); DefaultLineMapper lineMapper = new DefaultLineMapper<>(); @@ -93,10 +86,11 @@ public class SpringBatchRetryConfig { } @Bean - public Step retryStep(@Qualifier("retryItemProcessor") ItemProcessor processor, - ItemWriter writer) throws ParseException { - return stepBuilderFactory.get("retryStep") - .chunk(10) + public Step retryStep( + JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("retryItemProcessor") ItemProcessor processor, + ItemWriter writer) { + return new StepBuilder("retryStep", jobRepository) + .chunk(10, transactionManager) .reader(itemReader(inputCsv)) .processor(processor) .writer(writer) @@ -108,9 +102,8 @@ public class SpringBatchRetryConfig { } @Bean(name = "retryBatchJob") - public Job retryJob(@Qualifier("retryStep") Step retryStep) { - return jobBuilderFactory - .get("retryBatchJob") + public Job retryJob(JobRepository jobRepository, @Qualifier("retryStep") Step retryStep) { + return new JobBuilder("retryBatchJob", jobRepository) .start(retryStep) .build(); } diff --git a/spring-batch/src/main/java/com/baeldung/batch/SpringConfig.java b/spring-batch/src/main/java/com/baeldung/batch/SpringConfig.java deleted file mode 100644 index dc6c242996..0000000000 --- a/spring-batch/src/main/java/com/baeldung/batch/SpringConfig.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.baeldung.batch; - -import java.net.MalformedURLException; - -import javax.sql.DataSource; - -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.batch.core.launch.support.SimpleJobLauncher; -import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.core.io.Resource; -import org.springframework.jdbc.datasource.DriverManagerDataSource; -import org.springframework.jdbc.datasource.init.DataSourceInitializer; -import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; -import org.springframework.transaction.PlatformTransactionManager; - -@Configuration -@EnableBatchProcessing -@Profile("spring") -public class SpringConfig { - - @Value("org/springframework/batch/core/schema-drop-sqlite.sql") - private Resource dropReopsitoryTables; - - @Value("org/springframework/batch/core/schema-sqlite.sql") - private Resource dataReopsitorySchema; - - @Bean - public DataSource dataSource() { - DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName("org.sqlite.JDBC"); - dataSource.setUrl("jdbc:sqlite:repository.sqlite"); - return dataSource; - } - - @Bean - public DataSourceInitializer dataSourceInitializer(DataSource dataSource) throws MalformedURLException { - ResourceDatabasePopulator databasePopulator = new ResourceDatabasePopulator(); - - databasePopulator.addScript(dropReopsitoryTables); - databasePopulator.addScript(dataReopsitorySchema); - databasePopulator.setIgnoreFailedDrops(true); - - DataSourceInitializer initializer = new DataSourceInitializer(); - initializer.setDataSource(dataSource); - initializer.setDatabasePopulator(databasePopulator); - - return initializer; - } - - private JobRepository getJobRepository() throws Exception { - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(dataSource()); - factory.setTransactionManager(getTransactionManager()); - // JobRepositoryFactoryBean's methods Throws Generic Exception, - // it would have been better to have a specific one - factory.afterPropertiesSet(); - return (JobRepository) factory.getObject(); - } - - private PlatformTransactionManager getTransactionManager() { - return new ResourcelessTransactionManager(); - } - - public JobLauncher getJobLauncher() throws Exception { - SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); - // SimpleJobLauncher's methods Throws Generic Exception, - // it would have been better to have a specific one - jobLauncher.setJobRepository(getJobRepository()); - jobLauncher.afterPropertiesSet(); - return jobLauncher; - } - -} \ No newline at end of file diff --git a/spring-batch/src/main/java/com/baeldung/batch/model/Transaction.java b/spring-batch/src/main/java/com/baeldung/batch/model/Transaction.java index ffb6d59a79..c4ca36c1bc 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/model/Transaction.java +++ b/spring-batch/src/main/java/com/baeldung/batch/model/Transaction.java @@ -1,10 +1,11 @@ package com.baeldung.batch.model; +import java.time.LocalDateTime; + import com.baeldung.batch.service.adapter.LocalDateTimeAdapter; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; -import java.time.LocalDateTime; +import jakarta.xml.bind.annotation.XmlRootElement; +import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @SuppressWarnings("restriction") @XmlRootElement(name = "transactionRecord") diff --git a/spring-batch/src/main/java/com/baeldung/batch/partitioner/CustomMultiResourcePartitioner.java b/spring-batch/src/main/java/com/baeldung/batch/partitioner/CustomMultiResourcePartitioner.java index 4fade76ffc..1ff74ce192 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/partitioner/CustomMultiResourcePartitioner.java +++ b/spring-batch/src/main/java/com/baeldung/batch/partitioner/CustomMultiResourcePartitioner.java @@ -60,7 +60,7 @@ public class CustomMultiResourcePartitioner implements Partitioner { */ @Override public Map partition(int gridSize) { - Map map = new HashMap(gridSize); + Map map = new HashMap<>(gridSize); int i = 0, k = 1; for (Resource resource : resources) { ExecutionContext context = new ExecutionContext(); diff --git a/spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringbatchPartitionConfig.java b/spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringBatchPartitionConfig.java similarity index 77% rename from spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringbatchPartitionConfig.java rename to spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringBatchPartitionConfig.java index b08c95af53..ceacb36e4d 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringbatchPartitionConfig.java +++ b/spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringBatchPartitionConfig.java @@ -5,13 +5,13 @@ import com.baeldung.batch.service.RecordFieldSetMapper; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.batch.core.launch.support.SimpleJobLauncher; +import org.springframework.batch.core.launch.support.TaskExecutorJobLauncher; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.UnexpectedInputException; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.mapping.DefaultLineMapper; @@ -36,42 +36,35 @@ import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; import java.io.IOException; -import java.net.MalformedURLException; import java.text.ParseException; @Configuration @EnableBatchProcessing -public class SpringbatchPartitionConfig { +public class SpringBatchPartitionConfig { @Autowired - ResourcePatternResolver resoursePatternResolver; - - @Autowired - private JobBuilderFactory jobs; - - @Autowired - private StepBuilderFactory steps; + private ResourcePatternResolver resourcePatternResolver; @Bean(name = "partitionerJob") - public Job partitionerJob() throws UnexpectedInputException, MalformedURLException, ParseException { - return jobs.get("partitionerJob") - .start(partitionStep()) + public Job partitionerJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws UnexpectedInputException, ParseException { + return new JobBuilder("partitionerJob", jobRepository) + .start(partitionStep(jobRepository, transactionManager)) .build(); } @Bean - public Step partitionStep() throws UnexpectedInputException, MalformedURLException, ParseException { - return steps.get("partitionStep") + public Step partitionStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws UnexpectedInputException, ParseException { + return new StepBuilder("partitionStep", jobRepository) .partitioner("slaveStep", partitioner()) - .step(slaveStep()) + .step(slaveStep(jobRepository, transactionManager)) .taskExecutor(taskExecutor()) .build(); } @Bean - public Step slaveStep() throws UnexpectedInputException, MalformedURLException, ParseException { - return steps.get("slaveStep") - .chunk(1) + public Step slaveStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) throws UnexpectedInputException, ParseException { + return new StepBuilder("slaveStep", jobRepository) + .chunk(1, transactionManager) .reader(itemReader(null)) .writer(itemWriter(marshaller(), null)) .build(); @@ -82,7 +75,7 @@ public class SpringbatchPartitionConfig { CustomMultiResourcePartitioner partitioner = new CustomMultiResourcePartitioner(); Resource[] resources; try { - resources = resoursePatternResolver.getResources("file:src/main/resources/input/partitioner/*.csv"); + resources = resourcePatternResolver.getResources("file:src/main/resources/input/partitioner/*.csv"); } catch (IOException e) { throw new RuntimeException("I/O problems when resolving the input file pattern.", e); } @@ -108,7 +101,7 @@ public class SpringbatchPartitionConfig { @Bean(destroyMethod = "") @StepScope - public StaxEventItemWriter itemWriter(Marshaller marshaller, @Value("#{stepExecutionContext[opFileName]}") String filename) throws MalformedURLException { + public StaxEventItemWriter itemWriter(Marshaller marshaller, @Value("#{stepExecutionContext[opFileName]}") String filename) { StaxEventItemWriter itemWriter = new StaxEventItemWriter<>(); itemWriter.setMarshaller(marshaller); itemWriter.setRootTagName("transactionRecord"); @@ -133,7 +126,8 @@ public class SpringbatchPartitionConfig { return taskExecutor; } - private JobRepository getJobRepository() throws Exception { + @Bean(name = "jobRepository") + public JobRepository getJobRepository() throws Exception { JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); factory.setDataSource(dataSource()); factory.setTransactionManager(getTransactionManager()); @@ -143,20 +137,23 @@ public class SpringbatchPartitionConfig { return factory.getObject(); } - private DataSource dataSource() { + @Bean(name = "dataSource") + public DataSource dataSource() { EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - return builder.setType(EmbeddedDatabaseType.HSQL) + return builder.setType(EmbeddedDatabaseType.H2) .addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql") .addScript("classpath:org/springframework/batch/core/schema-h2.sql") .build(); } - private PlatformTransactionManager getTransactionManager() { + @Bean(name = "transactionManager") + public PlatformTransactionManager getTransactionManager() { return new ResourcelessTransactionManager(); } + @Bean(name = "jobLauncher") public JobLauncher getJobLauncher() throws Exception { - SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); + TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher(); // SimpleJobLauncher's methods Throws Generic Exception, // it would have been better to have a specific one jobLauncher.setJobRepository(getJobRepository()); diff --git a/spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringbatchPartitionerApp.java b/spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringBatchPartitionerApp.java similarity index 89% rename from spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringbatchPartitionerApp.java rename to spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringBatchPartitionerApp.java index e755e21ca9..a1661e750e 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringbatchPartitionerApp.java +++ b/spring-batch/src/main/java/com/baeldung/batch/partitioner/SpringBatchPartitionerApp.java @@ -8,14 +8,14 @@ import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.context.annotation.AnnotationConfigApplicationContext; -public class SpringbatchPartitionerApp { +public class SpringBatchPartitionerApp { - private static final Logger LOGGER = LoggerFactory.getLogger(SpringbatchPartitionerApp.class); + private static final Logger LOGGER = LoggerFactory.getLogger(SpringBatchPartitionerApp.class); public static void main(final String[] args) { // Spring Java config final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - context.register(SpringbatchPartitionConfig.class); + context.register(SpringBatchPartitionConfig.class); context.refresh(); final JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher"); diff --git a/spring-batch/src/main/java/com/baeldung/batch/service/CustomSkipPolicy.java b/spring-batch/src/main/java/com/baeldung/batch/service/CustomSkipPolicy.java index 25401de022..af6fe20529 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/service/CustomSkipPolicy.java +++ b/spring-batch/src/main/java/com/baeldung/batch/service/CustomSkipPolicy.java @@ -9,19 +9,13 @@ public class CustomSkipPolicy implements SkipPolicy { private static final int INVALID_TX_AMOUNT_LIMIT = -1000; @Override - public boolean shouldSkip(Throwable throwable, int skipCount) throws SkipLimitExceededException { - + public boolean shouldSkip(Throwable throwable, long skipCount) throws SkipLimitExceededException { if (throwable instanceof MissingUsernameException && skipCount < MAX_SKIP_COUNT) { return true; } - if (throwable instanceof NegativeAmountException && skipCount < MAX_SKIP_COUNT ) { - NegativeAmountException ex = (NegativeAmountException) throwable; - if(ex.getAmount() < INVALID_TX_AMOUNT_LIMIT){ - return false; - } else{ - return true; - } + if (throwable instanceof NegativeAmountException ex && skipCount < MAX_SKIP_COUNT ) { + return ex.getAmount() >= INVALID_TX_AMOUNT_LIMIT; } return false; diff --git a/spring-batch/src/main/java/com/baeldung/batch/service/RecordFieldSetMapper.java b/spring-batch/src/main/java/com/baeldung/batch/service/RecordFieldSetMapper.java index 09478e9a30..97c77d9e6a 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/service/RecordFieldSetMapper.java +++ b/spring-batch/src/main/java/com/baeldung/batch/service/RecordFieldSetMapper.java @@ -10,7 +10,7 @@ import java.time.format.DateTimeFormatter; public class RecordFieldSetMapper implements FieldSetMapper { - public Transaction mapFieldSet(FieldSet fieldSet) throws BindException { + public Transaction mapFieldSet(FieldSet fieldSet) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yyy"); diff --git a/spring-batch/src/main/java/com/baeldung/batch/service/RetryItemProcessor.java b/spring-batch/src/main/java/com/baeldung/batch/service/RetryItemProcessor.java index c380e2c0ab..aa49680b2a 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/service/RetryItemProcessor.java +++ b/spring-batch/src/main/java/com/baeldung/batch/service/RetryItemProcessor.java @@ -5,15 +5,13 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import com.baeldung.batch.model.Transaction; -import org.codehaus.jettison.json.JSONException; + import org.codehaus.jettison.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.item.ItemProcessor; import org.springframework.beans.factory.annotation.Autowired; -import java.io.IOException; - public class RetryItemProcessor implements ItemProcessor { private static final Logger LOGGER = LoggerFactory.getLogger(RetryItemProcessor.class); @@ -22,7 +20,7 @@ public class RetryItemProcessor implements ItemProcessor { private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; diff --git a/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBootBatchConfig.java b/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBootBatchConfig.java index 57531ebc39..6c463de5dc 100644 --- a/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBootBatchConfig.java +++ b/spring-batch/src/main/java/com/baeldung/batch/springboot/SpringBootBatchConfig.java @@ -5,8 +5,9 @@ import com.baeldung.batch.service.*; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; @@ -15,27 +16,21 @@ import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.mapping.DefaultLineMapper; import org.springframework.batch.item.file.transform.DelimitedLineTokenizer; import org.springframework.batch.item.xml.StaxEventItemWriter; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.core.io.Resource; +import org.springframework.core.io.WritableResource; import org.springframework.oxm.Marshaller; import org.springframework.oxm.jaxb.Jaxb2Marshaller; - -import java.text.ParseException; +import org.springframework.transaction.PlatformTransactionManager; @Configuration @EnableBatchProcessing @Profile("spring-boot") public class SpringBootBatchConfig { - @Autowired - private JobBuilderFactory jobBuilderFactory; - - @Autowired - private StepBuilderFactory stepBuilderFactory; @Value("input/record.csv") private Resource inputCsv; @@ -44,9 +39,9 @@ public class SpringBootBatchConfig { private Resource invalidInputCsv; @Value("file:xml/output.xml") - private Resource outputXml; + private WritableResource outputXml; - public ItemReader itemReader(Resource inputData) throws UnexpectedInputException, ParseException { + public ItemReader itemReader(Resource inputData) throws UnexpectedInputException { FlatFileItemReader reader = new FlatFileItemReader<>(); DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(); String[] tokens = {"username", "userid", "transactiondate", "amount"}; @@ -86,11 +81,10 @@ public class SpringBootBatchConfig { return marshaller3; } - @Bean - protected Step step1(@Qualifier("itemProcessor") ItemProcessor processor, ItemWriter itemWriter3) throws ParseException { - return stepBuilderFactory - .get("step1") - . chunk(10) + @Bean(name = "step1") + protected Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("itemProcessor") ItemProcessor processor, ItemWriter itemWriter3) { + return new StepBuilder("step1", jobRepository) + . chunk(10, transactionManager) .reader(itemReader(inputCsv)) .processor(processor) .writer(itemWriter3) @@ -98,16 +92,15 @@ public class SpringBootBatchConfig { } @Bean(name = "firstBatchJob") - public Job job(@Qualifier("step1") Step step1) { - return jobBuilderFactory.get("firstBatchJob").start(step1).build(); + public Job job(@Qualifier("step1") Step step1, JobRepository jobRepository) { + return new JobBuilder("firstBatchJob", jobRepository).start(step1).build(); } @Bean - public Step skippingStep(@Qualifier("skippingItemProcessor") ItemProcessor processor, - ItemWriter itemWriter3) throws ParseException { - return stepBuilderFactory - .get("skippingStep") - .chunk(10) + public Step skippingStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingItemProcessor") ItemProcessor processor, + ItemWriter itemWriter3) { + return new StepBuilder("skippingStep", jobRepository) + .chunk(10, transactionManager) .reader(itemReader(invalidInputCsv)) .processor(processor) .writer(itemWriter3) @@ -119,19 +112,17 @@ public class SpringBootBatchConfig { } @Bean(name = "skippingBatchJob") - public Job skippingJob(@Qualifier("skippingStep") Step skippingStep) { - return jobBuilderFactory - .get("skippingBatchJob") + public Job skippingJob(JobRepository jobRepository, @Qualifier("skippingStep") Step skippingStep) { + return new JobBuilder("skippingBatchJob", jobRepository) .start(skippingStep) .build(); } - @Bean - public Step skipPolicyStep(@Qualifier("skippingItemProcessor") ItemProcessor processor, - ItemWriter itemWriter3) throws ParseException { - return stepBuilderFactory - .get("skipPolicyStep") - .chunk(10) + @Bean(name = "skipPolicyStep") + public Step skipPolicyStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("skippingItemProcessor") ItemProcessor processor, + ItemWriter itemWriter3) { + return new StepBuilder("skipPolicyStep", jobRepository) + .chunk(10, transactionManager) .reader(itemReader(invalidInputCsv)) .processor(processor) .writer(itemWriter3) @@ -141,11 +132,9 @@ public class SpringBootBatchConfig { } @Bean(name = "skipPolicyBatchJob") - public Job skipPolicyBatchJob(@Qualifier("skipPolicyStep") Step skipPolicyStep) { - return jobBuilderFactory - .get("skipPolicyBatchJob") + public Job skipPolicyBatchJob(JobRepository jobRepository, @Qualifier("skipPolicyStep") Step skipPolicyStep) { + return new JobBuilder("skipPolicyBatchJob", jobRepository) .start(skipPolicyStep) .build(); } - } diff --git a/spring-batch/src/main/java/com/baeldung/batchtesting/SpringBatchConfiguration.java b/spring-batch/src/main/java/com/baeldung/batchtesting/SpringBatchConfiguration.java index 664db3fbba..547074ff84 100644 --- a/spring-batch/src/main/java/com/baeldung/batchtesting/SpringBatchConfiguration.java +++ b/spring-batch/src/main/java/com/baeldung/batchtesting/SpringBatchConfiguration.java @@ -1,7 +1,5 @@ package com.baeldung.batchtesting; -import java.io.IOException; - import com.baeldung.batchtesting.model.Book; import com.baeldung.batchtesting.model.BookDetails; import com.baeldung.batchtesting.model.BookRecord; @@ -12,10 +10,10 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepScope; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.file.FlatFileItemReader; @@ -25,27 +23,19 @@ import org.springframework.batch.item.json.JacksonJsonObjectMarshaller; import org.springframework.batch.item.json.JsonFileItemWriter; import org.springframework.batch.item.json.builder.JsonFileItemWriterBuilder; import org.springframework.batch.item.support.ListItemWriter; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.FileSystemResource; - +import org.springframework.transaction.PlatformTransactionManager; @Configuration -@EnableBatchProcessing public class SpringBatchConfiguration { private static Logger LOGGER = LoggerFactory.getLogger(SpringBatchConfiguration.class); private static final String[] TOKENS = { "bookname", "bookauthor", "bookformat", "isbn", "publishyear" }; - @Autowired - private JobBuilderFactory jobBuilderFactory; - - @Autowired - private StepBuilderFactory stepBuilderFactory; - @Bean @StepScope public FlatFileItemReader csvItemReader(@Value("#{jobParameters['file.input']}") String input) { @@ -65,7 +55,7 @@ public class SpringBatchConfiguration { @Bean @StepScope - public JsonFileItemWriter jsonItemWriter(@Value("#{jobParameters['file.output']}") String output) throws IOException { + public JsonFileItemWriter jsonItemWriter(@Value("#{jobParameters['file.output']}") String output) { JsonFileItemWriterBuilder builder = new JsonFileItemWriterBuilder<>(); JacksonJsonObjectMarshaller marshaller = new JacksonJsonObjectMarshaller<>(); LOGGER.info("Configuring writer to output {}", output); @@ -81,7 +71,7 @@ public class SpringBatchConfiguration { @Bean @StepScope public ListItemWriter listItemWriter() { - return new ListItemWriter(); + return new ListItemWriter<>(); } @Bean @@ -96,12 +86,11 @@ public class SpringBatchConfiguration { return new BookDetailsItemProcessor(); } - @Bean - public Step step1(ItemReader csvItemReader, ItemWriter jsonItemWriter) throws IOException { + @Bean(name = "step1") + public Step step1(JobRepository jobRepository, PlatformTransactionManager transactionManager, ItemReader csvItemReader, ItemWriter jsonItemWriter) { // @formatter:off - return stepBuilderFactory - .get("step1") - . chunk(3) + return new StepBuilder("step1", jobRepository) + . chunk(3, transactionManager) .reader(csvItemReader) .processor(bookItemProcessor()) .writer(jsonItemWriter) @@ -109,12 +98,11 @@ public class SpringBatchConfiguration { // @formatter:on } - @Bean - public Step step2(ItemReader csvItemReader, ItemWriter listItemWriter) { + @Bean(name = "step2") + public Step step2(JobRepository jobRepository, PlatformTransactionManager transactionManager, ItemReader csvItemReader, ItemWriter listItemWriter) { // @formatter:off - return stepBuilderFactory - .get("step2") - . chunk(3) + return new StepBuilder("step2", jobRepository) + . chunk(3, transactionManager) .reader(csvItemReader) .processor(bookDetailsItemProcessor()) .writer(listItemWriter) @@ -123,15 +111,13 @@ public class SpringBatchConfiguration { } @Bean(name = "transformBooksRecords") - public Job transformBookRecords(Step step1, Step step2) throws IOException { + public Job transformBookRecords(JobRepository jobRepository, Step step1, Step step2) { // @formatter:off - return jobBuilderFactory - .get("transformBooksRecords") + return new JobBuilder("transformBooksRecords", jobRepository) .flow(step1) .next(step2) .end() .build(); // @formatter:on } - } diff --git a/spring-batch/src/main/java/com/baeldung/batchtesting/service/BookDetailsItemProcessor.java b/spring-batch/src/main/java/com/baeldung/batchtesting/service/BookDetailsItemProcessor.java index 514a383108..4e4d1e9075 100644 --- a/spring-batch/src/main/java/com/baeldung/batchtesting/service/BookDetailsItemProcessor.java +++ b/spring-batch/src/main/java/com/baeldung/batchtesting/service/BookDetailsItemProcessor.java @@ -11,7 +11,7 @@ public class BookDetailsItemProcessor implements ItemProcessor { private static Logger LOGGER = LoggerFactory.getLogger(BookItemProcessor.class); @Override - public Book process(BookRecord item) throws Exception { + public Book process(BookRecord item) { Book book = new Book(); book.setAuthor(item.getBookAuthor()); book.setName(item.getBookName()); diff --git a/spring-batch/src/main/java/com/baeldung/batchtesting/service/BookRecordFieldSetMapper.java b/spring-batch/src/main/java/com/baeldung/batchtesting/service/BookRecordFieldSetMapper.java index d9e8ee1158..e4760da20f 100644 --- a/spring-batch/src/main/java/com/baeldung/batchtesting/service/BookRecordFieldSetMapper.java +++ b/spring-batch/src/main/java/com/baeldung/batchtesting/service/BookRecordFieldSetMapper.java @@ -9,7 +9,7 @@ import org.springframework.validation.BindException; public class BookRecordFieldSetMapper implements FieldSetMapper { @Override - public BookRecord mapFieldSet(FieldSet fieldSet) throws BindException { + public BookRecord mapFieldSet(FieldSet fieldSet) { BookRecord bookRecord = new BookRecord(); bookRecord.setBookName(fieldSet.readString("bookname")); bookRecord.setBookAuthor(fieldSet.readString("bookauthor")); diff --git a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/chunks/LineReader.java b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/chunks/LineReader.java index 6ffa730c19..d8ba2c9728 100644 --- a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/chunks/LineReader.java +++ b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/chunks/LineReader.java @@ -21,9 +21,9 @@ public class LineReader implements ItemReader, StepExecutionListener { } @Override - public Line read() throws Exception { + public Line read() { Line line = fu.readLine(); - if (line != null) logger.debug("Read line: " + line.toString()); + if (line != null) logger.debug("Read line: " + line); return line; } diff --git a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/chunks/LinesWriter.java b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/chunks/LinesWriter.java index 9f292b24b9..bcf648820c 100644 --- a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/chunks/LinesWriter.java +++ b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/chunks/LinesWriter.java @@ -7,10 +7,9 @@ import org.slf4j.LoggerFactory; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.StepExecution; import org.springframework.batch.core.StepExecutionListener; +import org.springframework.batch.item.Chunk; import org.springframework.batch.item.ItemWriter; -import java.util.List; - public class LinesWriter implements ItemWriter, StepExecutionListener { private final Logger logger = LoggerFactory.getLogger(LinesWriter.class); @@ -30,7 +29,7 @@ public class LinesWriter implements ItemWriter, StepExecutionListener { } @Override - public void write(List lines) throws Exception { + public void write(Chunk lines) { for (Line line : lines) { fu.writeLine(line); logger.debug("Wrote line " + line.toString()); diff --git a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/ChunksConfig.java b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/ChunksConfig.java index c8b05848f9..16c6b1191f 100644 --- a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/ChunksConfig.java +++ b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/ChunksConfig.java @@ -6,67 +6,19 @@ import com.baeldung.taskletsvschunks.chunks.LinesWriter; import com.baeldung.taskletsvschunks.model.Line; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.batch.core.launch.support.SimpleJobLauncher; +import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; -import org.springframework.batch.test.JobLauncherTestUtils; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.transaction.PlatformTransactionManager; -import javax.sql.DataSource; - @Configuration -@EnableBatchProcessing public class ChunksConfig { - @Autowired private JobBuilderFactory jobs; - - @Autowired private StepBuilderFactory steps; - - @Bean - public JobLauncherTestUtils jobLauncherTestUtils() { - return new JobLauncherTestUtils(); - } - - @Bean - public JobRepository jobRepository() throws Exception { - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(dataSource()); - factory.setTransactionManager(transactionManager()); - return factory.getObject(); - } - - @Bean - public DataSource dataSource() { - DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName("org.sqlite.JDBC"); - dataSource.setUrl("jdbc:sqlite:repository.sqlite"); - return dataSource; - } - - @Bean - public PlatformTransactionManager transactionManager() { - return new ResourcelessTransactionManager(); - } - - @Bean - public JobLauncher jobLauncher() throws Exception { - SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); - jobLauncher.setJobRepository(jobRepository()); - return jobLauncher; - } - @Bean public ItemReader itemReader() { return new LineReader(); @@ -82,20 +34,19 @@ public class ChunksConfig { return new LinesWriter(); } - @Bean - protected Step processLines(ItemReader reader, ItemProcessor processor, ItemWriter writer) { - return steps.get("processLines"). chunk(2) + @Bean(name = "processLines") + protected Step processLines(JobRepository jobRepository, PlatformTransactionManager transactionManager, ItemReader reader, ItemProcessor processor, ItemWriter writer) { + return new StepBuilder("processLines", jobRepository). chunk(2, transactionManager) .reader(reader) .processor(processor) .writer(writer) .build(); } - @Bean - public Job job() { - return jobs - .get("chunksJob") - .start(processLines(itemReader(), itemProcessor(), itemWriter())) + @Bean(name = "chunksJob") + public Job job(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new JobBuilder("chunksJob", jobRepository) + .start(processLines(jobRepository, transactionManager, itemReader(), itemProcessor(), itemWriter())) .build(); } diff --git a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/TaskletsConfig.java b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/TaskletsConfig.java index 5f2f49928c..ab9d506229 100644 --- a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/TaskletsConfig.java +++ b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/TaskletsConfig.java @@ -5,64 +5,16 @@ import com.baeldung.taskletsvschunks.tasklets.LinesReader; import com.baeldung.taskletsvschunks.tasklets.LinesWriter; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; -import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; -import org.springframework.batch.core.launch.JobLauncher; -import org.springframework.batch.core.launch.support.SimpleJobLauncher; +import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; -import org.springframework.batch.support.transaction.ResourcelessTransactionManager; -import org.springframework.batch.test.JobLauncherTestUtils; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.transaction.PlatformTransactionManager; -import javax.sql.DataSource; - @Configuration -@EnableBatchProcessing public class TaskletsConfig { - @Autowired private JobBuilderFactory jobs; - - @Autowired private StepBuilderFactory steps; - - @Bean - public JobLauncherTestUtils jobLauncherTestUtils() { - return new JobLauncherTestUtils(); - } - - @Bean - public JobRepository jobRepository() throws Exception { - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(dataSource()); - factory.setTransactionManager(transactionManager()); - return factory.getObject(); - } - - @Bean - public DataSource dataSource() { - DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName("org.sqlite.JDBC"); - dataSource.setUrl("jdbc:sqlite:repository.sqlite"); - return dataSource; - } - - @Bean - public PlatformTransactionManager transactionManager() { - return new ResourcelessTransactionManager(); - } - - @Bean - public JobLauncher jobLauncher() throws Exception { - SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); - jobLauncher.setJobRepository(jobRepository()); - return jobLauncher; - } - @Bean public LinesReader linesReader() { return new LinesReader(); @@ -79,36 +31,32 @@ public class TaskletsConfig { } @Bean - protected Step readLines() { - return steps - .get("readLines") - .tasklet(linesReader()) + protected Step readLines(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new StepBuilder("readLines", jobRepository) + .tasklet(linesReader(), transactionManager) .build(); } @Bean - protected Step processLines() { - return steps - .get("processLines") - .tasklet(linesProcessor()) + protected Step processLines(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new StepBuilder("processLines", jobRepository) + .tasklet(linesProcessor(), transactionManager) .build(); } @Bean - protected Step writeLines() { - return steps - .get("writeLines") - .tasklet(linesWriter()) + protected Step writeLines(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new StepBuilder("writeLines", jobRepository) + .tasklet(linesWriter(), transactionManager) .build(); } @Bean - public Job job() { - return jobs - .get("taskletsJob") - .start(readLines()) - .next(processLines()) - .next(writeLines()) + public Job job(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new JobBuilder("taskletsJob", jobRepository) + .start(readLines(jobRepository, transactionManager)) + .next(processLines(jobRepository, transactionManager)) + .next(writeLines(jobRepository, transactionManager)) .build(); } diff --git a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/tasklets/LinesReader.java b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/tasklets/LinesReader.java index b1f58be4a4..70f1a1b05d 100644 --- a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/tasklets/LinesReader.java +++ b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/tasklets/LinesReader.java @@ -24,7 +24,7 @@ public class LinesReader implements Tasklet, StepExecutionListener { @Override public void beforeStep(StepExecution stepExecution) { - lines = new ArrayList(); + lines = new ArrayList<>(); fu = new FileUtils("taskletsvschunks/input/tasklets-vs-chunks.csv"); logger.debug("Lines Reader initialized."); } diff --git a/spring-batch/src/main/java/org/baeldung/conditionalflow/ConditionalFlowApplication.java b/spring-batch/src/main/java/org/baeldung/conditionalflow/ConditionalFlowApplication.java index c977d6ecab..8a8f62ae31 100644 --- a/spring-batch/src/main/java/org/baeldung/conditionalflow/ConditionalFlowApplication.java +++ b/spring-batch/src/main/java/org/baeldung/conditionalflow/ConditionalFlowApplication.java @@ -15,7 +15,7 @@ public class ConditionalFlowApplication implements CommandLineRunner { } @Override - public void run(String... args) throws Exception { + public void run(String... args) { logger.info("Running conditional flow application..."); } } diff --git a/spring-batch/src/main/java/org/baeldung/conditionalflow/config/NumberInfoConfig.java b/spring-batch/src/main/java/org/baeldung/conditionalflow/config/NumberInfoConfig.java index 906a6e1d28..4954d9ffcd 100644 --- a/spring-batch/src/main/java/org/baeldung/conditionalflow/config/NumberInfoConfig.java +++ b/spring-batch/src/main/java/org/baeldung/conditionalflow/config/NumberInfoConfig.java @@ -6,39 +6,49 @@ import org.baeldung.conditionalflow.step.*; import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; -import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; -import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.job.builder.JobBuilder; +import org.springframework.batch.core.launch.JobLauncher; +import org.springframework.batch.core.launch.support.TaskExecutorJobLauncher; +import org.springframework.batch.core.repository.JobRepository; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; +import org.springframework.batch.core.step.builder.StepBuilder; +import org.springframework.batch.support.transaction.ResourcelessTransactionManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.transaction.PlatformTransactionManager; import static org.baeldung.conditionalflow.NumberInfoDecider.NOTIFY; +import javax.sql.DataSource; + @Configuration @EnableBatchProcessing public class NumberInfoConfig { @Bean @Qualifier("NotificationStep") - public Step notificationStep(StepBuilderFactory sbf) { - return sbf.get("Notify step") - .tasklet(new NotifierTasklet()) + public Step notificationStep(JobRepository jobRepository, PlatformTransactionManager transactionManager) { + return new StepBuilder("Notify step", jobRepository) + .tasklet(new NotifierTasklet(), transactionManager) .build(); } - public Step numberGeneratorStep(StepBuilderFactory sbf, int[] values, String prepend) { - return sbf.get("Number generator") - . chunk(1) + public Step numberGeneratorStep(JobRepository jobRepositories, PlatformTransactionManager transactionManager, int[] values, String prepend) { + return new StepBuilder("Number generator", jobRepositories) + . chunk(1, transactionManager) .reader(new NumberInfoGenerator(values)) .processor(new NumberInfoClassifier()) .writer(new PrependingStdoutWriter<>(prepend)) .build(); } - public Step numberGeneratorStepDecider(StepBuilderFactory sbf, int[] values, String prepend) { - return sbf.get("Number generator decider") - . chunk(1) + public Step numberGeneratorStepDecider(JobRepository jobRepositories, PlatformTransactionManager transactionManager, int[] values, String prepend) { + return new StepBuilder("Number generator decider", jobRepositories) + . chunk(1, transactionManager) .reader(new NumberInfoGenerator(values)) .processor(new NumberInfoClassifierWithDecider()) .writer(new PrependingStdoutWriter<>(prepend)) @@ -47,10 +57,10 @@ public class NumberInfoConfig { @Bean @Qualifier("first_job") - public Job numberGeneratorNonNotifierJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, @Qualifier("NotificationStep") Step notificationStep) { + public Job numberGeneratorNonNotifierJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("NotificationStep") Step notificationStep) { int[] nonNotifierData = { -1, -2, -3 }; - Step step = numberGeneratorStep(stepBuilderFactory, nonNotifierData, "First Dataset Processor"); - return jobBuilderFactory.get("Number generator - first dataset") + Step step = numberGeneratorStep(jobRepository, transactionManager, nonNotifierData, "First Dataset Processor"); + return new JobBuilder("Number generator - first dataset", jobRepository) .start(step) .on(NOTIFY) .to(notificationStep) @@ -63,10 +73,10 @@ public class NumberInfoConfig { @Bean @Qualifier("second_job") - public Job numberGeneratorNotifierJob(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, @Qualifier("NotificationStep") Step notificationStep) { + public Job numberGeneratorNotifierJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("NotificationStep") Step notificationStep) { int[] billableData = { 11, -2, -3 }; - Step dataProviderStep = numberGeneratorStep(stepBuilderFactory, billableData, "Second Dataset Processor"); - return jobBuilderFactory.get("Number generator - second dataset") + Step dataProviderStep = numberGeneratorStep(jobRepository, transactionManager, billableData, "Second Dataset Processor"); + return new JobBuilder("Number generator - second dataset", jobRepository) .start(dataProviderStep) .on(NOTIFY) .to(notificationStep) @@ -77,10 +87,10 @@ public class NumberInfoConfig { @Bean @Qualifier("third_job") @Primary - public Job numberGeneratorNotifierJobWithDecider(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory, @Qualifier("NotificationStep") Step notificationStep) { + public Job numberGeneratorNotifierJobWithDecider(JobRepository jobRepository, PlatformTransactionManager transactionManager, @Qualifier("NotificationStep") Step notificationStep) { int[] billableData = { 11, -2, -3 }; - Step dataProviderStep = numberGeneratorStepDecider(stepBuilderFactory, billableData, "Third Dataset Processor"); - return jobBuilderFactory.get("Number generator - third dataset") + Step dataProviderStep = numberGeneratorStepDecider(jobRepository, transactionManager, billableData, "Third Dataset Processor"); + return new JobBuilder("Number generator - third dataset", jobRepository) .start(dataProviderStep) .next(new NumberInfoDecider()) .on(NOTIFY) @@ -88,4 +98,39 @@ public class NumberInfoConfig { .end() .build(); } + + @Bean(name = "jobRepository") + public JobRepository getJobRepository() throws Exception { + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(dataSource()); + factory.setTransactionManager(getTransactionManager()); + // JobRepositoryFactoryBean's methods Throws Generic Exception, + // it would have been better to have a specific one + factory.afterPropertiesSet(); + return factory.getObject(); + } + + @Bean(name = "dataSource") + public DataSource dataSource() { + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + return builder.setType(EmbeddedDatabaseType.H2) + .addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql") + .addScript("classpath:org/springframework/batch/core/schema-h2.sql") + .build(); + } + + @Bean(name = "transactionManager") + public PlatformTransactionManager getTransactionManager() { + return new ResourcelessTransactionManager(); + } + + @Bean(name = "jobLauncher") + public JobLauncher getJobLauncher() throws Exception { + TaskExecutorJobLauncher jobLauncher = new TaskExecutorJobLauncher(); + // SimpleJobLauncher's methods Throws Generic Exception, + // it would have been better to have a specific one + jobLauncher.setJobRepository(getJobRepository()); + jobLauncher.afterPropertiesSet(); + return jobLauncher; + } } diff --git a/spring-batch/src/main/java/org/baeldung/conditionalflow/step/NotifierTasklet.java b/spring-batch/src/main/java/org/baeldung/conditionalflow/step/NotifierTasklet.java index 0d1db66fe9..99ec151cba 100644 --- a/spring-batch/src/main/java/org/baeldung/conditionalflow/step/NotifierTasklet.java +++ b/spring-batch/src/main/java/org/baeldung/conditionalflow/step/NotifierTasklet.java @@ -7,9 +7,8 @@ import org.springframework.batch.repeat.RepeatStatus; public class NotifierTasklet implements Tasklet { @Override - public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception { - System.err.println("[" + chunkContext.getStepContext() - .getJobName() + "] contains interesting data!!"); + public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) { + System.err.println("[" + chunkContext.getStepContext().getJobName() + "] contains interesting data!!"); return RepeatStatus.FINISHED; } } diff --git a/spring-batch/src/main/java/org/baeldung/conditionalflow/step/NumberInfoClassifier.java b/spring-batch/src/main/java/org/baeldung/conditionalflow/step/NumberInfoClassifier.java index fdb28263e7..71d88e3f0a 100644 --- a/spring-batch/src/main/java/org/baeldung/conditionalflow/step/NumberInfoClassifier.java +++ b/spring-batch/src/main/java/org/baeldung/conditionalflow/step/NumberInfoClassifier.java @@ -29,7 +29,7 @@ public class NumberInfoClassifier extends ItemListenerSupport implements ItemProcessor { @Override - public Integer process(NumberInfo numberInfo) throws Exception { + public Integer process(NumberInfo numberInfo) { return Integer.valueOf(numberInfo.getNumber()); } } diff --git a/spring-batch/src/main/java/org/baeldung/conditionalflow/step/PrependingStdoutWriter.java b/spring-batch/src/main/java/org/baeldung/conditionalflow/step/PrependingStdoutWriter.java index 9ffea1e798..abadb78e93 100644 --- a/spring-batch/src/main/java/org/baeldung/conditionalflow/step/PrependingStdoutWriter.java +++ b/spring-batch/src/main/java/org/baeldung/conditionalflow/step/PrependingStdoutWriter.java @@ -1,7 +1,6 @@ package org.baeldung.conditionalflow.step; -import java.util.List; - +import org.springframework.batch.item.Chunk; import org.springframework.batch.item.ItemWriter; public class PrependingStdoutWriter implements ItemWriter { @@ -12,8 +11,8 @@ public class PrependingStdoutWriter implements ItemWriter { } @Override - public void write(List list) { - for (T listItem : list) { + public void write(Chunk chunk) { + for (T listItem : chunk) { System.out.println(prependText + " " + listItem.toString()); } } diff --git a/spring-batch/src/main/resources/output/output1.xml b/spring-batch/src/main/resources/output/output1.xml index 838d04882a..78bc7349e8 100644 --- a/spring-batch/src/main/resources/output/output1.xml +++ b/spring-batch/src/main/resources/output/output1.xml @@ -1,21 +1,21 @@ - - 10000.0 - 2015-10-31 00:00:00 - 1234 - devendra - - - 12321.0 - 2015-12-03 00:00:00 - 2134 - john - - - 23411.0 - 2015-02-02 00:00:00 - 2134 - robin - + + 10000.0 + 2015-10-31 00:00:00 + 1234 + devendra + + + 12321.0 + 2015-12-03 00:00:00 + 2134 + john + + + 23411.0 + 2015-02-02 00:00:00 + 2134 + robin + \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output2.xml b/spring-batch/src/main/resources/output/output2.xml index 838d04882a..78bc7349e8 100644 --- a/spring-batch/src/main/resources/output/output2.xml +++ b/spring-batch/src/main/resources/output/output2.xml @@ -1,21 +1,21 @@ - - 10000.0 - 2015-10-31 00:00:00 - 1234 - devendra - - - 12321.0 - 2015-12-03 00:00:00 - 2134 - john - - - 23411.0 - 2015-02-02 00:00:00 - 2134 - robin - + + 10000.0 + 2015-10-31 00:00:00 + 1234 + devendra + + + 12321.0 + 2015-12-03 00:00:00 + 2134 + john + + + 23411.0 + 2015-02-02 00:00:00 + 2134 + robin + \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output3.xml b/spring-batch/src/main/resources/output/output3.xml index 838d04882a..78bc7349e8 100644 --- a/spring-batch/src/main/resources/output/output3.xml +++ b/spring-batch/src/main/resources/output/output3.xml @@ -1,21 +1,21 @@ - - 10000.0 - 2015-10-31 00:00:00 - 1234 - devendra - - - 12321.0 - 2015-12-03 00:00:00 - 2134 - john - - - 23411.0 - 2015-02-02 00:00:00 - 2134 - robin - + + 10000.0 + 2015-10-31 00:00:00 + 1234 + devendra + + + 12321.0 + 2015-12-03 00:00:00 + 2134 + john + + + 23411.0 + 2015-02-02 00:00:00 + 2134 + robin + \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output4.xml b/spring-batch/src/main/resources/output/output4.xml index 838d04882a..78bc7349e8 100644 --- a/spring-batch/src/main/resources/output/output4.xml +++ b/spring-batch/src/main/resources/output/output4.xml @@ -1,21 +1,21 @@ - - 10000.0 - 2015-10-31 00:00:00 - 1234 - devendra - - - 12321.0 - 2015-12-03 00:00:00 - 2134 - john - - - 23411.0 - 2015-02-02 00:00:00 - 2134 - robin - + + 10000.0 + 2015-10-31 00:00:00 + 1234 + devendra + + + 12321.0 + 2015-12-03 00:00:00 + 2134 + john + + + 23411.0 + 2015-02-02 00:00:00 + 2134 + robin + \ No newline at end of file diff --git a/spring-batch/src/main/resources/output/output5.xml b/spring-batch/src/main/resources/output/output5.xml index 838d04882a..78bc7349e8 100644 --- a/spring-batch/src/main/resources/output/output5.xml +++ b/spring-batch/src/main/resources/output/output5.xml @@ -1,21 +1,21 @@ - - 10000.0 - 2015-10-31 00:00:00 - 1234 - devendra - - - 12321.0 - 2015-12-03 00:00:00 - 2134 - john - - - 23411.0 - 2015-02-02 00:00:00 - 2134 - robin - + + 10000.0 + 2015-10-31 00:00:00 + 1234 + devendra + + + 12321.0 + 2015-12-03 00:00:00 + 2134 + john + + + 23411.0 + 2015-02-02 00:00:00 + 2134 + robin + \ No newline at end of file diff --git a/spring-batch/src/main/resources/spring-batch-intro.xml b/spring-batch/src/main/resources/spring-batch-intro.xml index 2a7c1e7c4a..bb11ea0efd 100644 --- a/spring-batch/src/main/resources/spring-batch-intro.xml +++ b/spring-batch/src/main/resources/spring-batch-intro.xml @@ -17,7 +17,7 @@ + value="username,userid,transactiondate,amount" /> @@ -33,11 +33,11 @@ - + - + com.baeldung.batch.model.Transaction diff --git a/spring-batch/src/main/resources/spring.xml b/spring-batch/src/main/resources/spring.xml index dea261c5e6..fc7e867941 100644 --- a/spring-batch/src/main/resources/spring.xml +++ b/spring-batch/src/main/resources/spring.xml @@ -9,8 +9,8 @@ - - + + @@ -18,8 +18,8 @@ - + location="org/springframework/batch/core/schema-drop-h2.sql" /> + @@ -31,7 +31,6 @@ class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> - { - assertThat(stepExecution.getWriteCount(), is(8)); + assertEquals(8L, stepExecution.getWriteCount()); }); } diff --git a/spring-batch/src/test/java/com/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java b/spring-batch/src/test/java/com/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java index 4655117b85..311bd828cb 100644 --- a/spring-batch/src/test/java/com/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java +++ b/spring-batch/src/test/java/com/baeldung/batchtesting/SpringBatchStepScopeIntegrationTest.java @@ -1,22 +1,21 @@ package com.baeldung.batchtesting; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.springframework.batch.test.AssertFile.assertFileEquals; -import java.util.Arrays; +import java.util.List; -import com.baeldung.batchtesting.SpringBatchConfiguration; import com.baeldung.batchtesting.model.Book; import com.baeldung.batchtesting.model.BookRecord; -import org.junit.After; -import org.junit.Test; -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.StepExecution; +import org.springframework.batch.item.Chunk; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.json.JsonFileItemWriter; -import org.springframework.batch.test.AssertFile; import org.springframework.batch.test.JobRepositoryTestUtils; import org.springframework.batch.test.MetaDataInstanceFactory; import org.springframework.batch.test.StepScopeTestUtils; @@ -24,21 +23,12 @@ import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.core.io.FileSystemResource; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.annotation.DirtiesContext.ClassMode; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; -import org.springframework.test.context.support.DirtiesContextTestExecutionListener; -@RunWith(SpringRunner.class) @SpringBatchTest @EnableAutoConfiguration @ContextConfiguration(classes = { SpringBatchConfiguration.class }) -@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) public class SpringBatchStepScopeIntegrationTest { private static final String TEST_OUTPUT = "src/test/resources/output/actual-output.json"; @@ -62,7 +52,7 @@ public class SpringBatchStepScopeIntegrationTest { return paramsBuilder.toJobParameters(); } - @After + @AfterEach public void cleanUp() { jobRepositoryTestUtils.removeJobExecutions(); } @@ -80,11 +70,11 @@ public class SpringBatchStepScopeIntegrationTest { while ((bookRecord = itemReader.read()) != null) { // then - assertThat(bookRecord.getBookName(), is("Foundation")); - assertThat(bookRecord.getBookAuthor(), is("Asimov I.")); - assertThat(bookRecord.getBookISBN(), is("ISBN 12839")); - assertThat(bookRecord.getBookFormat(), is("hardcover")); - assertThat(bookRecord.getPublishingYear(), is("2018")); + assertEquals("Foundation", bookRecord.getBookName()); + assertEquals("Asimov I.", bookRecord.getBookAuthor()); + assertEquals("ISBN 12839", bookRecord.getBookISBN()); + assertEquals("hardcover", bookRecord.getBookFormat()); + assertEquals("2018", bookRecord.getPublishingYear()); } itemReader.close(); return null; @@ -106,12 +96,12 @@ public class SpringBatchStepScopeIntegrationTest { StepScopeTestUtils.doInStepScope(stepExecution, () -> { jsonItemWriter.open(stepExecution.getExecutionContext()); - jsonItemWriter.write(Arrays.asList(demoBook)); + jsonItemWriter.write(new Chunk<>(List.of(demoBook))); jsonItemWriter.close(); return null; }); // then - AssertFile.assertFileEquals(expectedResult, actualResult); + assertFileEquals(expectedResult, actualResult); } } diff --git a/spring-batch/src/test/java/com/baeldung/taskletsvschunks/chunks/ChunksIntegrationTest.java b/spring-batch/src/test/java/com/baeldung/taskletsvschunks/chunks/ChunksIntegrationTest.java index 1132e4d5e2..109342076b 100644 --- a/spring-batch/src/test/java/com/baeldung/taskletsvschunks/chunks/ChunksIntegrationTest.java +++ b/spring-batch/src/test/java/com/baeldung/taskletsvschunks/chunks/ChunksIntegrationTest.java @@ -1,25 +1,29 @@ package com.baeldung.taskletsvschunks.chunks; +import static org.junit.jupiter.api.Assertions.assertEquals; + import com.baeldung.taskletsvschunks.config.ChunksConfig; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.Test; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.test.JobLauncherTestUtils; +import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = ChunksConfig.class) +@SpringBatchTest +@EnableAutoConfiguration +@ContextConfiguration(classes = ChunksConfig.class) public class ChunksIntegrationTest { - @Autowired private JobLauncherTestUtils jobLauncherTestUtils; + @Autowired + private JobLauncherTestUtils jobLauncherTestUtils; @Test public void givenChunksJob_WhenJobEnds_ThenStatusCompleted() throws Exception { JobExecution jobExecution = jobLauncherTestUtils.launchJob(); - Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); } } \ No newline at end of file diff --git a/spring-batch/src/test/java/com/baeldung/taskletsvschunks/tasklets/TaskletsIntegrationTest.java b/spring-batch/src/test/java/com/baeldung/taskletsvschunks/tasklets/TaskletsIntegrationTest.java index 2e1ad031aa..103b1a2096 100644 --- a/spring-batch/src/test/java/com/baeldung/taskletsvschunks/tasklets/TaskletsIntegrationTest.java +++ b/spring-batch/src/test/java/com/baeldung/taskletsvschunks/tasklets/TaskletsIntegrationTest.java @@ -1,25 +1,29 @@ package com.baeldung.taskletsvschunks.tasklets; +import static org.junit.jupiter.api.Assertions.assertEquals; + import com.baeldung.taskletsvschunks.config.TaskletsConfig; -import org.junit.Assert; -import org.junit.Test; -import org.junit.runner.RunWith; + +import org.junit.jupiter.api.Test; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.test.JobLauncherTestUtils; +import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -@RunWith(SpringJUnit4ClassRunner.class) +@SpringBatchTest +@EnableAutoConfiguration @ContextConfiguration(classes = TaskletsConfig.class) public class TaskletsIntegrationTest { - @Autowired private JobLauncherTestUtils jobLauncherTestUtils; + @Autowired + private JobLauncherTestUtils jobLauncherTestUtils; @Test public void givenTaskletsJob_WhenJobEnds_ThenStatusCompleted() throws Exception { JobExecution jobExecution = jobLauncherTestUtils.launchJob(); - Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); + assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus()); } } \ No newline at end of file diff --git a/spring-batch/src/test/java/org/baeldung/conditionalflow/DeciderJobIntegrationTest.java b/spring-batch/src/test/java/org/baeldung/conditionalflow/DeciderJobIntegrationTest.java index e73cb17494..a50ad0455c 100644 --- a/spring-batch/src/test/java/org/baeldung/conditionalflow/DeciderJobIntegrationTest.java +++ b/spring-batch/src/test/java/org/baeldung/conditionalflow/DeciderJobIntegrationTest.java @@ -1,8 +1,10 @@ package org.baeldung.conditionalflow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + import org.baeldung.conditionalflow.config.NumberInfoConfig; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; import org.springframework.batch.core.ExitStatus; import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.StepExecution; @@ -10,26 +12,16 @@ import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.batch.test.context.SpringBatchTest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; -import org.springframework.test.context.support.DirtiesContextTestExecutionListener; import java.util.Collection; import java.util.Iterator; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -@RunWith(SpringRunner.class) @SpringBatchTest @EnableAutoConfiguration @ContextConfiguration(classes = { NumberInfoConfig.class }) -@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class }) -@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) public class DeciderJobIntegrationTest { + @Autowired private JobLauncherTestUtils jobLauncherTestUtils; @@ -39,8 +31,7 @@ public class DeciderJobIntegrationTest { Collection actualStepExecutions = jobExecution.getStepExecutions(); ExitStatus actualJobExitStatus = jobExecution.getExitStatus(); - assertEquals("COMPLETED", actualJobExitStatus.getExitCode() - .toString()); + assertEquals("COMPLETED", actualJobExitStatus.getExitCode()); assertEquals(2, actualStepExecutions.size()); boolean notifyStepDidRun = false; Iterator iterator = actualStepExecutions.iterator(); diff --git a/spring-batch/src/test/java/org/baeldung/conditionalflow/model/NumberInfoUnitTest.java b/spring-batch/src/test/java/org/baeldung/conditionalflow/model/NumberInfoUnitTest.java index dc396b38da..bdecee5621 100644 --- a/spring-batch/src/test/java/org/baeldung/conditionalflow/model/NumberInfoUnitTest.java +++ b/spring-batch/src/test/java/org/baeldung/conditionalflow/model/NumberInfoUnitTest.java @@ -5,10 +5,10 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.test.context.junit.jupiter.SpringExtension; -@RunWith(SpringJUnit4ClassRunner.class) +@ExtendWith(SpringExtension.class) class NumberInfoUnitTest { @Test diff --git a/spring-batch/src/test/resources/output/actual-output.json b/spring-batch/src/test/resources/output/actual-output.json index 1fd6cfcf37..32ad8b7ead 100644 --- a/spring-batch/src/test/resources/output/actual-output.json +++ b/spring-batch/src/test/resources/output/actual-output.json @@ -1,3 +1,10 @@ [ - {"author":"Grisham J.","name":"The Firm"} + {"author":"Asimov I.","name":"Foundation"}, + {"author":"Strugatski A.","name":"Roadside Picnic"}, + {"author":"Murakami H.","name":"Norwegian Wood"}, + {"author":"Brown D.","name":"Davinci Code"}, + {"author":"Dick K. P.","name":"Ubik"}, + {"author":"King S.","name":"JFK"}, + {"author":"Sagan C.","name":"Contact"}, + {"author":"Huxley A.","name":"Brave New World"} ]