【问题标题】:Spring Batch retry doesn't work in Java if the app implements the CommandLineRunner如果应用程序实现 CommandLineRunner,则 Spring Batch 重试在 Java 中不起作用
【发布时间】:2020-06-07 17:41:28
【问题描述】:

作为参考Retry not working with Spring Batch with Java Config 我签入了以下春季批处理阅读器重试示例https://github.com/atulkulkarni18/spring-batch-reader-retry 的代码,并且重试功能按预期工作。 但是实现 CommandLineRunner(如下面的代码所示),重试功能不起作用......有人可以建议吗?

@SpringBootApplication
@EnableBatchProcessing
@Data
@NoArgsConstructor
@AllArgsConstructor
@EnableRetry
public class Stack56170179Application implements CommandLineRunner {

    @Autowired
    JobLauncher jobLauncher;

    @Autowired
    private JobBuilderFactory jobs;

    @Autowired
    private StepBuilderFactory steps;

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

    @Bean
    public Job job() {
        return jobs.get("myJob").start(step1()).build();
    }

    @Bean
    public Step step1() {
        return steps.get("step1").<String, String>chunk(1).reader(myReader())
                .processor(myProcessor())
                .writer(myWriter())
                .build();
    }

    @Override
    public void run(String... args) throws Exception {
        JobParameters params = new JobParametersBuilder()
                .addString("JobID", String.valueOf(System.currentTimeMillis()))
                .toJobParameters();
        jobLauncher.run(job(), params);
    }

    @Bean
    @StepScope
    public MyReader myReader() {
        return new MyReader();
    }

    @Bean
    @StepScope
    public MyProcessor myProcessor() {
        return new MyProcessor();
    }

    @Bean
    @StepScope
    public MyWriter myWriter() {
        return new MyWriter();
    }

}

public class MyReader implements ItemReader<String> {

    private long count;
    private long retryCount;

    @Override
    @Retryable(include = { MyException.class }, maxAttempts = 5)
    public String read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        final long value = count;
        System.out.println("MyReader : " + value);

        if (value == 3 && retryCount <= 2) {
            retryCount++;
            System.out.println("****");
            Thread.sleep(500);
            throw new MyException();
        }

        if (value < 5) {
            count++;
            Thread.sleep(500);
            return String.valueOf(value);
        } else {
            return null;
        }
    }
}


public class MyProcessor implements ItemProcessor<String, String> {

    @Override
    public String process(final String arg0) throws Exception {
        System.out.println("MyProcessor : " + arg0);
        return arg0;
    }

}


public class MyWriter implements ItemWriter<String> {

    @Override
    public void write(final List<? extends String> arg0) throws Exception {
        System.out.println("MyWriter : " + arg0);
    }

}

public class MyException extends Exception {

    private static final long serialVersionUID = 1L;

}

预期输出:

MyReader : 0
MyProcessor : 0
MyWriter : [0]
MyReader : 1
MyProcessor : 1
MyWriter : [1]
MyReader : 2
MyProcessor : 2
MyWriter : [2]
MyReader : 3
****
MyReader : 3
****
MyReader : 3
****
MyReader : 3
MyProcessor : 3
MyWriter : [3]
MyReader : 4
MyProcessor : 4
MyWriter : [4]
MyReader : 5

【问题讨论】:

  • 从您分享的代码中,您希望重试什么?
  • 对不起,我添加了缺少的类,以下是预期的输出: MyReader : 0 MyProcessor : 0 MyWriter : [0] MyReader : 1 MyProcessor : 1 MyWriter : [1] MyReader : 2 MyProcessor : 2 MyWriter:[2] MyReader:3 **** MyReader:3 **** MyReader:3 **** MyReader:3 MyProcessor:3 MyWriter:[3] MyReader:4 MyProcessor:4 MyWriter:[4] MyReader: 5
  • 将预期的输出放入问题中。
  • 嗨斯蒂芬,我把它添加到问题中

标签: java spring-boot command-line spring-batch spring-retry


【解决方案1】:

问题不在于CommandLineRunner,而在于MyReader 对象。您已经创建了普通对象并且它不是 Spring 管理的。 尝试创建像

这样的 spring 托管 bean
 @Bean
 @StepScope
 public MyReader myReader() {
    return new MyReader();
 }

并在方法step1() 中使用myReader() 而不是new MyReader()

希望对您有所帮助!

【讨论】:

  • 嗨,Neetesh,我应用了您评论的更改(请参阅原始帖子),但没有成功。顺便说一句,我添加到 application.properties 文件 spring.batch.job.enabled=false 所以该批处理不在应用程序启动时执行,而是通过 run(String... args) 方法执行。这样做会抛出执行并且不执行重试。
  • 我已将代码与输出一起添加到 github。请查看github.com/neeteshbhardwaj/batch-retry-command-line-runner
  • 请检查您的 pom 和 java 版本。仅供参考,我正在使用 java8。
  • Neetesh,非常感谢您的示例,它的效果很棒;我的错误,在我深入检查了我的项目后,我意识到我没有 @EnableRetry 注释。
  • 顺便说一句,我的最终目标是在我的阅读器中使用 JdbcCursorItemReader 并且我能够做到。为了实用,我用 FlatFileItemReader 创建了一个例子,它工作得很好github.com/jeronimogalicia/batch-retry-flatfile-item-reader
猜你喜欢
  • 2021-03-14
  • 2019-11-10
  • 2017-11-11
  • 1970-01-01
  • 2020-12-22
  • 2020-06-03
  • 1970-01-01
  • 1970-01-01
  • 2018-10-15
相关资源
最近更新 更多