Comprehensive Spring Batch Tutorial: Architecture, Core Interfaces, and Practical Implementation

This article provides an in‑depth guide to Spring Batch, covering its overall architecture, supported business scenarios, core components such as JobRepository, JobLauncher, Job, Step, and ItemReader/Processor/Writer, and demonstrates practical implementations including Maven configuration, multi‑step jobs, parallel flows, decision logic, nested jobs, data readers, writers, processors, and scheduling integration.

Top Architect
Top Architect
Top Architect
Comprehensive Spring Batch Tutorial: Architecture, Core Interfaces, and Practical Implementation

Spring Batch is a lightweight, comprehensive batch processing framework built on Spring, designed to create robust batch applications for enterprise daily operations while leveraging Spring's productivity and POJO‑based development model.

It is not a scheduler; instead, it works alongside external schedulers like Quartz, Tivoli, or Control‑M to trigger jobs.

Business scenarios supported by Spring Batch include:

Periodic batch submissions

Concurrent batch processing (parallel job execution)

Stage‑based enterprise message‑driven processing

Large‑scale parallel batch processing

Manual or scheduled restart after failures

Ordered step processing (extendable to workflow‑driven batches)

Partial processing with record skipping (e.g., on rollback)

Transactional batch execution for small batches or existing stored procedures/scripts

Core architecture components (see table):

Name

Purpose

JobRepository

Provides persistence for Job, JobInstance, and Step metadata

JobLauncher JobLauncher launches a Job with a set of JobParameters Job Job encapsulates the entire batch process

Step Step represents an independent phase of a job

Core interfaces : ItemReader: abstraction for reading a chunk of items from a

Step
ItemProcessor

: abstraction for business processing of each item ItemWriter: abstraction for writing a chunk of items after processing

The typical flow is ItemReader → ItemProcessor → ItemWriter, with a Job containing multiple Step s.

1. Adding Spring Batch to a Spring Boot project

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.2.5.RELEASE</version>
</parent>
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-batch</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
  </dependency>
</dependencies>

Enable batch processing in the main class:

@SpringBootApplication
@EnableBatchProcessing
public class SpringBatchStartApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBatchStartApplication.class, args);
    }
}

2. Defining a simple job (FirstJobDemo)

@Component
public class FirstJobDemo {
    @Autowired private JobBuilderFactory jobBuilderFactory;
    @Autowired private StepBuilderFactory stepBuilderFactory;

    @Bean
    public Job firstJob() {
        return jobBuilderFactory.get("firstJob")
                .start(step())
                .build();
    }

    private Step step() {
        return stepBuilderFactory.get("step")
                .tasklet((contribution, chunkContext) -> {
                    System.out.println("执行步骤....");
                    return RepeatStatus.FINISHED;
                })
                .build();
    }
}

3. Multi‑step job with flow control

@Bean
public Job multiStepJob() {
    return jobBuilderFactory.get("multiStepJob2")
            .start(step1())
            .on(ExitStatus.COMPLETED.getExitCode()).to(step2())
            .from(step2()).on(ExitStatus.COMPLETED.getExitCode()).to(step3())
            .from(step3()).end()
            .build();
}

private Step step1() { /* similar to step2/step3 */ }
private Step step2() { /* similar to step1 */ }
private Step step3() { /* similar to step1 */ }

4. Parallel execution using split

@Bean
public Job splitJob() {
    return jobBuilderFactory.get("splitJob")
            .start(flow1())
            .split(new SimpleAsyncTaskExecutor())
            .add(flow2())
            .end()
            .build();
}

private Flow flow1() {
    return new FlowBuilder<Flow>("flow1")
            .start(step1())
            .next(step2())
            .build();
}

private Flow flow2() {
    return new FlowBuilder<Flow>("flow2")
            .start(step3())
            .build();
}

5. Decision logic (JobExecutionDecider)

@Component
public class MyDecider implements JobExecutionDecider {
    @Override
    public FlowExecutionStatus decide(JobExecution jobExecution, StepExecution stepExecution) {
        DayOfWeek day = LocalDate.now().getDayOfWeek();
        if (day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY) {
            return new FlowExecutionStatus("weekend");
        } else {
            return new FlowExecutionStatus("workingDay");
        }
    }
}

Job using the decider:

@Bean
public Job deciderJob() {
    return jobBuilderFactory.get("deciderJob")
            .start(step1())
            .next(myDecider)
            .from(myDecider).on("weekend").to(step2())
            .from(myDecider).on("workingDay").to(step3())
            .from(step3()).on("*").to(step4())
            .end()
            .build();
}

6. Nested jobs (JobStepBuilder)

@Bean
public Job parentJob() {
    return jobBuilderFactory.get("parentJob")
            .start(childJobOneStep())
            .next(childJobTwoStep())
            .build();
}

private Step childJobOneStep() {
    return new JobStepBuilder(new StepBuilder("childJobOneStep"))
            .job(childJobOne())
            .launcher(jobLauncher)
            .repository(jobRepository)
            .transactionManager(platformTransactionManager)
            .build();
}

private Job childJobOne() {
    return jobBuilderFactory.get("childJobOne")
            .start(stepBuilderFactory.get("childJobOneStep")
                    .tasklet((c, ctx) -> { System.out.println("子任务一执行步骤。。。"); return RepeatStatus.FINISHED; })
                    .build())
            .build();
}

7. Reading data (FlatFileItemReader example)

private ItemReader<TestData> fileItemReader() {
    FlatFileItemReader<TestData> reader = new FlatFileItemReader<>();
    reader.setResource(new ClassPathResource("reader/file"));
    reader.setLinesToSkip(1);
    DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
    tokenizer.setNames("id", "field1", "field2", "field3");
    DefaultLineMapper<TestData> mapper = new DefaultLineMapper<>();
    mapper.setLineTokenizer(tokenizer);
    mapper.setFieldSetMapper(fieldSet -> {
        TestData data = new TestData();
        data.setId(fieldSet.readInt("id"));
        data.setField1(fieldSet.readString("field1"));
        data.setField2(fieldSet.readString("field2"));
        data.setField3(fieldSet.readString("field3"));
        return data;
    });
    reader.setLineMapper(mapper);
    return reader;
}

8. Writing data (FlatFileItemWriter with JSON output)

private FlatFileItemWriter<TestData> fileItemWriter() throws Exception {
    FlatFileItemWriter<TestData> writer = new FlatFileItemWriter<>();
    FileSystemResource file = new FileSystemResource("D:/code/spring-batch-demo/src/main/resources/writer/writer-file");
    if (!Files.exists(Paths.get(file.getPath()))) {
        Files.createFile(Paths.get(file.getPath()));
    }
    writer.setResource(file);
    writer.setLineAggregator(item -> {
        try {
            return new ObjectMapper().writeValueAsString(item);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return "";
        }
    });
    writer.afterPropertiesSet();
    return writer;
}

9. Validation processor example

private BeanValidatingItemProcessor<TestData> beanValidatingItemProcessor() throws Exception {
    BeanValidatingItemProcessor<TestData> processor = new BeanValidatingItemProcessor<>();
    processor.afterPropertiesSet();
    return processor;
}

10. Scheduling the job via a REST controller

@RestController
@RequestMapping("job")
public class JobController {
    @Autowired private Job job;
    @Autowired private JobLauncher jobLauncher;

    @GetMapping("launcher/{message}")
    public String launch(@PathVariable String message) throws Exception {
        JobParameters params = new JobParametersBuilder()
                .addString("message", message)
                .toJobParameters();
        jobLauncher.run(job, params);
        return "success";
    }
}

Overall, the article walks through the complete lifecycle of a Spring Batch application—from conceptual overview and supported scenarios to concrete code examples for job configuration, step composition, parallel execution, decision making, nested jobs, data I/O, validation, and external scheduling—providing a practical reference for backend developers building robust batch solutions.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

javabackend-developmentSpring BootJob SchedulingSpring Batch
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.