Step‑by‑Step Spring Batch Hello World Job with Spring Boot

This tutorial walks you through building a simple Spring Batch Hello World job using Spring Boot and Maven, covering the framework basics, project setup, Maven configuration, entity modeling, job and step configuration, data processing, testing, and how to run the example to generate greeting output.

Programmer DD
Programmer DD
Programmer DD
Step‑by‑Step Spring Batch Hello World Job with Spring Boot

1. Spring Batch Framework Overview

Spring Batch processes large volumes of data in a batch job. A Job consists of one or more Step objects, each typically reading data with an ItemReader, transforming it with an ItemProcessor, and writing it with an ItemWriter. The JobLauncher starts a job, while the JobRepository stores job metadata.

2. Example Overview

The example uses Spring Batch 4.1, Spring Boot 2.1, and Maven 3.6. The project follows a standard Maven layout.

3. Maven Configuration

The Maven pom.xml includes the Spring Boot parent, the spring-boot-starter-batch and spring-boot-starter-test dependencies, as well as spring-batch-test for testing. The spring-boot-maven-plugin builds an executable uber‑jar.

<project xmlns="http://maven.apache.org/POM/4.0.0">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.codenotfound</groupId>
  <artifactId>spring-batch-hello-world</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.5.RELEASE</version>
  </parent>
  <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>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

4. Spring Boot Configuration

Create a SpringBatchApplication class annotated with @SpringBootApplication and exclude DataSourceAutoConfiguration so that Spring Batch uses an in‑memory job repository.

package com.codenotfound;

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

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class SpringBatchApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBatchApplication.class, args);
    }
}
Note: @SpringBootApplication combines @Configuration , @EnableAutoConfiguration and @ComponentScan .

5. Entity Model

The input CSV rows are mapped to a simple POJO named Person with firstName and lastName fields.

package com.codenotfound.model;

public class Person {
    private String firstName;
    private String lastName;

    public Person() {}

    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }
    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }

    @Override
    public String toString() {
        return firstName + " " + lastName;
    }
}

6. Spring Batch Job Configuration

First, a BatchConfig class extends DefaultBatchConfigurer and overrides setDataSource to keep the default map‑based JobRepository.

package com.codenotfound.batch;

import javax.sql.DataSource;
import org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableBatchProcessing
public class BatchConfig extends DefaultBatchConfigurer {
    @Override
    public void setDataSource(DataSource dataSource) {
        // use map‑based JobRepository (no DB)
    }
}

Next, HelloWorldJobConfig defines the Job and Step beans, a FlatFileItemReader for the CSV, a PersonItemProcessor, and a FlatFileItemWriter that writes greetings to greeting.txt.

package com.codenotfound.batch;

import com.codenotfound.model.Person;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.builder.FlatFileItemWriterBuilder;
import org.springframework.batch.item.file.transform.PassThroughLineAggregator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;

@Configuration
public class HelloWorldJobConfig {
    @Bean
    public Job helloWorldJob(JobBuilderFactory jobBuilders, StepBuilderFactory stepBuilders) {
        return jobBuilders.get("helloWorldJob")
                .start(helloWorldStep(stepBuilders))
                .build();
    }

    @Bean
    public Step helloWorldStep(StepBuilderFactory stepBuilders) {
        return stepBuilders.get("helloWorldStep")
                .<Person, String>chunk(10)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .build();
    }

    @Bean
    public FlatFileItemReader<Person> reader() {
        return new FlatFileItemReaderBuilder<Person>()
                .name("personItemReader")
                .resource(new ClassPathResource("csv/persons.csv"))
                .delimited()
                .names("firstName", "lastName")
                .targetType(Person.class)
                .build();
    }

    @Bean
    public PersonItemProcessor processor() {
        return new PersonItemProcessor();
    }

    @Bean
    public FlatFileItemWriter<String> writer() {
        return new FlatFileItemWriterBuilder<String>()
                .name("greetingItemWriter")
                .resource(new FileSystemResource("target/test-outputs/greetings.txt"))
                .lineAggregator(new PassThroughLineAggregator<>())
                .build();
    }
}

7. Data Processing

The PersonItemProcessor implements ItemProcessor<Person, String> and converts a Person into a greeting string.

package com.codenotfound.batch;

import com.codenotfound.model.Person;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.ItemProcessor;

public class PersonItemProcessor implements ItemProcessor<Person, String> {
    private static final Logger LOGGER = LoggerFactory.getLogger(PersonItemProcessor.class);

    @Override
    public String process(Person person) throws Exception {
        String greeting = "Hello " + person.getFirstName() + " " + person.getLastName() + "!";
        LOGGER.info("converting '{}' into '{}'", person, greeting);
        return greeting;
    }
}

8. Testing the Batch Job

A Spring Boot test uses JobLauncherTestUtils to launch the job and asserts that the exit status is COMPLETED.

package com.codenotfound;

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {SpringBatchApplicationTests.BatchTestConfig.class})
public class SpringBatchApplicationTests {
    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    @Test
    public void testHelloWorldJob() throws Exception {
        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        assertThat(jobExecution.getExitStatus().getExitCode()).isEqualTo("COMPLETED");
    }

    @Configuration
    @Import({BatchConfig.class, HelloWorldJobConfig.class})
    static class BatchTestConfig {
        @Autowired
        private Job helloWorldJob;

        @Bean
        public JobLauncherTestUtils jobLauncherTestUtils() {
            JobLauncherTestUtils utils = new JobLauncherTestUtils();
            utils.setJob(helloWorldJob);
            return utils;
        }
    }
}

9. Running the Example

Execute the test (or the job) with Maven: mvn test The job reads persons.csv, creates greetings, and writes them to target/test-outputs/greetings.txt. The resulting file contains:

Hello John Doe!
Hello Jane Doe!

For the full source code, visit the original tutorial page.

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.

Batch ProcessingSpring Batch
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.