【问题标题】:Spring batch return custom process exit codeSpring批量返回自定义进程退出代码
【发布时间】:2018-06-19 14:46:11
【问题描述】:

我有一个包含多个作业的 jar,我想每次只执行一个作业并检索自定义退出代码。

例如,我有一个基本工作 (retrieveErrorsJob) 配置,其中一个步骤将读取输入 XML 文件并将数据写入特定数据库表中。

应用类

@SpringBootApplication
@EnableBatchProcessing
@Import(CoreCommonsAppComponent.class)
public class Application {

    private static final Logger logger = LoggerFactory.getLogger(Application.class);
    private ConfigurationConstants constants;

    @Autowired
    public Application(ConfigurationConstants constants) {
        this.constants = constants;
    }

    @EventListener(ApplicationStartedEvent.class)
    public void idApplication()
    {
        logger.info("================================================");
        logger.info(constants.APPLICATION_NAME() + "-v." + constants.APPLICATION_VERSION() + " started on " + constants.REMOTE_HOST());
        logger.info("------------------------------------------------");
    }

    public static void main(String... args) throws Exception{
        ApplicationContext context = SpringApplication.run(Application.class, args);
        logger.info("================================================");
        SpringApplication.exit(context);
    }
}

我可以从命令行中选择一项工作:

java -jar my-jar.jar --spring.batch.job.names=retrieveErrorsJob --input.xml.file=myfile.xml

Spring Batch 启动正确的作业。

问题是我需要 jar 来返回自定义进程退出整数,如 ExitCode.FAILED == 4 等。但我总是有一个零(如果 ExitCode = SUCCESS 或 FAILED)。

根据文档,我需要实现ExitCodeMapper 接口。

代码(未完成)

public class CustomExitCodeMapper implements ExitCodeMapper {

private static final int NORMAL_END_EXECUTION = 1;
private static final int NORMAL_END_WARNING = 2;
private static final int ABNORMAL_END_WARNING = 3;
private static final int ABNORMAL_END_ERROR = 4;

@Override
public int intValue(String exitCode) {

    System.out.println("EXIT CODE = " + exitCode);

    switch (exitCode)
    {
        case "FAILED":
            return ABNORMAL_END_WARNING;
        default:
            return NORMAL_END_EXECUTION;
    }
}

}

我找不到使用此自定义实现的方法。我可以将自定义实现设置为CommandLineJobRunner,但是如何使用这个类?

【问题讨论】:

    标签: java spring spring-boot jvm exit-code


    【解决方案1】:

    感谢@Mahendra,我有了一个想法 :)

    我按照@Mahendra 的建议创建了一个JobCompletionNotificationListener 类:

    @Component
    public class JobCompletionNotificationListener extends JobExecutionListenerSupport {
    
        private static final Logger logger = LoggerFactory.getLogger(JobCompletionNotificationListener.class);
    
        @Override
        public void afterJob(JobExecution jobExecution) {
    
            SingletonExitCode exitCode = SingletonExitCode.getInstance();
    
           if(jobExecution.getStatus() == BatchStatus.COMPLETED)
           {
               logger.info("Exit with code " + ExitCode.NORMAL_END_OF_EXECUTION);
               exitCode.setExitCode(ExitCode.NORMAL_END_OF_EXECUTION);
           }
           else {
               logger.info("Exit with code " + ExitCode.ABNORMAL_END_OF_EXECUTION_WARNING);
               exitCode.setExitCode(ExitCode.ABNORMAL_END_OF_EXECUTION_WARNING);
           }
        }
    }
    

    但我不会强制应用程序以 System.exit() 从此类中退出。我已经实现了一个像这样的简单单例:

    public class SingletonExitCode {
    
        public ExitCode exitCode = ExitCode.ABNORMAL_END_OF_EXECUTION_WARNING; // Default code 3
        private static SingletonExitCode instance = new SingletonExitCode();
    
        private SingletonExitCode() {}
    
        public static SingletonExitCode getInstance() {
            return instance;
        }
    
        public void setExitCode(ExitCode exitCode) {
            this.exitCode = exitCode;
        }
    }
    

    我在关闭 Spring 上下文后向我的单身人士询问 ExitCode

    @SpringBootApplication
    @EnableBatchProcessing
    @Import(CoreCommonsAppComponent.class)
    public class Application {
        // a lot of nice things
    
        public static void main(String... args) throws Exception{
            ApplicationContext context = SpringApplication.run(Application.class, args);
            logger.info("================================================");
            SpringApplication.exit(context);
            System.exit(SingletonExitCode.getInstance().exitCode.getCode());
        }
    }
    

    我这样做是因为如果我们直接从 JobCompletionNotificationListener 类退出,我们会错过日志中的重要行:

    作业:[FlowJob: [name=writeErrorFromFile]] 使用以下参数完成:[{-input.xml.file=c:/temp/unit-test-error.xml, -spring.batch.job.names =writeErrorFromFile, run.id=15, input.xml.file=c:/temp/unit-test-error.xml}] 和以下状态:[FAILED]

    而且似乎 Spring 上下文没有正确关闭。

    【讨论】:

    • 它不会立即杀死应用程序吗?作业完成后如何退出应用程序?
    【解决方案2】:

    尽管 Sprint-Batch 的 Job 处于退出状态(即 COMPLETED 或 FAILED),java 进程将成功完成(您将获得进程退出代码为 0)。

    如果您想要为 java 进程自定义退出代码,以便您可以在任何脚本或其他地方使用它,您可以使用 JobExecutionListener

    您可以在afterJob() 中检查作业的 exitStatus 并相应地使用所需的退出代码退出 java 进程(即 4 表示 FAILURE)

    JobExecutionListener 示例

    public class InterceptingExitStatus implements JobExecutionListener{
    
        @Override
        public void beforeJob(JobExecution jobExecution) {
        }
    
        @Override
        public void afterJob(JobExecution jobExecution) {
            ExitStatus exitStatus = jobExecution.getExitStatus() ;
    
            if(exitStatus == ExitStatus.COMPLETED ){
                System.exit(0);
            }
    
            if(exitStatus == ExitStatus.FAILED ){
                System.exit(4);
            }
        }
    
    }
    

    这就是您可以在 xml 文件中配置作业侦听器的方式 -

    <job id="job">
    ....
    ....
    
        <listeners>
            <listener ref="interceptingExitStatus "/>
        </listeners>
    </job>
    

    【讨论】:

    • 那是我的第一次尝试,碰巧有时 spring 没有时间更新数据库中的作业状态,因为它在System.exit 之后关闭了连接,所以寻找那个
    【解决方案3】:

    Spring Boot 和 Sring Batch 已经为此提供了内部解决方案,您只需要一行额外的代码:

    System.exit(SpringApplication.exit(applicationContext));
    

    这是另一个例子:

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

    编辑:如果您想知道它是如何工作的,请查看此类:org.springframework.boot.autoconfigure.batch.JobExecutionExitCodeGenerator

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      • 2015-01-31
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多