Reputation: 1051
I am new to Spring and Spring Batch. I wrote a basic job that's supposed to repeat every 5 seconds. It has two steps, the first of which (step1
) is supposed to fail every time. My aim was to see if the job would report these errors in step1
and continue to step2
. The approach I am using to catch errors in step1
is below (using listener
s). I would like some critique on how right/wrong my approach is.
This is my job configuration. It has one job which has two steps:
@Configuration
public class JobConfig {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Autowired
private JobLauncher jobLauncher;
@Autowired
private JobRepository jobRepository;
@Autowired
private StepExecutionListenerImpl stepExecutionListener;
@Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.listener(this.stepExecutionListener)
.tasklet(new Tasklet() throws Exception {
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
throw new Exception("Step1 caused an exception");
return RepeatStatus.FINISHED;
}
})
.build();
}
@Bean
public Step step2() {
return stepBuilderFactory.get("step2")
.tasklet(new Tasklet() {
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws InterruptedException {
System.out.println("Step2 is executing");
return RepeatStatus.FINISHED;
}
})
.build();
}
@Bean
public Job job() throws Exception {
return jobBuilderFactory.get("job")
.incrementer(new RunIdIncrementer())
.start(step1())
.on("COMPLETED").to(step2()).end()
.build();
}
@Scheduled(cron = "*/5 * * * * *")
public void runJob() throws Exception {
System.out.println("Job Started at :" + new Date());
JobParameters param = new JobParametersBuilder().addString("JobID", String.valueOf(System.currentTimeMillis()))
.toJobParameters();
JobExecution execution = jobLauncher.run(job(), param);
System.out.println("Job finished with status :" + execution.getStatus());
}
@Bean
public JobLauncher getJobLauncher() {
SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
simpleJobLauncher.setJobRepository(this.jobRepository);
return simpleJobLauncher;
}
}
To cause an error in step1
, I threw an exception in that step. I also added a listener
in step1
whose afterStep()
method checks if any exceptions have occurred in that step, and if so, returns ExitStatus.FAILED
. If no exceptions occur, it returns ExitStatus.COMPLETED
. Below is the code for that:
@Component
public class StepExecutionListenerImpl implements StepExecutionListener {
@Override
public void beforeStep(StepExecution stepExecution) {
System.out.println("Before starting step");
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
List<Throwable> exceptions = stepExecution.getFailureExceptions();
if(exceptions.isEmpty()) {
return ExitStatus.COMPLETED;
} else {
System.out.println("This step has encountered exceptions");
exceptions.forEach(th -> System.out.println("Exception has occurred in job"));
return ExitStatus.FAILED;
}
}
}
This seems to be working, since step1
fails on each iteration of the job, and then a new iteration begins. So my question is, is this a good way of catching errors in Spring Batch jobs? Am I using listeners correctly?
Upvotes: 0
Views: 9625
Reputation: 2239
We have implemented ItemReadListener
,ItemProcessListener
,ItemWriteListener
interfaces which contains methods like onReadError
,onProcessError
,onWriteError
. These methods are invoked if there is any exception during the process of reading/processing/writing the records.
Upvotes: 1