使用@StepScope时Spring Batch重启功能不起作用 [英] Spring Batch restart functionality not working when using @StepScope

查看:43
本文介绍了使用@StepScope时Spring Batch重启功能不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望使用Spring Batch(v3.0.9)重新启动功能,以便在JobInstance重新启动时,流程步骤从最后一个失败的块点开始向前读取。只要我不对myBatisPagingItemReaderbean方法使用@StepScope注释,我的重启就可以正常工作。
我使用@StepScope以便可以进行后期绑定,以便在我的myBatisPagingItemReaderbean方法@Value("#{jobParameters['run-date']}"))中获取JobParameters 如果我在myBatisPagingItemReader()Bean方法上使用@StepScope注释,则重新启动不起作用,因为它创建了新实例(Scope=Step,name=scopedTarget.myBatisPagingItemReader).
如果我使用StepScope,我的myBatiPagingItemReader是否可以设置上次失败后的read.count以使重新启动工作正常?

我已经用下面的示例说明了此问题。

@Configuration
@EnableBatchProcessing
public class BatchConfig {
    @Bean
    public Step step1(StepBuilderFactory stepBuilderFactory,
        ItemReader<Model> myBatisPagingItemReader,
        ItemProcessor<Model, Model> itemProcessor,
         ItemWriter<Model> itemWriter) {

         return stepBuilderFactory.get("data-load")
            .<Model, Model>chunk(10)
            .reader(myBatisPagingItemReader)
            .processor(itemProcessor)
             .writer(itemWriter)
             .listener(itemReadListener())
             .listener(new JobParameterExecutionContextCopyListener())
             .build();
   }
   @Bean
   public Job job(JobBuilderFactory jobBuilderFactory, @Qualifier("step1") 
               Step step1) {
           return jobBuilderFactory.get("load-job")
            .incrementer(new RunIdIncrementer())
            .start(step1)
            .listener(jobExecutionListener())
            .build();
   }
   @Bean
   @StepScope
   public ItemReader<Model> myBatisPagingItemReader(
         SqlSessionFactory sqlSessionFactory,
         @Value("#{JobParameters['run-date']}") String runDate) 
  {
     MyBatisPagingItemReader<Model> reader = new 
     MyBatisPagingItemReader<>();
     Map<String, Object> parameterValues = new HashMap<>();
     parameterValues.put("runDate", runDate);
     reader.setSqlSessionFactory(sqlSessionFactory);
     reader.setParameterValues(parameterValues);
     reader.setQueryId("query");
     return reader;
   }
}

重新启动示例当我对myBatisPagingItemReader()使用@Stepscope注释时,读取器正在提取5条记录,并且我将块大小(Commit-Interval)设置为3。

作业实例-01-作业参数-01/02/2019。
区块1:
-过程记录-1
-过程记录
-过程记录
编写器-写入所有3条记录
区块-1提交成功

块-2:
过程记录-4
流程记录-5-抛出和异常
作业完成并设置为"失败"状态

现在使用相同的作业参数再次重新启动该作业。
作业实例-01-作业参数-01/02/2019。
区块1:
过程记录-1
过程记录-2
过程记录-3
编写器-写入所有3条记录
区块-1提交成功

块-2:
过程记录-4
流程记录-5-抛出和异常
作业完成并设置为"失败"状态

myBatisPagingItemReader()bean方法上的@StepScope注释创建一个新实例,请参阅下面的日志消息。
在Scope=step,Name=scope edTarget.myBatiPagingItemReader中创建对象
在Scope=step,Name=scope edTarget.myBatiPagingItemReader中注册销毁回调
因为它是新实例,所以它从开始启动进程,而不是从块2开始。

如果我不使用@Stepscope,它将从Chunk-2重新启动,因为重新启动的作业步骤设置为-MyBatiPagingItemReader.read.count=3。

推荐答案

这里的问题是您返回的是ItemReader而不是完全限定的类(MyBatisPagingItemReader)或至少是ItemStreamReader。当您使用Spring Batch的步骤作用域时,我们创建一个代理以允许后期初始化。代理基于方法的返回类型(在本例中为ItemReader)。您遇到的问题是,因为代理是ItemReader,Spring Batch不知道您的bean也实现了ItemStream,而正是那个接口启用了可重启性。默认情况下,Spring Batch将自动为您注册ItemStream类型的所有bean(您也可以自己显式注册bean,但通常不需要)。

要解决您的问题,应执行以下操作(请注意返回类型的更改):

   @Bean
   @StepScope
   public MyBatisPagingItemReader<Model> myBatisPagingItemReader(
         SqlSessionFactory sqlSessionFactory,
         @Value("#{JobParameters['run-date']}") String runDate) {

     MyBatisPagingItemReader<Model> reader = 
         new MyBatisPagingItemReader<>();

     Map<String, Object> parameterValues = new HashMap<>();
     parameterValues.put("runDate", runDate);

     reader.setSqlSessionFactory(sqlSessionFactory);
     reader.setParameterValues(parameterValues);
     reader.setQueryId("query");

     return reader;
   }

这就是为什么我建议在可能的情况下,在使用@Bean带注释的方法时,应尽可能返回最具体的类型,以便允许Spring提供尽可能多的帮助。

这篇关于使用@StepScope时Spring Batch重启功能不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆