Spring Boot Batch with Scheduler Example

Spring boot batch processing is described as the automatic processing of huge amounts of data with no external involvement. Spring boot schedulers are used to automatically perform the batch process at regular intervals. The scheduler interval can be set as a fixed delay, fixed rate, or by using a cron expression. The spring boot batch will run automatically using these schedulers, with no user involvement required. This post goes over an example of a spring boot batch with a scheduler.

The spring boot batch will regularly invoke the batch process utilizing the schedulers and complete the work without any human intercession. The spring boot batch reads the data, processes it, and saves or sends it in the necessary format. It checks on a regular basis, according to the scheduler configuration. Normally, the spring boot batch is set to run in the off business hour.

The Tasklet interface is used in this example to implement a spring boot batch task. The spring boot scheduler will run the spring boot batch task, which interns refer to as the batch step. The Tasklet-implemented Task is included in the step. When the step is done, the task will be completed.



Scheduler Configuration

The spring boot scheduler configuration class helps in configuring the spring boot batch to run automatically without human involvement. To automatically invoke the spring boot batch, add the Spring boot scheduler configuration class to your spring boot project. The scheduler class should have the annotations @EnableScheduling and @Configuration. The @Scheduled annotation is used to configure a method that will run on a regular basis based on the settings.

SchedulerConfig.java

package com.yawintutor;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

@Configuration
@EnableScheduling
public class SchedulerConfig {

	@Autowired
	JobLauncher jobLauncher;

	@Autowired
	Job job;

	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");

	@Scheduled(fixedRate = 5000)
	public void scheduleByFixedRate() throws Exception {
		System.out.println("Batch job starting");
		JobParameters jobParameters = new JobParametersBuilder()
				.addString("time", format.format(Calendar.getInstance().getTime())).toJobParameters();
		jobLauncher.run(job, jobParameters);
		System.out.println("Batch job executed successfully\n");
	}
}


Spring Boot Batch Logs

If you include the spring boot scheduler class in your project, the spring boot batch will run on a regular basis and display the logs shown below. The scheduler will run once every 5 seconds. Two system out logs will show the start and finish of the spring boot batch execution.

Batch job starting
2021-07-21 09:46:29.960  INFO 58448 --- [   scheduling-1] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=MyJob]] launched with the following parameters: [{time=2021-07-21 09:46:29.955}]
2021-07-21 09:46:29.965  INFO 58448 --- [   scheduling-1] o.s.batch.core.job.SimpleStepHandler     : Executing step: [MyStep]
MyTask:execute: executing tasklet - 2021-07-21 09:46:29.967
2021-07-21 09:46:29.969  INFO 58448 --- [   scheduling-1] o.s.batch.core.step.AbstractStep         : Step: [MyStep] executed in 4ms
2021-07-21 09:46:29.972  INFO 58448 --- [   scheduling-1] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=MyJob]] completed with the following parameters: [{time=2021-07-21 09:46:29.955}] and the following status: [COMPLETED] in 10ms
Batch job executed successfully


Pom.xml

The pom.xml file contains spring boot batch dependencies as well as a database dependency. The h2 database is used in this example.

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.5.2</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.yawintutor</groupId>
	<artifactId>SpringBootBatch1</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>SpringBootBatch1</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-batch</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.batch</groupId>
			<artifactId>spring-batch-test</artifactId>
			<scope>test</scope>
		</dependency>
		
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
		</dependency>
		
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>


Application.properties

In the application.properties file, add the following configuration. The first configuration is for the h2 database url. Spring boot batch database table creation in the h2 database is the second configuration.

spring.datasource.url=jdbc:h2:file:./DB
spring.batch.initialize-schema=ALWAYS


Spring Boot Main Class

The following will show the spring boot application main class. The main class is not modified.

SpringBootBatch1Application.java

package com.yawintutor;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootBatch1Application {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootBatch1Application.class, args);
	}

}


Tasklet class

In this spring boot batch with spring boot scheduler example, the Tasklet class is used to define the batch task. Tasklet is a spring boot batch interface. This is used to process a single operation and destroy resources after or before the step begins or finishes. The example below shows the Tasklet implemented class.

MyTask.java

package com.yawintutor;

import java.text.SimpleDateFormat;
import java.util.Calendar;

import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;

public class MyTask implements Tasklet {
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
	@Override
	public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
		System.out.println("MyTask:execute: executing tasklet - "+format.format(Calendar.getInstance().getTime()));
		return null;
	}

}


Spring Boot Batch Configuration

The spring boot batch configuration class contains the batch related methods which creates Job, Step objects. These objects are used to process the batch task in the spring boot batch.

BatchConfig.java

package com.yawintutor;

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.support.RunIdIncrementer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableBatchProcessing
public class BatchConfig {
	@Autowired
	public JobBuilderFactory jobBuilderFactory;

	@Autowired
	public StepBuilderFactory stepBuilderFactory;

	@Bean
	public Job createJob() {
		return jobBuilderFactory.get("MyJob")
				.incrementer(new RunIdIncrementer())
				.start(createStep()).build();
	}
	
	@Bean
	public Step createStep() {
		return stepBuilderFactory.get("MyStep").tasklet(new MyTask()).build();
	}
	
}



Leave a Reply