Spring Boot Batch Job + Scheduler Simple Example
In a previous post we had implemented a Spring Boot Hello World
Application. In that the Batch Job got triggered by a REST API call. In this
post we develop a simple Spring Boot Batch application where batch job gets
triggered using a scheduler.
Consider the simple use case where the user wants to delete files from a particular location everyday at a particular time. We will schedule this batch job using the scheduler.
Consider the simple use case where the user wants to delete files from a particular location everyday at a particular time. We will schedule this batch job using the scheduler.
Lets Begin-
The project will be as follows-
<?xml version="1.0"
encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javainuse</groupId>
<artifactId>springboot-batch</artifactId>
<version>0.0.1</version>
<packaging>jar</packaging>
<name>SpringBatch</name>
<description>Spring
Batch-Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.3.RELEASE</version>
<relativePath
/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-batch</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Create a batch configuration class as below.
package com.javainuse.jobs;
import java.util.Date;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import
org.springframework.batch.core.JobParameters;
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.launch.support.RunIdIncrementer;
import
org.springframework.batch.core.launch.support.SimpleJobLauncher;
import
org.springframework.batch.core.repository.JobRepository;
import
org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
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.Resource;
import
org.springframework.scheduling.annotation.Scheduled;
import com.javainuse.tasklet.FileDeletingTasklet;
@Configuration
@EnableBatchProcessing
public class ProcessMultiFilesJob {
@Autowired
private JobBuilderFactory
jobBuilderFactory;
@Autowired
private StepBuilderFactory
stepBuilderFactory;
@Autowired
private SimpleJobLauncher
jobLauncher;
@Value("file:C:\\inbox\\")
private
Resource directory;
@Bean
public
ResourcelessTransactionManager transactionManager() {
return
new ResourcelessTransactionManager();
}
@Bean
public
MapJobRepositoryFactoryBean
mapJobRepositoryFactory(ResourcelessTransactionManager txManager)
throws
Exception {
MapJobRepositoryFactoryBean
factory = new MapJobRepositoryFactoryBean(txManager);
factory.afterPropertiesSet();
return
factory;
}
@Bean
public
JobRepository jobRepository(MapJobRepositoryFactoryBean factory) throws
Exception {
return
factory.getObject();
}
@Scheduled(cron = "*/5 * * * * *")
public
void perform() throws Exception {
System.out.println("Job
Started at :" + new Date());
JobParameters
param = new JobParametersBuilder().addString("JobID", String.valueOf(System.currentTimeMillis()))
.toJobParameters();
JobExecution
execution = jobLauncher.run(readFiles(), param);
System.out.println("Job
finished with status :" + execution.getStatus());
}
@Bean
public
Job readFiles() {
return
jobBuilderFactory.get("readFiles").incrementer(new
RunIdIncrementer()).flow(step1()).end().build();
}
@Bean
public
Step step1() {
return
stepBuilderFactory.get("step1").tasklet(fileDeletingTasklet()).build();
}
@Bean
public
FileDeletingTasklet fileDeletingTasklet() {
FileDeletingTasklet
tasklet = new FileDeletingTasklet();
tasklet.setDirectory(directory);
return
tasklet;
}
@Bean
public
SimpleJobLauncher jobLauncher(JobRepository
jobRepository) {
SimpleJobLauncher
launcher = new SimpleJobLauncher();
launcher.setJobRepository(jobRepository);
return
launcher;
}
}
In the above configuration, we get the reference of the
configured JobLauncher through autowired injection. Run the JobLauncher with
passing job bean and custom job parameter.
Next define the Tasklet as follows-
Next define the Tasklet as follows-
package com.javainuse.jobs;
import java.util.Date;
import org.springframework.batch.core.Job;
import
org.springframework.cbatch.core.JobExecution;
import
org.springframework.batch.core.JobParameters;
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.launch.support.RunIdIncrementer;
import
org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import
org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
import
org.springframework.batch.support.transaction.ResourcelessTransactionManager;
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.Resource;
import org.springframework.scheduling.annotation.Scheduled;
import com.javainuse.tasklet.FileDeletingTasklet;
@Configuration
@EnableBatchProcessing
public class ProcessMultiFilesJob {
@Autowired
private
JobBuilderFactory
jobBuilderFactory;
@Autowired
private
StepBuilderFactory
stepBuilderFactory;
@Autowired
private
SimpleJobLauncher
jobLauncher;
@Value("file:C:\\inbox\\")
private
Resource directory;
@Bean
public
ResourcelessTransactionManager transactionManager() {
return
new ResourcelessTransactionManager();
}
@Bean
public
MapJobRepositoryFactoryBean
mapJobRepositoryFactory(ResourcelessTransactionManager txManager) throws Exception {
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean
(txManager);
factory.afterPropertiesSet();
return
factory;
}
@Bean
public
JobRepository jobRepository(MapJobRepositoryFactoryBean factory) throws
Exception {
return
factory.getObject();
}
@Scheduled(cron =
"*/5 * * * * *")
public
void perform()
throws Exception {
System.out.println("Job
Started at :" + new Date());
JobParameters
param = new JobParametersBuilder().addString("JobID",
String.valueOf(System.currentTimeMillis()))
.toJobParameters();
JobExecution
execution = jobLauncher.run(readFiles(), param);
System.out.println("Job
finished with status :" + execution.getStatus());
}
@Bean
public
Job readFiles() {
return
jobBuilderFactory.get("readFiles").incrementer(new
RunIdIncrementer()).flow(step1()).end().build();
}
@Bean
public
Step step1() {
return
stepBuilderFactory.get("step1").tasklet(fileDeletingTasklet()).build();
}
@Bean
public
FileDeletingTasklet fileDeletingTasklet() {
FileDeletingTasklet
tasklet = new FileDeletingTasklet();
tasklet.setDirectory(directory);
return
tasklet;
}
@Bean
public
SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
SimpleJobLauncher
launcher = new SimpleJobLauncher();
launcher.setJobRepository(jobRepository);
return
launcher;
}
}
In the application.properties,
add the following property which tells the Spring Boot Application to not start the Batch Job on Application startup. Define the
class implementing the spring batch ItemProcessor interface as follows-
spring.batch.job.enabled=false
Run the following Spring Boot class to start our application
package com.javainuse;
import
org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import
org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(exclude =
DataSourceAutoConfiguration.class)
@EnableBatchProcessing
public class SpringBatchApplication {
public
static void main(String[] args) {
SpringApplication.run(SpringBatchApplication.class,
args);
}
}
The files from the specified folder location get deleted each time the scheduler runs. In our case every 5 seconds.
No comments:
Post a Comment