Rerunning Failed Jobs - Spring Batch Part 5
If the Spring Job fails, Spring Batch Job uses Job Repository to know where the Job Failed, and restarts from that step.
Lets see an example on how it is done:
entire code can be found at git repo: https://github.com/ricsr/spring-batch-demo/tree/exercise_05
Note: I have dropped the Spring Job Repository tables just to able to rerun the application just to make it easy to rerun the Job
DROP TABLE BATCH_STEP_EXECUTION_CONTEXT ;
DROP TABLE BATCH_STEP_EXECUTION ;
DROP TABLE BATCH_JOB_INSTANCE ;
DROP TABLE BATCH_JOB_EXECUTION_PARAMS ;
DROP TABLE BATCH_JOB_EXECUTION_CONTEXT ;
DROP TABLE BATCH_JOB_EXECUTION ;
// Toggle true/false to test rerunning failed jobs
private boolean throwException = true;
@Bean
public Step packageStep() {
return this.stepBuilderFactory.get("packageStep").tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
if(throwException){
throw new RuntimeException("Exception while Packaging");
}
System.out.println("Packaging the gift with " + giftWrapper);
return RepeatStatus.FINISHED;
}
}).build();
}
Running the application by setting throwException=true.
Here is the output after running the application:
2020-07-19 14:59:10.211 INFO 6944 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=giftShopJob]] launched with the following parameters: [{giftWrapper=Golden Box}]
2020-07-19 14:59:10.383 INFO 6944 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [readOrderStep]
Order Received
2020-07-19 14:59:10.419 INFO 6944 --- [ main] o.s.batch.core.step.AbstractStep : Step: [readOrderStep] executed in 36ms
2020-07-19 14:59:10.439 INFO 6944 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [packageStep]
2020-07-19 14:59:10.451 ERROR 6944 --- [ main] o.s.batch.core.step.AbstractStep : Encountered an error executing step packageStep in job giftShopJob
java.lang.RuntimeException: Exception while Packaging
at com.ricsr.springbootdemo.SpringbootdemoApplication$2.execute(SpringbootdemoApplication.java:53) ~[main/:na]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:407) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:331) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.2.7.RELEASE.jar:5.2.7.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:273) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE]
......
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.1.RELEASE.jar:2.3.1.RELEASE]
at com.ricsr.springbootdemo.SpringbootdemoApplication.main(SpringbootdemoApplication.java:73) ~[main/:na]
2020-07-19 14:59:10.455 INFO 6944 --- [ main] o.s.batch.core.step.AbstractStep : Step: [packageStep] executed in 16ms
2020-07-19 14:59:10.463 INFO 6944 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=giftShopJob]] completed with the following parameters: [{giftWrapper=Golden Box}] and the following status: [FAILED] in 152ms
2020-07-19 14:59:10.467 INFO 6944 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2020-07-19 14:59:10.483 INFO 6944 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
BUILD SUCCESSFUL in 6s
3 actionable tasks: 2 executed, 1 up-to-date
2:59:10 PM: Task execution finished 'SpringbootdemoApplication.main()'.
So, there was an exception, as expected, while running the packageStep and the deliveryStep was not executed. But the orderStep was executed.
Now, lets look at the tables:
BATCH_JOB_EXECUTION table tells us that the job has failed and the exception we got while running the Job.
While the BATCH_STEP_EXECUTION has information of the Steps of the Job which have executed either successfully or have failed:
Let us try rerunning the job by toggling our throwException flag to false.
2020-07-19 15:22:35.081 INFO 1520 --- [ main] c.r.s.SpringbootdemoApplication : Started SpringbootdemoApplication in 1.497 seconds (JVM running for 1.801)
2020-07-19 15:22:35.085 INFO 1520 --- [ main] o.s.b.a.b.JobLauncherApplicationRunner : Running default command line with: []
2020-07-19 15:22:35.975 INFO 1520 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=giftShopJob]] launched with the following parameters: [{}]
2020-07-19 15:22:36.003 INFO 1520 --- [ main] o.s.batch.core.job.SimpleStepHandler : Step already complete or not restartable, so no action to execute: StepExecution: id=37, version=3, name=readOrderStep, status=COMPLETED, exitStatus=COMPLETED, readCount=0, filterCount=0, writeCount=0 readSkipCount=0, writeSkipCount=0, processSkipCount=0, commitCount=1, rollbackCount=0, exitDescription=
2020-07-19 15:22:36.015 INFO 1520 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [packageStep]
Packaging the gift
2020-07-19 15:22:36.031 INFO 1520 --- [ main] o.s.batch.core.step.AbstractStep : Step: [packageStep] executed in 16ms
2020-07-19 15:22:36.043 INFO 1520 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [deliveryStep]
Package out for delivery
2020-07-19 15:22:36.051 INFO 1520 --- [ main] o.s.batch.core.step.AbstractStep : Step: [deliveryStep] executed in 8ms
2020-07-19 15:22:36.055 INFO 1520 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [SimpleJob: [name=giftShopJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 64ms
2020-07-19 15:22:36.059 INFO 1520 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2020-07-19 15:22:36.067 INFO 1520 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
BUILD SUCCESSFUL in 4s
As you can see from the output, our orderStep was not executed. But the Job started from where it failed: it rerun the packageJob and then the deliveryJob.
Lets look at the tables:
BATCH_JOB_EXECUTION has an entry for the successfully run job.
And so does the BATCH_STEP_EXECUTION
This is a very useful feature of Spring Batch as you dont have to worry about rerunning already run Steps OR unable to rerun the failed Steps of a Job.
entire code can be found at git repo: https://github.com/ricsr/spring-batch-demo/tree/exercise_05
Comments