I am writing a batch application in which I would like to set the exit status immediately when ever my application logic identify an issue and return.
For example I am setting the below status in my writer's write method.
stepExecution.getJobExecution().setExitStatus(ExitStatus.FAILED);
eventhough the above statment is executed, am getting below message in logs and the exit code is seems to be success.
"Batch Execution Successful!"
May I know how can I set the exit code properly?
There are some ways to set after step.
Like:
@AfterStep
public ExitStatus afterStep(){
//Test condition
return new ExistStatus("CUSTOM EXIT STATUS");
}
But I don't want to persist the exit stauts and set the exit status in the above method.
You should properly intercept job execution-
public void afterJob(JobExecution jobExecution){
if( jobExecution.getStatus() == BatchStatus.COMPLETED ){
jobExecution.setExitStatus(new ExitStatus("CUSTOM SUCCESS STATUS"));
} else if(jobExecution.getStatus() == BatchStatus.FAILED){
jobExecution.setExitStatus(new ExitStatus("CUSTOM FAILURE STATUS"));
}
}
I had a similar issue and just solved it 5 minutes ago.
I have multiple steps doing 'stuff' and a default "failure step" that is called when all other steps throw an exception.
The steps that throw an exception will be Abandoned in 'spring-batch' logic, but I need them to be Failed so that I can restart them.
So, after trying with listeners and forcing statuses, I finally got it to work by updating the abandoned step(s) after the 'failure step' is called.
So my 'failure-step' will look like this :
public class EnleveDossiersRejetesEtMAJSteps implements Tasklet {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
/**some business logic code for my step, AND the code bellow*/
if (chunkContext.getStepContext() != null && chunkContext.getStepContext().getStepExecution() != null) {
Long jobExecutionId = chunkContext.getStepContext().getStepExecution().getJobExecutionId();
batchTablesService.updateJobStepStatuses(jobExecutionId, BatchStatus.ABANDONED, BatchStatus.FAILED);
}
/** end the step like expected */
return RepeatStatus.FINISHED;
}
}
My 'batchTablesService' is a Service class that I created, which links to a DAO that simply retrieves all steps, then for all 'Abandoned' steps, it updates them to 'Failed'.
Like so :
@Override
public void updateJobStepStatuses(Long jobExecutionId, BatchStatus sInitial, BatchStatus sFinal) {
log.debug("-- call updateJobStepStatuses(" + jobExecutionId + "," + sInitial + "," + sFinal + ")");
List<BatchStepExecution> steps = getStepExecutions((int) (long) jobExecutionId, null);
for (BatchStepExecution step : steps) {
if (!step.getStatus().isEmpty() && step.getStatus().equalsIgnoreCase(sInitial.toString())) {
step.setStatus(sFinal.toString());
entityManager.merge(step);
}
}
}
Good luck!
No custom interfaces or classes are required. Take a look at this -
https://github.com/spring-projects/spring-boot/issues/14075