使用@StepScope时Spring Batch重启功能不起作用 [英] Spring Batch restart functionality not working when using @StepScope
问题描述
我希望使用Spring Batch(v3.0.9)重新启动功能,以便在JobInstance
重新启动时,流程步骤从最后一个失败的块点开始向前读取。只要我不对myBatisPagingItemReader
bean方法使用@StepScope
注释,我的重启就可以正常工作。
我使用@StepScope
以便可以进行后期绑定,以便在我的myBatisPagingItemReader
bean方法@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屋!