代码之家  ›  专栏  ›  技术社区  ›  Druckles

在基于块的步骤中中止批处理作业

  •  2
  • Druckles  · 技术社区  · 8 年前

    我在Spring Batch中设置了一个有点线性的作业,该作业由几个步骤组成。如果在任何一点上,一个步骤失败,那么作业应该失败。

    这些步骤由多个微线程和一个基于块的步骤组成。即。:

    • 步骤1
      • 微线程1
    • 第2步
      • 微线程2
    • 步骤3
      • 读者
      • 加工机
      • 作家

    如果出现问题,最明显的做法是抛出异常。Spring Batch将处理此问题并记录所有内容。这种行为,特别是打印堆栈跟踪,是不可取的,如果作业可以优雅地结束,并将状态设置为 FAILED .

    微线程当前设置 ExitStatus 直接在 StepContribution . 它们也使用流来构建(这并不理想,但在其他情况下,这些步骤可以不受阻碍地继续进行)。然后可以在Tasklet中直接处理这些问题。

    然而,我们无法访问 阶跃贡献 在基于块的方法中。我们只有 StepExecution . 使用 setExitStatus 这里什么都不做。

    我们正在使用建筑商( JobBuilerFactory StepBuilderFactory ),而不是XML设置。

    潜在的解决方案:

    1. 告诉或配置批处理如何处理异常(而不是打印堆栈跟踪)。
    2. 捕捉侦听器中的异常。不幸的是,当Spring批处理到达 @AfterStep .
    3. 告诉步骤/作业我们不想继续(例如,在执行上下文中设置值或为 阶跃贡献 .
    3 回复  |  直到 7 年前
        1
  •  1
  •   Druckles    7 年前

    据我所知,停止作业的唯一方法是抛出异常。没有其他优雅的方式告诉Spring Batch“这项工作完成了,它失败了,直接转到失败,不要通过,等等。”

    虽然不是原始问题的直接解决方案,但可以使用 .exceptionHandler() StepBuilder 为了更好地控制抛出的异常,例如记录它们。

    public class LogAndRethrowExceptionHandler implements ExceptionHandler {
        private static final Logger LOGGER = Logger.getLogger(...);
    
        @Override
        public void handleException(RepeatContext repeatContext, Throwable throwable) throws Throwable {
            LOGGER.error(throwable.getMessage());
            throw throwable;
        }
    }
    

    理论上,这样可以隐藏Spring批处理生成的堆栈跟踪,但仍然显示错误消息。

        2
  •  0
  •   Niraj Sonawane    8 年前

    我认为你可以探索以下两种选择。

    选项1: 您可以使用 noSkip 例外 .

    这明确防止跳过某些异常(和子类) 抛出一些您希望作业失败的特定异常。

    这是如何配置hat的

    stepBuilderFactory.get("myStep")
                    .<POJO, POJO> chunk(1000)
                    .reader(reader)
                    .processor(processor)
                    .writer(writer)
                    .faultTolerant()
                    .noSkip(YourCustomException.class)
                    .skip(Exception.class)
                    .skipLimit(100) 
    

    ****选项2**:*您可以使用将退出状态设置为 失败 对于步骤完成后的错误流

    public class MyStepExecutionListener implements StepExecutionListener {
    
        @Override
        public ExitStatus afterStep(StepExecution stepExecution) {
    
    
        if(allIsGood()) // 
        {
             return ExitStatus.COMPLETED;
        }
        else if (someExceptionOrErrorCase()){   
    
            return ExitStatus.FAILED;
        }
     }
    
     }
    

    希望这有帮助

        3
  •  0
  •   user9869932    4 年前

    在我的例子中,我最终添加了条件并抛出 JobInterruptedException 在读卡器和处理器中

    import org.springframework.batch.core.BatchStatus;
    import org.springframework.batch.core.JobInterruptedException;
    
    public class CustomReader implements ItemReader<String> {
    
      @Override
      public String read() throws Exception {
        // ...
    
        // if ("condition to stop job") {
          throw new JobInterruptedException("Aborting Job", BatchStatus.ABANDONED);
        // }
      }
    
    }