Spring Batch is primarily executed by schedulers. It is typically run by schedulers like Jenkins, which determines whether a Jenkins job has failed or succeeded by reading the exit status of the application JVM.
However, the current code exits with a status of 0 even if the job fails, leading Jenkins to assume that the job completed successfully, which causes issues in operations.
Therefore, I believe there is a need to enhance the logic to transition the application's exit status according to the job's exit status.
The CommandLineJobRunner in Spring Batch illustrates these points well.
Please refer to the following link:
https://github.com/spring-projects/spring-batch/blob/main/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/CommandLineJobRunner.java
point 1
JobExecution jobExecution = launcher.run(job, jobParameters);
return exitCodeMapper.intValue(jobExecution.getExitStatus().getExitCode());
point 2
int result = command.start(jobPath, jobIdentifier, parameters, opts);
command.exit(result);
Lastly, please review the proposed changes.
Comment From: wilkinsona
@diqksrk Spring Boot has general support for exit codes that's intended to be used in situations like this. Please review the documentation and let us know if it meets your needs.
Comment From: diqksrk
@wilkinsona Thank you for your answer ! I am aware of the general support for exit codes. I think I may have conveyed my intention incorrectly.
What I intended to say is that the application exit status in Spring Batch is determined based on the job's status. This is important when using it with a scheduler like Jenkins because the success of a Jenkins job depends on the application exit status.
Therefore, as I have proposed in the PR, the application should throw an exception based on the job's status, so that the exit code is determined by the Spring context upon termination.
Here is the relevant code:
private void validateJobTerminateStatus() throws JobExecutionException {
String exitCode = jobExplorer.getLastJobExecution(jobExplorer.getLastJobInstance(this.jobName))
.getExitStatus().getExitCode();
if (exitCodeMapper.intValue(exitCode) != JVM_EXITCODE_COMPLETED) {
throw new JobExecutionException("Job Terminated with BatchStatus : " + exitCode);
}
}
Comment From: wilkinsona
As I've just described on the PR, this shouldn't be necessary. If you're using System.exit and SpringApplication.exit, a job execution failure should already result in a non-zero exit code thanks to JobExecutionExitCodeGenerator. If that's not working for you and you would like us to investigate, please provide a minimal sample that reproduces the problem and we'll investigate.
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: diqksrk
Thank you for your kind guidance. The issue has been resolved, so I will go ahead and close the issue.
Comment From: diqksrk
@wilkinsona I have something to mention.
This is something that could be overlooked, but since it's a framework I use, I felt I should mention it and ask a question.
In the BatchAutoConfiguration.class(https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java) of the spring-boot-autoconfigure:3.3.1 library, you can find the following statement:
@ConditionalOnMissingBean(value = DefaultBatchConfiguration.class, annotation = EnableBatchProcessing.class)
When you check the DefaultBatchConfiguration.class(https://github.com/spring-projects/spring-batch/blob/main/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultBatchConfiguration.java) , you can see the following statement:
@Configuration(proxyBeanMethods = false)
@Import(ScopeConfiguration.class)
public class DefaultBatchConfiguration implements ApplicationContextAware {
As far as I know, the @Configuration annotation registers the class as a bean. Therefore, it is always registered as a bean every time it runs.
Due to the DefaultBatchConfiguration.class always being registered by.. BatchAutoConfiguration.class, it cannot be executed.
Additionally, the tasks registered as beans are also omitted.
When looking at the Spring Boot manual, you can find the following statement: https://docs.spring.io/spring-boot/how-to/batch.html#howto.batch.running-jobs-on-startup
Running Spring Batch Jobs on Startup
Spring Batch auto-configuration is enabled by adding spring-boot-starter-batch to your application’s classpath.
If a single Job bean is found in the application context, it is executed on startup (see [JobLauncherApplicationRunner](https://docs.spring.io/spring-boot/api/java/org/springframework/boot/autoconfigure/batch/JobLauncherApplicationRunner.html) for details). If multiple Job beans are found, the job that should be executed must be specified using spring.batch.job.name.
To disable running a Job found in the application context, set the spring.batch.job.enabled to false.
See [BatchAutoConfiguration](https://github.com/spring-projects/spring-boot/tree/v3.3.2/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/batch/BatchAutoConfiguration.java) for more details.
It guides you with this statement, but you cannot actually use it.
I also had to register jobLauncherApplicationRunner.class and jobExecutionExitCodeGenerator.class as beans directly.
This makes it unavoidable to check the internal code. Is this the intended result? Or am I misunderstanding something? Thank you for always checking.
Comment From: wilkinsona
BatchAutoConfiguration will be used unless you've defined your own @Configuration class that sub-classes DefaultBatchConfiguration or you've used @EnableBatchProcessing.
If you have any further questions, please follow up on Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.