Provide Best Programming Tutorials

Spring Batch Example Job with Parallel Steps

Overview

This tutorial will show you how to run a Spring Batch Job with parallel steps.

For scaling a Batch Job, Parallel Steps is one solution that bases on the business logic of the application. We split the logic business in distinct responsibilities, and each step can be executed in parallelized flow.

Technologies used

  • spring-batch-starter-batch
  • JDK 1.8
  • Maven 3
  • Mysql

Project Structure

Steps

  1. Create a Spring Boot project
  2. Add dependencies
  3. Config Batch Job DataSource
  4. Create a Simple Tasklet Step
  5. Create a Job Launch
  6. Enable Batch Job
  7. Define Spring Batch Job with XML config
  8. Run & Check Result

Practices

1.Create a Spring Boot Project

2. Add maven dependencies

<?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.javasampleapproach</groupId>
  <artifactId>SpringBatchParallelStep</artifactId>
  <version>0.0.1</version>
  <packaging>jar</packaging>
​
  <name>SpringBatchParallelStep</name>
  <description>Spring Batch Parallel Step</description>
​
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.1.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-web</artifactId>
    </dependency>
​
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-batch</artifactId>
    </dependency>
​
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
    </dependency>
​
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>
​
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
​
</project>
​

3.Config Batch Job Datasource

application.properties

spring.datasource.url=jdbc:mysql://localhost:3307/details
spring.datasource.username=root
spring.datasource.password=123456
spring.batch.job.enabled=false

4.Create a Simple Tasklet Step

Create a SimpleStep that implements the Tasklet interface. We define a workload function for simulating card processing.

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 SimpleStep implements Tasklet{
​
    @Override
    public RepeatStatus execute(StepContribution contribution,
            ChunkContext chunkContext) throws Exception {
        workload();
        System.out.println("Done");
        return RepeatStatus.FINISHED;
    }
    
    private void workload() throws Exception{
        Thread.sleep(5000);
    }

}

5.Define Spring Batch Job With XML Config

We defines 4 steps: step_1, step_2, step_3, step_4. Step_1, Step_2, Step_3 are designed for parallel processing with 3 flow in a split split_1.

After split_1 is Done, it means: step_1, step_2, step_3 are Done, then step_4 is processed.

<beans:beans xmlns="http://www.springframework.org/schema/batch"
    xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/batch
           http://www.springframework.org/schema/batch/spring-batch-3.0.xsd">
​
    <job id="job">
        <split id="split_1" task-executor="taskExecutor" next="step_4">
            <flow>
                <step id="step_1">
                    <tasklet ref="taskletStep_1"/>
                </step>
            </flow>
            <flow>
                <step id="step_2">
                    <tasklet ref="taskletStep_2"/>
                </step>
            </flow>
            <flow>
                <step id="step_3">
                    <tasklet ref="taskletStep_3"/>
                </step>
            </flow>
        </split>
        <step id="step_4">
                    <tasklet ref="taskletStep_3"/>
        </step>
    </job>
​
    <beans:bean id="taskletStep_1" class="com.javasampleapproach.batch.parallelstep.step.SimpleStep" />
    <beans:bean id="taskletStep_2" class="com.javasampleapproach.batch.parallelstep.step.SimpleStep" />
    <beans:bean id="taskletStep_3" class="com.javasampleapproach.batch.parallelstep.step.SimpleStep" />
    <beans:bean id="taskletStep_4" class="com.javasampleapproach.batch.parallelstep.step.SimpleStep" />
    
    <beans:bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor" />
​
</beans:beans>

The TaskExecutor is defaulted by a SyncTaskExecutor, but for parallel processing batch job requires an asynchronous TaskExecutor. So we set task-executor=”taskExecutor” with:

<beans:bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor" />

6.Create a Job to launch

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
​
@RestController
public class JobLauncherController {
​
    @Autowired
    JobLauncher jobLauncher;
​
    @Autowired
    Job job;
​
    @RequestMapping("/launchjob")
    public String handle() throws Exception {
​
        Logger logger = LoggerFactory.getLogger(this.getClass());
        try {
            JobParameters jobParameters = new JobParametersBuilder().addLong("time", System.currentTimeMillis())
                    .toJobParameters();
            jobLauncher.run(job, jobParameters);
        } catch (Exception e) {
            logger.info(e.getMessage());
        }
​
        return "Done";
    }
}

7.Enable Batch Job

import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
​
@SpringBootApplication
@EnableBatchProcessing
@ImportResource("classpath:batchjob.xml")
public class SpringBatchParallelStepApplication {
​
    public static void main(String[] args) {
        SpringApplication.run(SpringBatchParallelStepApplication.class, args);
    }
}

8.Run & Check Result

Build the project with Maven: clean install Run project with mode: Spring Boot App

Make a launch request: http://localhost:8080/launchjob

9.Source code

Github

springbatchtutorial_jobwithparellelsteps-master

Leave a Reply

Close Menu