diff --git a/spring-batch-2/README.md b/spring-batch-2/README.md index 08bf1933db..9b5d59f0b9 100644 --- a/spring-batch-2/README.md +++ b/spring-batch-2/README.md @@ -1,3 +1,5 @@ ### Relevant Articles: - [Spring Boot With Spring Batch](https://www.baeldung.com/spring-boot-spring-batch) +- [How to Trigger and Stop a Scheduled Spring Batch Job](https://www.baeldung.com/spring-batch-start-stop-job) +- More articles [[<-- prev]](/spring-batch) diff --git a/spring-batch-2/pom.xml b/spring-batch-2/pom.xml index c429c272bd..12d31aca14 100644 --- a/spring-batch-2/pom.xml +++ b/spring-batch-2/pom.xml @@ -22,10 +22,8 @@ spring-boot-starter-batch - org.hsqldb - hsqldb - ${hsqldb.version} - runtime + com.h2database + h2 org.springframework.boot @@ -44,11 +42,17 @@ ${spring.batch.version} test + + org.awaitility + awaitility + ${awaitility.version} + test + 4.3.0 - 2.5.1 + 3.1.1 \ No newline at end of file diff --git a/spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java similarity index 69% rename from spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java rename to spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java index cff4e96c89..c830a41855 100644 --- a/spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java +++ b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java @@ -11,26 +11,20 @@ import org.springframework.batch.core.configuration.annotation.EnableBatchProces 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.repository.JobRepository; -import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; 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.batch.support.transaction.ResourcelessTransactionManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; -import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.scheduling.TaskScheduler; 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 javax.sql.DataSource; import java.util.Date; import java.util.IdentityHashMap; import java.util.List; @@ -58,13 +52,16 @@ public class SpringBatchScheduler { @Autowired private StepBuilderFactory stepBuilderFactory; + @Autowired + private JobLauncher jobLauncher; + @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) - .toJobParameters()); + JobExecution jobExecution = jobLauncher.run(job(), new JobParametersBuilder().addDate("launchDate", date) + .toJobParameters()); batchRunCounter.incrementAndGet(); logger.debug("Batch job ends with status as " + jobExecution.getStatus()); } @@ -110,56 +107,33 @@ public class SpringBatchScheduler { @Bean public Job job() { - return jobBuilderFactory.get("job") - .start(readBooks()) - .build(); - } - - @Bean - public JobLauncher jobLauncher() throws Exception { - SimpleJobLauncher jobLauncher = new SimpleJobLauncher(); - jobLauncher.setJobRepository(jobRepository()); - jobLauncher.afterPropertiesSet(); - return jobLauncher; - } - - @Bean - public JobRepository jobRepository() throws Exception { - JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); - factory.setDataSource(dataSource()); - factory.setTransactionManager(new ResourcelessTransactionManager()); - return factory.getObject(); - } - - @Bean - public DataSource dataSource() { - DriverManagerDataSource dataSource = new DriverManagerDataSource(); - dataSource.setDriverClassName("org.sqlite.JDBC"); - dataSource.setUrl("jdbc:sqlite:repository.sqlite"); - return dataSource; + return jobBuilderFactory + .get("job") + .start(readBooks()) + .build(); } @Bean protected Step readBooks() { return stepBuilderFactory.get("readBooks") - . chunk(2) - .reader(reader()) - .writer(writer()) - .build(); + . chunk(2) + .reader(reader()) + .writer(writer()) + .build(); } @Bean public FlatFileItemReader reader() { return new FlatFileItemReaderBuilder().name("bookItemReader") - .resource(new ClassPathResource("books.csv")) - .delimited() - .names(new String[] { "id", "name" }) - .fieldSetMapper(new BeanWrapperFieldSetMapper() { - { - setTargetType(Book.class); - } - }) - .build(); + .resource(new ClassPathResource("books.csv")) + .delimited() + .names(new String[] { "id", "name" }) + .fieldSetMapper(new BeanWrapperFieldSetMapper() { + { + setTargetType(Book.class); + } + }) + .build(); } @Bean diff --git a/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchSchedulerApplication.java b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchSchedulerApplication.java new file mode 100644 index 0000000000..349a359efb --- /dev/null +++ b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/SpringBatchSchedulerApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.batchscheduler; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBatchSchedulerApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBatchSchedulerApplication.class, args); + } + +} diff --git a/spring-batch/src/main/java/com/baeldung/batchscheduler/model/Book.java b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/model/Book.java similarity index 98% rename from spring-batch/src/main/java/com/baeldung/batchscheduler/model/Book.java rename to spring-batch-2/src/main/java/com/baeldung/batchscheduler/model/Book.java index 8ee986c729..7deedeb63e 100644 --- a/spring-batch/src/main/java/com/baeldung/batchscheduler/model/Book.java +++ b/spring-batch-2/src/main/java/com/baeldung/batchscheduler/model/Book.java @@ -3,7 +3,7 @@ package com.baeldung.batchscheduler.model; public class Book { private int id; private String name; - + public Book() {} public Book(int id, String name) { @@ -27,7 +27,7 @@ public class Book { public void setName(String name) { this.name = name; } - + public String toString() { return "Book [id=" + id + ", name=" + name + "]"; } diff --git a/spring-batch/src/main/resources/books.csv b/spring-batch-2/src/main/resources/books.csv similarity index 100% rename from spring-batch/src/main/resources/books.csv rename to spring-batch-2/src/main/resources/books.csv diff --git a/spring-batch/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java b/spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java similarity index 76% rename from spring-batch/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java rename to spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java index 81877fbc39..61e5a1dd74 100644 --- a/spring-batch/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java +++ b/spring-batch-2/src/test/java/com/baeldung/batchscheduler/SpringBatchSchedulerIntegrationTest.java @@ -4,32 +4,40 @@ 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.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.*; -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = SpringBatchScheduler.class) +@SpringBatchTest +@SpringBootTest +@DirtiesContext +@PropertySource("classpath:application.properties") +@RunWith(SpringRunner.class) public class SpringBatchSchedulerIntegrationTest { @Autowired private ApplicationContext context; @Test - public void stopJobsWhenSchedulerDisabled() throws Exception { + public void stopJobsWhenSchedulerDisabled() { SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get())); + .get())); schedulerBean.stop(); await().atLeast(3, SECONDS); Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get()); + .get()); } @Test @@ -37,24 +45,24 @@ public class SpringBatchSchedulerIntegrationTest { ScheduledAnnotationBeanPostProcessor bean = context.getBean(ScheduledAnnotationBeanPostProcessor.class); SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get())); + .get())); bean.postProcessBeforeDestruction(schedulerBean, "SpringBatchScheduler"); await().atLeast(3, SECONDS); Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get()); + .get()); } @Test public void stopJobSchedulerWhenFutureTasksCancelled() throws Exception { SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get())); + .get())); schedulerBean.cancelFutureSchedulerTasks(); await().atLeast(3, SECONDS); Assert.assertEquals(2, schedulerBean.getBatchRunCounter() - .get()); + .get()); } diff --git a/spring-batch/README.md b/spring-batch/README.md index 3a89459629..b87a2149a0 100644 --- a/spring-batch/README.md +++ b/spring-batch/README.md @@ -7,8 +7,8 @@ This module contains articles about Spring Batch - [Introduction to Spring Batch](https://www.baeldung.com/introduction-to-spring-batch) - [Spring Batch using Partitioner](https://www.baeldung.com/spring-batch-partitioner) - [Spring Batch – Tasklets vs Chunks](https://www.baeldung.com/spring-batch-tasklet-chunk) -- [How to Trigger and Stop a Scheduled Spring Batch Job](https://www.baeldung.com/spring-batch-start-stop-job) - [Configuring Skip Logic in Spring Batch](https://www.baeldung.com/spring-batch-skip-logic) - [Testing a Spring Batch Job](https://www.baeldung.com/spring-batch-testing-job) - [Configuring Retry Logic in Spring Batch](https://www.baeldung.com/spring-batch-retry-logic) - [Conditional Flow in Spring Batch](https://www.baeldung.com/spring-batch-conditional-flow) +- More articles [[next -->]](/spring-batch-2) diff --git a/spring-batch/pom.xml b/spring-batch/pom.xml index 9879a4777f..32126fec9b 100644 --- a/spring-batch/pom.xml +++ b/spring-batch/pom.xml @@ -82,12 +82,6 @@ hsqldb runtime - - org.awaitility - awaitility - ${awaitility.version} - test - @@ -97,7 +91,6 @@ 4.1 2.3.1 2.12.3 - 3.1.1 \ No newline at end of file diff --git a/spring-batch/repository.sqlite b/spring-batch/repository.sqlite index a2b87ffa00..b6a954554c 100644 Binary files a/spring-batch/repository.sqlite and b/spring-batch/repository.sqlite differ