Skip to main content

πŸš€ Spring Batch – Beginner’s Guide with Real-Time Example

πŸš€ Spring Batch – Beginner’s Guide with Real-Time Example

Ever wondered how large amounts of data are processed in batches, like a boss? 😎

Welcome to Spring Batch – your friend when you need reliable, fast, and scalable batch processing in Java!

1️⃣ What is Spring Batch? πŸ€”

  • A framework to process large volumes of data efficiently.
  • Handles batch jobs, transactions, retries, skip logic, and chunk-based processing.
  • Perfect for ETL jobs, report generation, invoice processing – basically, anything your database hates if you run it all at once πŸ˜‚.

2️⃣ Important Concepts & Flow πŸ”„

Core Components:

  • Job – The whole batch process (like a movie 🎬).
  • Step – A phase of a job (like a scene in that movie).
  • ItemReader – Reads data from source (DB, CSV, API…think Sherlock reading clues πŸ•΅️‍♂️).
  • ItemProcessor – Processes/validates data (Sherlock deduces πŸ”).
  • ItemWriter – Writes data to destination (He reports findings ✉️).

Flow:



Controller/Scheduler ➡ JobLauncher ➡ Job ➡ Step ➡ Reader ➡ Processor ➡ Writer ➡ Job Complete πŸŽ‰

3️⃣ Key Annotations & Configurations ⚙️

Annotation What it does Funny Analogy
@EnableBatchProcessing Boots up Spring Batch Like turning on the engine πŸš—
@Configuration Defines beans and jobs Architect drawing blueprints πŸ—️
@Bean Declares a component “Hey Spring, manage this for me!” 🏷️
@JobScope / @StepScope Scope for job or step beans Beans with VIP access 🎫
@Component Marks a regular Spring component Ordinary citizen πŸ§‘‍πŸ’Ό

Dependencies:



<!-- Maven -->

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-batch</artifactId>

</dependency>

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

4️⃣ Real-Time Example πŸ’Ό

Scenario: Daily employee salary update from CSV to DB.

  1. Controller or Scheduler triggers Job
  2. JobLauncher launches Job
  3. Step reads CSV (ItemReader)
  4. Step processes salary (ItemProcessor)
  5. Step writes to DB (ItemWriter)
  6. Job finishes successfully or fails with retry logic

5️⃣ Flow Diagram Representation πŸ“Š



  +-------------+       +------------+       +------------+       +-----------+

  | Controller /|       | JobLauncher|       | Job        |       | Step      |

  | Scheduler   | --->  | ---------->| --->  | ---------->| --->  | ---------->|

  +-------------+       +------------+       +------------+       +-----------+

                                                              |           |

                                                              v           v

                                                      +---------+   +---------+

                                                      | Reader  |   | Writer  |

                                                      +---------+   +---------+

                                                            |

                                                            v

                                                      +-----------+

                                                      | Processor |

                                                      +-----------+

                                                            |

                                                            v

                                                      Job Completed πŸŽ‰

6️⃣ Example Program – CSV to Database Batch Job πŸ’»

Scenario: Daily employee salary update from CSV to DB.



// 1️⃣ Entity

@Entity

public class Employee {

    @Id

    private Long id;

    private String name;

    private Double salary;

    // getters & setters

}

// 2️⃣ Batch Configuration

@Configuration

@EnableBatchProcessing

public class BatchConfig {

    @Autowired

    private JobBuilderFactory jobBuilderFactory;

    @Autowired

    private StepBuilderFactory stepBuilderFactory;

    @Autowired

    private DataSource dataSource;

    // Reader - read CSV

    @Bean

    @StepScope

    public FlatFileItemReader reader(@Value("#{jobParameters['filePath']}") String path) {

        return new FlatFileItemReaderBuilder()

                .name("employeeReader")

                .resource(new FileSystemResource(path))

                .delimited()

                .names("id", "name", "salary")

                .targetType(Employee.class)

                .build();

    }

    // Processor - validate salary

    @Bean

    public ItemProcessor processor() {

        return emp -> {

            if(emp.getSalary() < 0) throw new IllegalArgumentException("Salary cannot be negative!");

            return emp;

        };

    }

    // Writer - save to DB

    @Bean

    public JdbcBatchItemWriter writer() {

        return new JdbcBatchItemWriterBuilder()

                .dataSource(dataSource)

                .sql("INSERT INTO employee (id, name, salary) VALUES (:id, :name, :salary)")

                .beanMapped()

                .build();

    }

    // Step

    @Bean

    public Step step1() {

        return stepBuilderFactory.get("step1")

                .chunk(5)

                .reader(reader(null))

                .processor(processor())

                .writer(writer())

                .build();

    }

    // Job

    @Bean

    public Job importEmployeeJob(JobCompletionNotificationListener listener) {

        return jobBuilderFactory.get("importEmployeeJob")

                .listener(listener)

                .flow(step1())

                .end()

                .build();

    }

}

// 3️⃣ Job Launcher from Controller

@RestController

public class JobLauncherController {

    @Autowired

    private JobLauncher jobLauncher;

    @Autowired

    private Job importEmployeeJob;

    @GetMapping("/launchjob")

    public String launchJob() throws Exception {

        JobParameters params = new JobParametersBuilder()

                .addString("filePath", "/path/to/employee.csv")

                .addLong("time", System.currentTimeMillis())

                .toJobParameters();

        jobLauncher.run(importEmployeeJob, params);

        return "Batch Job has been invoked";

    }

}

✅ What happens:

  • Visit http://localhost:8080/launchjob and your batch job triggers.
  • CSV data is read, validated, and written to DB in chunks.
  • Spring Batch manages transactions, retries, and job metadata automatically.

7️⃣ Extra Fun Facts & Tips πŸ€“

  • Spring Batch automatically manages transaction, chunk, retry, and skip logic.
  • You can restart failed jobs without re-processing completed data.
  • Jobs can be triggered via Scheduler, Cron, or API endpoint.

8️⃣ Wrapping Up 🎁

Spring Batch might look complex initially, but it’s like a conveyor belt for your data – you just need to set up the machinery and let it run! 🏭

πŸ’‘ Tip: Always use chunk-based processing for large files, otherwise your JVM might cry 😭.

References / Learn More:

Comments

Popular posts from this blog

πŸ” Is final Really Final in Java? The Truth May Surprise You 😲

πŸ’¬ “When I was exploring what to do and what not to do in Java, one small keyword caught my eye — final . I thought it meant: locked, sealed, frozen — like my fridge when I forget to defrost it.”   But guess what? Java has its own meaning of final… and it’s not always what you expect! πŸ˜… Let’s break it down together — with code, questions, confusion, jokes, and everything in between. 🎯 The Confusing Case: You Said It's Final... Then It Changed?! 🫠 final List<String> names = new ArrayList <>(); names.add( "Anand" ); names.add( "Rahul" ); System.out.println(names); // [Anand, Rahul] 🀯 Hold on... that’s final , right?! So how on earth is it still changing ? Time to dive deeper... 🧠 Why Is It Designed Like This? Here’s the key secret: In Java, final applies to the reference , not the object it points to . Let’s decode this like a spy mission πŸ•΅️‍♂️: Imagine This: final List<String> names = new ArrayList <>(); Be...

🌟 My Journey – From Zero to Senior Java Tech Lead 🌟

 There’s one thing I truly believe… If I can become a Java developer, then anyone in the world can. πŸ’― Sounds crazy? Let me take you back. πŸ•“ Back in 2015… I had zero coding knowledge . Not just that — I had no interest in coding either. But life has its own plans. In 2016, I got a chance to move to Bangalore and joined a Java course at a training center. That’s where it all started — Every day, every session made me feel like: "Ohhh! Even I can be a developer!" That course didn’t just teach Java — it gave me confidence . πŸ§ͺ Two Life-Changing Incidents 1️⃣ The Interview That Wasn't Planned Halfway through my course, I had to urgently travel to Chennai to donate blood to a family member. After that emotional rollercoaster, I found myself reflecting on my skills and the future. The next day, as I was preparing for my move to Bangalore to complete the remaining four months of my course, I randomly thought — "Let me test my skills... let me just see...

🎒 Java Loops: Fun, Fear, and ForEach() Fails

πŸŒ€ Oops, I Looped It Again! — The Ultimate Java Loop Guide You Won't Forget “I remember this question from one of my early interviews — I was just 2 years into Java and the interviewer asked, ‘Which loop do you prefer and why?’” At first, I thought, “Duh! for-each is cleaner.” But then he grilled me with cases where it fails. 😡 That led me to explore all loop types, their powers, and their pitfalls. Let’s deep-dive into every major Java loop with examples &  real-world guidance so you'll never forget again. πŸ” Loop Type #1: Classic For Loop — “The Old Reliable” ✅ When to Use: You need an index You want to iterate in reverse You want full control over loop mechanics ✅ Good Example: List<String> names = List.of("A", "B", "C"); for (int i = 0; i < names.size(); i++) { System.out.println(i + ": " + names.get(i)); } πŸ”₯ Reverse + Removal Example: List<String> item...