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

🐱 Tomcat vs ⚡ Netty – Which One Should You Use?

🐱 Tomcat vs ⚡ Netty – Which One Should You Use? So recently I got curious about this too πŸ€”. Everywhere in Spring Boot tutorials we see Tomcat . Then suddenly while exploring Spring WebFlux , the name Netty pops up. And I was like – “Wait, who’s this Netty guy trying to replace Tomcat?” πŸ˜… Let’s break it down with real-time examples , icons , and fun comparisons . 🐱 Tomcat – The Traditional Web Server Type: Servlet Container (blocking I/O) World: Used with Spring MVC Style: Thread-per-request model πŸ‘©‍πŸ’» Pros: Stable, widely used, battle-tested Cons: Struggles with huge concurrent connections πŸ‘‰ Example in real life: Tomcat is like a restaurant with fixed waiters 🍴. - Each customer = one thread/waiter - If too many customers come in at once → waiters run out → customers wait outside πŸšͺ ⚡ Netty – The Reactive Rockstar Type: Asynchronous Event-Driven Network Framework World: Default for Spring WebFlux Style: Event-lo...

🎭 Spring’s Secret: Why @Transactional & Friends Betray You Silently

πŸ’‘ Lesson Learned — Not a Prod Bug, But a Real Pain No, this wasn’t a production outage. Nobody screamed at me. But I sat for 3 hours wondering: “Why the heck is my @Transactional not rolling back!?” 😡‍πŸ’« “Why is Redis cache not working?” 🀯 Turned out, the issue was one silent villain: 🧱 Self-invocation 🀷 What Is @Transactional ? If you're new: @Transactional = Tells Spring to start a DB transaction when a method is called. It’ll commit if everything’s okay. It’ll rollback if something fails. 🧠 Think of it like wrapping your code in: try { beginTransaction(); // your logic commit(); } catch(Exception e) { rollback(); } πŸ•΅️ Real-Life Analogy — The Gateway Community 🏘️ Let me tell you about my society — it has a strict watchman at the gate. Here’s how it works: πŸ›‚ Watchman = Spring Proxy 🏠 Your apartment = Your service class πŸšͺ Your room = A method inside that class πŸƒ Scenario 1: Outsider Visits Your friend from outside...

🌟 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...