Merge pull request #11507 from kwoyke/JAVA-8362

JAVA-8362: Split or move spring-batch module
This commit is contained in:
Loredana Crusoveanu 2021-11-25 16:41:08 +02:00 committed by GitHub
commit 0edbe4c8fb
10 changed files with 66 additions and 72 deletions

View File

@ -1,3 +1,5 @@
### Relevant Articles: ### Relevant Articles:
- [Spring Boot With Spring Batch](https://www.baeldung.com/spring-boot-spring-batch) - [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)

View File

@ -22,10 +22,8 @@
<artifactId>spring-boot-starter-batch</artifactId> <artifactId>spring-boot-starter-batch</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hsqldb</groupId> <groupId>com.h2database</groupId>
<artifactId>hsqldb</artifactId> <artifactId>h2</artifactId>
<version>${hsqldb.version}</version>
<scope>runtime</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -44,11 +42,17 @@
<version>${spring.batch.version}</version> <version>${spring.batch.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
<spring.batch.version>4.3.0</spring.batch.version> <spring.batch.version>4.3.0</spring.batch.version>
<hsqldb.version>2.5.1</hsqldb.version> <awaitility.version>3.1.1</awaitility.version>
</properties> </properties>
</project> </project>

View File

@ -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.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher; 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.ItemWriter;
import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; 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.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.scheduling.TaskScheduler; import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.ScheduledMethodRunnable; import org.springframework.scheduling.support.ScheduledMethodRunnable;
import javax.sql.DataSource;
import java.util.Date; import java.util.Date;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.List; import java.util.List;
@ -58,13 +52,16 @@ public class SpringBatchScheduler {
@Autowired @Autowired
private StepBuilderFactory stepBuilderFactory; private StepBuilderFactory stepBuilderFactory;
@Autowired
private JobLauncher jobLauncher;
@Scheduled(fixedRate = 2000) @Scheduled(fixedRate = 2000)
public void launchJob() throws Exception { public void launchJob() throws Exception {
Date date = new Date(); Date date = new Date();
logger.debug("scheduler starts at " + date); logger.debug("scheduler starts at " + date);
if (enabled.get()) { if (enabled.get()) {
JobExecution jobExecution = jobLauncher().run(job(), new JobParametersBuilder().addDate("launchDate", date) JobExecution jobExecution = jobLauncher.run(job(), new JobParametersBuilder().addDate("launchDate", date)
.toJobParameters()); .toJobParameters());
batchRunCounter.incrementAndGet(); batchRunCounter.incrementAndGet();
logger.debug("Batch job ends with status as " + jobExecution.getStatus()); logger.debug("Batch job ends with status as " + jobExecution.getStatus());
} }
@ -110,56 +107,33 @@ public class SpringBatchScheduler {
@Bean @Bean
public Job job() { public Job job() {
return jobBuilderFactory.get("job") return jobBuilderFactory
.start(readBooks()) .get("job")
.build(); .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;
} }
@Bean @Bean
protected Step readBooks() { protected Step readBooks() {
return stepBuilderFactory.get("readBooks") return stepBuilderFactory.get("readBooks")
.<Book, Book> chunk(2) .<Book, Book> chunk(2)
.reader(reader()) .reader(reader())
.writer(writer()) .writer(writer())
.build(); .build();
} }
@Bean @Bean
public FlatFileItemReader<Book> reader() { public FlatFileItemReader<Book> reader() {
return new FlatFileItemReaderBuilder<Book>().name("bookItemReader") return new FlatFileItemReaderBuilder<Book>().name("bookItemReader")
.resource(new ClassPathResource("books.csv")) .resource(new ClassPathResource("books.csv"))
.delimited() .delimited()
.names(new String[] { "id", "name" }) .names(new String[] { "id", "name" })
.fieldSetMapper(new BeanWrapperFieldSetMapper<Book>() { .fieldSetMapper(new BeanWrapperFieldSetMapper<Book>() {
{ {
setTargetType(Book.class); setTargetType(Book.class);
} }
}) })
.build(); .build();
} }
@Bean @Bean

View File

@ -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);
}
}

View File

@ -3,7 +3,7 @@ package com.baeldung.batchscheduler.model;
public class Book { public class Book {
private int id; private int id;
private String name; private String name;
public Book() {} public Book() {}
public Book(int id, String name) { public Book(int id, String name) {
@ -27,7 +27,7 @@ public class Book {
public void setName(String name) { public void setName(String name) {
this.name = name; this.name = name;
} }
public String toString() { public String toString() {
return "Book [id=" + id + ", name=" + name + "]"; return "Book [id=" + id + ", name=" + name + "]";
} }

View File

@ -4,32 +4,40 @@ import com.baeldung.batchscheduler.SpringBatchScheduler;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor; import org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import static org.awaitility.Awaitility.await; import static org.awaitility.Awaitility.await;
import static java.util.concurrent.TimeUnit.*; import static java.util.concurrent.TimeUnit.*;
@RunWith(SpringJUnit4ClassRunner.class) @SpringBatchTest
@ContextConfiguration(classes = SpringBatchScheduler.class) @SpringBootTest
@DirtiesContext
@PropertySource("classpath:application.properties")
@RunWith(SpringRunner.class)
public class SpringBatchSchedulerIntegrationTest { public class SpringBatchSchedulerIntegrationTest {
@Autowired @Autowired
private ApplicationContext context; private ApplicationContext context;
@Test @Test
public void stopJobsWhenSchedulerDisabled() throws Exception { public void stopJobsWhenSchedulerDisabled() {
SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class);
await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
.get())); .get()));
schedulerBean.stop(); schedulerBean.stop();
await().atLeast(3, SECONDS); await().atLeast(3, SECONDS);
Assert.assertEquals(2, schedulerBean.getBatchRunCounter() Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
.get()); .get());
} }
@Test @Test
@ -37,24 +45,24 @@ public class SpringBatchSchedulerIntegrationTest {
ScheduledAnnotationBeanPostProcessor bean = context.getBean(ScheduledAnnotationBeanPostProcessor.class); ScheduledAnnotationBeanPostProcessor bean = context.getBean(ScheduledAnnotationBeanPostProcessor.class);
SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class);
await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
.get())); .get()));
bean.postProcessBeforeDestruction(schedulerBean, "SpringBatchScheduler"); bean.postProcessBeforeDestruction(schedulerBean, "SpringBatchScheduler");
await().atLeast(3, SECONDS); await().atLeast(3, SECONDS);
Assert.assertEquals(2, schedulerBean.getBatchRunCounter() Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
.get()); .get());
} }
@Test @Test
public void stopJobSchedulerWhenFutureTasksCancelled() throws Exception { public void stopJobSchedulerWhenFutureTasksCancelled() throws Exception {
SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class); SpringBatchScheduler schedulerBean = context.getBean(SpringBatchScheduler.class);
await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter() await().untilAsserted(() -> Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
.get())); .get()));
schedulerBean.cancelFutureSchedulerTasks(); schedulerBean.cancelFutureSchedulerTasks();
await().atLeast(3, SECONDS); await().atLeast(3, SECONDS);
Assert.assertEquals(2, schedulerBean.getBatchRunCounter() Assert.assertEquals(2, schedulerBean.getBatchRunCounter()
.get()); .get());
} }

View File

@ -7,8 +7,8 @@ This module contains articles about Spring Batch
- [Introduction to Spring Batch](https://www.baeldung.com/introduction-to-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 using Partitioner](https://www.baeldung.com/spring-batch-partitioner)
- [Spring Batch Tasklets vs Chunks](https://www.baeldung.com/spring-batch-tasklet-chunk) - [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) - [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) - [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) - [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) - [Conditional Flow in Spring Batch](https://www.baeldung.com/spring-batch-conditional-flow)
- More articles [[next -->]](/spring-batch-2)

View File

@ -82,12 +82,6 @@
<artifactId>hsqldb</artifactId> <artifactId>hsqldb</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
@ -97,7 +91,6 @@
<opencsv.version>4.1</opencsv.version> <opencsv.version>4.1</opencsv.version>
<jaxb.version>2.3.1</jaxb.version> <jaxb.version>2.3.1</jaxb.version>
<jackson-datatype.version>2.12.3</jackson-datatype.version> <jackson-datatype.version>2.12.3</jackson-datatype.version>
<awaitility.version>3.1.1</awaitility.version>
</properties> </properties>
</project> </project>

Binary file not shown.