[spring-projects/spring-boot]作业失败的批处理应用程序应该能够返回非零退出代码

2024-04-17 971 views
4

目前,如果 Spring Batch 作业ExitStatus.ExitCode失败,启动应用程序将以 0 退出代码结束。但是,我们收到了来自用户的多个请求,希望应用程序在ExitStatus.ExitCodeSpring Batch 作业返回 FAILED 时返回非零退出代码。
此功能应该是可配置的,默认行为应保持原样,但用户可以对其进行配置,以便启动应用程序在ExitStatus.ExitCode失败时返回非零退出代码。

回答

4

@cppwfs 我想看看这个。通过快速浏览代码,我认为解决方案应该类似于org.springframework.boot.autoconfigure.batch.JobExecutionExitCodeGenerator,但使用可配置属性作为结果代码,而不是使用 的序数BatchStatus,对吗?

8

@cppwfs:“getExitCode”在功能接口中定义为抽象方法ExitCodeGenerator,更新getExitCode类型将更改默认行为。我们可以在 /batch/JobExecutionExitCodeGenerator 中添加一个新方法,例如String getExitCodeStatus带有自动配置返回代码的选项?我可以提交 PR。如果这看起来不错?

1

嗨@philwebb,你能指导我吗?如果没有其他人在做这件事,我想工作。谢谢。

4

@nishantraut 恐怕我不太熟悉 Spring Batch 的内部结构,所以我不太确定这里涉及什么。可能需要进行一些更改,JobExecutionExitCodeGenerator但我不知道 Spring BatchExitStatus是如何获得的。也许@mminella 有一些建议?

8

这可能是因为该应用程序是通过以下方式执行的:

public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
}

而不是:

public static void main(String[] args) {
   System.exit(
      SpringApplication.exit(
         SpringApplication.run(DemoApplication.class, args)
      )
   );
}

批次样品中所述。如果像启动批处理示例一样运行,则失败的 Spring Batch 应用程序默认应返回 5(这是枚举中的序数)而不是 0。这是一个快速示例:FAILEDBatchStatus

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();
    }

}

但是,我们收到了多个用户请求,希望应用程序在 Spring Batch 作业的 ExitStatus.ExitCode 返回 FAILED 时返回非零退出代码。

我认为不需要在启动中添加新功能来实现这一点。 Boot 已经发出了JobExecutionEventJobExecution因此添加自定义ExitCodeGenerator作为此类事件的侦听器就足够了,例如:

@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();
    }
}

将此 bean 添加到前面的示例中,使其在作业失败时返回 42。

0

谢谢@benas。查看您的样本和原始描述,并不清楚这里应该做什么。我将取消“理想贡献”,直到范围明确为止(至少对我来说)。

3

@benas 听起来不错。这是用户可以注册的东西,因此不需要新功能,在这种情况下,可以关闭此问题和 PR。

9

@snicoll 实际上没什么可做的,boot 已经提供了一种通过ExitCodeGenerator.如果用户想要生成自定义退出代码,他/她必须注册一个自定义退出代码,ExitCodeGenerator如上例所示。所以对我来说,ExitCodeGeneratorAPI就是这里所要求的功能。

3

谢谢大家,那么我们就结束这个话题吧。

6

抱歉@mminella,我错过了那部分。您能否提交包含该代码的 PR,我非常乐意对其进行审核。

8

如果您在 SimpleJobLauncher 中配置了 SimplyAsyncTaskExecutor,则此操作不起作用。

@Override
protected JobLauncher createJobLauncher() throws Exception {
    SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher();
    simpleJobLauncher.setJobRepository(jobRepository);

    // To run 4 jobs parallelly.
    SimpleAsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor();
    taskExecutor.setConcurrencyLimit(4);
    simpleJobLauncher.setTaskExecutor(taskExecutor);
    simpleJobLauncher.afterPropertiesSet();

    return simpleJobLauncher;
}

关于如何实现从批处理作业返回非零状态代码的目标有什么想法吗?

5

@binbeast21 我们更喜欢仅使用 GitHub 问题来解决错误和增强功能,因此请在 Stack Overflow 或 Gitter 上提出此类问题。