Currently if a Spring Batch Job's ExitStatus.ExitCode is FAILED the Boot application ends with a 0 exit code. However we have had several requests from users that would like for the application to return a non zero exit code if the ExitStatus.ExitCode of a Spring Batch Job returns a FAILED.
This feature should be configurable where the default behavior should remain as is, but a user can configure it such that Boot app returns a non zero exit code if ExitStatus.ExitCode is FAILED.
@cppwfs I'd like to take a look at this. From some quick looking around in the code, I think the solution should be something similar to org.springframework.boot.autoconfigure.batch.JobExecutionExitCodeGenerator, but with the configurable property as result code instead of using the ordinal of the BatchStatus, correct?
@cppwfs: 'getExitCode' is defined as abstract method in the functional interface ExitCodeGenerator and updating getExitCode type would change the default behaviour. We can add a new method in /batch/JobExecutionExitCodeGenerator such as String getExitCodeStatus with option to autoconfigure return code? I can submit a PR. if this seems fine?
Hi @philwebb Can you please guide me on this, would like to wok if no one else is working on this. Thanks.
@nishantraut I'm afraid I'm not that familiar with the internals of Spring Batch so I'm not too sure what's involved here. Probably something changes are required to JobExecutionExitCodeGenerator but I don't know exactly how the Spring Batch ExitStatus is obtained. Perhaps @mminella has some advice?
PR submitted for this issue: https://github.com/spring-projects/spring-boot/pull/15066
Also requested review from @mminella @benas
Currently if a Spring Batch Job's ExitStatus.ExitCode is FAILED the Boot application ends with a 0 exit code.
This is probably because the app is executed with:
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
rather than:
public static void main(String[] args) {
System.exit(
SpringApplication.exit(
SpringApplication.run(DemoApplication.class, args)
)
);
}
as mentioned in the batch sample. If run like in the boot batch sample, a failed Spring Batch app should by default return 5 (which is the ordinal of FAILED in the BatchStatus enum) and not 0. Here is a quick sample:
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@EnableBatchProcessing
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
System.exit(
SpringApplication.exit(
SpringApplication.run(DemoApplication.class, args)
)
);
}
@Bean
public Job job(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory) {
Step step = stepBuilderFactory.get("step")
.tasklet((contribution, chunkContext) -> {
throw new Exception("Boom");
}).build();
return jobBuilderFactory.get("job")
.start(step)
.build();
}
}
However we have had several requests from users that would like for the application to return a non zero exit code if the ExitStatus.ExitCode of a Spring Batch Job returns a FAILED.
I think there is no need for a new feature in boot to achieve this. Boot already emits a JobExecutionEvent with the JobExecution, so adding a custom ExitCodeGenerator as a listener to this type of event is enough, something like:
@Bean
public ExitCodeGenerator exitCodeGenerator () {
return new MyExitCodeGenerator();
}
class MyExitCodeGenerator implements ExitCodeGenerator, ApplicationListener<JobExecutionEvent> {
private JobExecution jobExecution;
@Override
public int getExitCode() {
ExitStatus exitStatus = jobExecution.getExitStatus();
if (ExitStatus.FAILED.getExitCode().equals(exitStatus.getExitCode())) {
return 42;
}
return 0;
}
@Override
public void onApplicationEvent(JobExecutionEvent jobExecutionEvent) {
this.jobExecution = jobExecutionEvent.getJobExecution();
}
}
adding this bean to the previous example makes it return 42 when the job fails.
Thanks @benas. Looking at your sample and the original description, it is not crystal clear what should be done here. I am taking off the "ideal-for-contribution" until the scope is clarified (at least for me).
@benas sounds good. This is something the user can register so no need for a new feature in which case this issue and PR can be closed.
@snicoll There is actually nothing to do, boot already provides a way to generate a custom exit code through the ExitCodeGenerator. If the user wants to generate a custom exit code, he/she has to register a custom ExitCodeGenerator as shown in the example above. So for me, the ExitCodeGenerator API is the feature requested here.
Sorry for the delay on chiming in on this issue. I held off because this functionality already exists in Spring Cloud Task but was broken. I merged the PR that contained the fixes yesterday. You can see what we have here https://github.com/spring-cloud/spring-cloud-task/blob/master/spring-cloud-task-batch/src/main/java/org/springframework/cloud/task/batch/handler/TaskJobLauncherCommandLineRunner.java. This issue was originally opened to donate that code here.
Thanks all, let's close this one then.
This issue was originally opened to donate that code here.
Sorry @mminella I missed that part. Can you please submit a PR with that code and I am more than happy to review it.
Most helpful comment
This is probably because the app is executed with:
rather than:
as mentioned in the batch sample. If run like in the boot batch sample, a failed Spring Batch app should by default return 5 (which is the ordinal of
FAILEDin theBatchStatusenum) and not 0. Here is a quick sample:I think there is no need for a new feature in boot to achieve this. Boot already emits a
JobExecutionEventwith theJobExecution, so adding a customExitCodeGeneratoras a listener to this type of event is enough, something like:adding this bean to the previous example makes it return 42 when the job fails.