代码之家  ›  专栏  ›  技术社区  ›  Grechka Vassili

Spring批量返回自定义进程退出代码

  •  2
  • Grechka Vassili  · 技术社区  · 6 年前

    我有一个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批处理启动正确的作业。

    问题是,我需要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 但是如何使用这个类呢?

    2 回复  |  直到 6 年前
        1
  •  3
  •   Grechka Vassili    6 年前

    感谢@马亨德拉,我有一个想法:

    我创造了一个 JobCompletionNotificationListener 类为@ MahandRA建议:

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

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

    我这么做是因为如果我们直接离开 作业完成通知侦听器 班级我们漏掉了日志中的一行:

    作业:[流作业:[name=WrreReRoFrame文件] ]用下列参数完成:[{-Posi.xml文件://TEMP/UNIT-TESTErr.xml,-prun.Posi.Copy.Name=WrreReRoReFrame,Run.ID=15,输入.xml文件.//TEMP/单元测试错误.XML}]和以下状态:[失败]

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

        2
  •  1
  •   Mahendra    6 年前

    尽管Sprint批处理任务的退出状态(即完成或失败),Java进程将成功完成(并且您将获得进程退出代码为0)。

    如果您希望为Java进程提供自定义退出代码,以便您可以使用它或任何脚本或其他地方,则可以使用 JobExecutionListener .

    您可以查看作业的退出状态。 afterJob() 并相应地用您希望的退出代码退出Java进程(即失败4)。

    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>