Spring Batch - 从SpringApplicationBuilder调用时如何失败作业

时间:2015-02-18 20:11:56

标签: spring-boot spring-batch

我需要能够使用错误代码退出程序,以便启动程序的调度程序可以知道它失败了。目前,我正在通过SpringApplicationBuilder运行我的工作。

@SpringBootApplication
@EnableBatchProcessing
@Slf4j
public class WeeklyImportApplication extends DefaultBatchConfigurer {

...

    public static void main(String[] args) {
        handleArguments(args);

        new SpringApplicationBuilder(WeeklyImportApplication.class).listeners(new CustomLoggingConfigurationApplicationListener(logConfigurer)).run(args);

        finished();
    }

    @Bean
    public Job weeklyImport(JobBuilderFactory jobs, Step determineTableName, Step determineColumnNames, Step readAccessDb) {
        return jobs.get("weeklyImport").incrementer(new RunIdIncrementer()).flow(determineTableName).next(determineColumnNames).next(readAccessDb).end().build();
    }

    @Bean
    public Step determineTableName(StepBuilderFactory stepBuilderFactory, ItemReader<String> tableNameReader, TableNameWriter tableNameWriter) {
        return stepBuilderFactory.get("determineTableName").<String, String> chunk(100).reader(tableNameReader).writer(tableNameWriter).build();
    }

    @Bean
    public Step determineColumnNames(StepBuilderFactory stepBuilderFactory, ItemReader<String> columnNamesReader, ColumnNamesWriter columnNamesWriter) {
        return stepBuilderFactory.get("determineColumnNames").<String, String> chunk(1000).reader(columnNamesReader).writer(columnNamesWriter).build();
    }

    @Bean
    public Step readAccessDb(StepBuilderFactory stepBuilderFactory, ItemReader<WeeklyStoreItem> importReader, ItemWriter<WeeklyStoreItem> weeklyStoreItemWriter, PlatformTransactionManager legacyTransactionManager) {
        return stepBuilderFactory.get("readAccessDb").<WeeklyStoreItem, WeeklyStoreItem> chunk(chunkSize).reader(importReader).writer(weeklyStoreItemWriter).transactionManager(legacyTransactionManager).build();
    }

...

如果任何步骤失败,在作业执行的任何时候,我都希望能够退出并做两件事:

  1. 将正在处理的文件移至specfic文件夹。
  2. 让调度程序通过程序退出代码知道发生了错误。
  3. 现在,当一个未捕获的异常发生时,该作业将退出,这部分是我想要的,但Spring处理异常,记录它,然后优雅地退出到我的main方法。那时,我不确定如何捕捉作业是否真正成功。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。我设法像这样部分地解决了(Dave Sayer已在评论中概述了这个想法)。

首先我创建了这个创建的侦听器:

import org.springframework.batch.core.ExitStatus;
import org.springframework.boot.autoconfigure.batch.JobExecutionEvent;
import org.springframework.context.ApplicationListener;

public class JobResultListener implements
    ApplicationListener<JobExecutionEvent> {
  private ExitStatus jobExitStatus;

  public ExitStatus getJobExitStatus() {
    return jobExitStatus;
  }

  @Override
  public void onApplicationEvent(JobExecutionEvent event) {
    jobExitStatus = event.getJobExecution().getExitStatus();
  }
}

比我用它以这种方式获得作业执行状态:

@SpringBootApplication
public class Application{

  public static void main(String[] args) {
    SpringApplication springApplication =
        new SpringApplication(Application.class);

    JobResultListener jobResultListener = new JobResultListener();
    springApplication.addListeners(jobResultListener);
    springApplication.run(args);

    if (!ExitStatus.COMPLETED.equals(jobResultListener.getJobExitStatus())) {
      throw new IllegalStateException("Job failed");
    }
  }
}

但由于某种原因,我无法从注入事件中获取异常实例。但正如您所提到的,错误会记录到应用程序日志中,因此这个机制足以让我通过错误代码通知调用我的进程错误!= 0.

顺便说一下,我观察到springApplication.run(args)来电时出现了一些错误,但不确定为什么不是全部。此外,我没有找到Spring Boot文档中提到的任何内容