Stop and Fail Transitions - Spring Batch Part 7
Lets modify our throwException boolean to true and run application from our previous blog post
// Toggle true/false to test rerunning failed jobs
private boolean throwException = true;
In case of an exception thrown by the packageStep, we go to manualPackageStep and the workflow just stops there. But the steps to deliver/pickup have not been executed. If you try rerunning by setting the throwException = false, it wont run.
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
Also, if you check the Step status of packageStep in BATCH_STEP_EXECUTION table, it will show that the Step was ABANDONED and the status of the Job in BATCH_JOB_EXECUTION table, it will be COMPLETED.
But this is not what we want. We want to manually fix the packaging and then send it out either for delivery or for pickup.
The problem is that we are ending our condiotional block using end(), which Spring Batch considers a successful flow.
full code available at: https://github.com/ricsr/spring-batch-demo/tree/exercise_07
We can fix the problem using stop() method. So, in our case, if the packageStep fails, we want someone to manually fix the problem, right?
@Bean
public Job packageJob(){
return this.jobBuilderFactory.get("giftShopJob").start(readOrderStep())
.next(packageStep())
.on("FAILED").stop()
.from(packageStep())
.on("*").to(pickupOrDeliveryDecider())
.on("DELIVER").to(deliveryStep())
.from(pickupOrDeliveryDecider())
.on("PICKUP").to(pickupStep())
.end()
.build();
}
Now if you try rerunning the application, you see the following output:
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
2020-07-20 00:00:21.601 INFO 13740 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=giftShopJob]] launched with the following parameters: [{}]
2020-07-20 00:00:21.660 INFO 13740 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [readOrderStep]
Order Received
2020-07-20 00:00:21.683 INFO 13740 --- [ main] o.s.batch.core.step.AbstractStep : Step: [readOrderStep] executed in 22ms
2020-07-20 00:00:21.700 INFO 13740 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [packageStep]
2020-07-20 00:00:21.712 ERROR 13740 --- [ 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:61) ~[main/:na]
at ..........
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:108) ~[main/:na]
2020-07-20 00:00:21.714 INFO 13740 --- [ main] o.s.batch.core.step.AbstractStep : Step: [packageStep] executed in 14ms
2020-07-20 00:00:21.724 INFO 13740 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=giftShopJob]] completed with the following parameters: [{}] and the following status: [STOPPED] in 85ms
2020-07-20 00:00:21.728 INFO 13740 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2020-07-20 00:00:21.742 INFO 13740 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
BUILD SUCCESSFUL in 4s
If you look at the output of BATCH_JOB_EXECUTION , you see that the status of the job is STOPPED.
Let us now manually fix the error. I mean set throwException = false; and rerun
2020-07-20 00:04:23.034 INFO 16244 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=giftShopJob]] launched with the following parameters: [{}]
2020-07-20 00:04:23.077 INFO 16244 --- [ main] o.s.batch.core.job.SimpleStepHandler : Step already complete or not restartable, so no action to execute: StepExecution: id=63, 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-20 00:04:23.090 INFO 16244 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [packageStep]
Packaging the gift
2020-07-20 00:04:23.110 INFO 16244 --- [ main] o.s.batch.core.step.AbstractStep : Step: [packageStep] executed in 20ms
Customer choose: DELIVER
2020-07-20 00:04:23.126 INFO 16244 --- [ main] o.s.batch.core.job.SimpleStepHandler : Executing step: [deliveryStep]
Package out for delivery
2020-07-20 00:04:23.134 INFO 16244 --- [ main] o.s.batch.core.step.AbstractStep : Step: [deliveryStep] executed in 8ms
2020-07-20 00:04:23.140 INFO 16244 --- [ main] o.s.b.c.l.support.SimpleJobLauncher : Job: [FlowJob: [name=giftShopJob]] completed with the following parameters: [{}] and the following status: [COMPLETED] in 77ms
2020-07-20 00:04:23.144 INFO 16244 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2020-07-20 00:04:23.153 INFO 16244 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
As you can see, the job continued from the packageStep and COMPLETED this time.
Lets also take a look at the BATCH_JOB_EXECUTION table:
Also, I suggest you to take a look at BATCH_STEP_EXECUTION table:
You can also FAIL a Job.
@Bean
public Job packageJob(){
return this.jobBuilderFactory.get("giftShopJob").start(readOrderStep())
.next(packageStep())
.on("FAILED").fail()
.from(packageStep())
.on("*").to(pickupOrDeliveryDecider())
.on("DELIVER").to(deliveryStep())
.from(pickupOrDeliveryDecider())
.on("PICKUP").to(pickupStep())
.end()
.build();
}
Both STOP and FAIL allows us to rerun the application. We should not, in any case, set up a job which transitions to a state where we are unable to rerun it if it fails. We should be able to revive from a failed job.
full code available at: https://github.com/ricsr/spring-batch-demo/tree/exercise_07
Comments