Simple Spring Batch Job using Job, Step and Tasklet

Job – Big Picture, Step – building block, Tasklet – Worker

Component Role Typical Use Case
Job Orchestrates steps Full batch process
Step Executes a unit of work Reading, processing, writing
Tasklet Performs a single task Logging, cleanup, file ops

OrderSchedulerApplication.java

package com.mugil.org;

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

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

BatchConfig.java

package com.mugil.org.config;

import org.springframework.batch.core.*;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
public class BatchConfig {
    @Bean
    public Job job(JobRepository jobRepository, Step step) {
        return new JobBuilder("job", jobRepository)
                .start(step)
                .build();
    }

    @Bean
    public Step step(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        StepBuilder stepBuilderOne = new StepBuilder("step1", jobRepository);
        return stepBuilderOne.tasklet(helloWorldTasklet(), transactionManager)
                .build();
    }

    @Bean
    public Tasklet helloWorldTasklet() {
        return (StepContribution contribution, ChunkContext chunkContext) -> {
            System.out.println("Hello, World!");
            return RepeatStatus.FINISHED;
        };
    }
}

Output

2025-08-30T15:33:46.902+05:30  INFO 3620 --- [OrderScheduler] [           main] o.s.b.c.l.s.TaskExecutorJobLauncher      : Job: [SimpleJob: [name=job]] launched with the following parameters: [{}]
2025-08-30T15:33:46.909+05:30  INFO 3620 --- [OrderScheduler] [           main] o.s.batch.core.job.SimpleStepHandler     : Executing step: [step1]
Hello, World!
2025-08-30T15:33:46.914+05:30  INFO 3620 --- [OrderScheduler] [           main] o.s.batch.core.step.AbstractStep         : Step: [step1] executed in 3ms
2025-08-30T15:33:46.917+05:30  INFO 3620 --- [OrderScheduler] [           main] o.s.b.c.l.s.TaskExecutorJobLauncher      : Job: [SimpleJob: [name=job]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 9ms

Having separate Tasklet
HelloWorldTasklet.java

public class HelloWorldTasklet implements Tasklet {
    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        System.out.println("Hello, World!");
        return RepeatStatus.FINISHED;
    }
}

FAQ

  1. You cannot have multiple Tasklets however you can have multiple Steps

For the above job the following tables would be impacted.

  1. batch_job_instance(unique job entity which needs to run)
  2. batch_job_execution(Instance may have one execution if execution is success or more than one execution if failed)
  3. batch_step_execution(Job would have multiple steps)
  4. batch_job_execution_context(Context which is shared by among different steps in job)
SELECT BJI.job_name, BSE.step_name, BJE.start_time, BJE.end_time, BJE.status as job_staus, 
       BSE.status as step_staus,  BJE.exit_code, BJE.exit_message
  FROM public.batch_job_instance   BJI INNER JOIN 
       public.batch_job_execution  BJE ON BJE.job_instance_id = BJI.job_instance_id INNER JOIN 
       public.batch_step_execution BSE ON BJE.job_execution_id = BSE.job_execution_id	   
 WHERE BJE.job_execution_id=1;

Job Execution Context and Step Execution Context
Job Execution Context – Available throughout the entire job execution across various steps. Stores data that needs to be shared across multiple steps or retrieved after a job restart. it survives restarts and failures.

I.E.
If you download a file in Step 1 and need its path in Step 3, store the path in the Job Execution Context.

Step Execution Context – Limited to the specific step execution.Stores data relevant only to that step, such as reader/writer state or counters.
I.E.
A reader might store the last read line number here so it can resume from that point if the step fails. We can pass values between steps and jobs using ExecutionContextPromotionListener.