Spring Batch ItemReader列表仅处理一次
我正在尝试使用ListItemReader<String>
、ItemProcessor<String, String>
和ItemWriter<String>
创建Spring批处理作业。
XML如下所示
<job id="sourceJob" xmlns="http://www.springframework.org/schema/batch">
<step id="step1" next="step2">
<tasklet>
<chunk reader="svnSourceItemReader"
processor="metadataItemProcessor"
writer="metadataItemWriter"
commit-interval="1" />
</tasklet>
</step>
<step id="step2">
<tasklet ref="lastRevisionLoggerTasklet"></tasklet>
</step>
</job>
<bean id="svnSourceItemReader"
class="com.example.repository.batch.SvnSourceItemReader"
scope="prototype">
<constructor-arg index="0">
<list>
<value>doc1.xkbml</value>
<value>doc2.xkbml</value>
<value>doc3.xkbml</value>
</list>
</constructor-arg>
</bean>
<bean id="metadataItemProcessor"
class="com.example.repository.batch.MetadataItemProcessor"
scope="prototype" />
<bean id="metadataItemWriter"
class="com.example.repository.batch.MetadataItemWriter"
scope="prototype" />
阅读器、处理器和写入器都是普通的
public class SvnSourceItemReader extends ListItemReader<String> {
public SvnSourceItemReader(List<String> list) {
super(list);
System.out.println("Reading data list " + list);
}
@Override
public String read() {
String out = (String) super.read();
System.out.println("Reading data " + out);
return out;
}
}
public class MetadataItemProcessor implements ItemProcessor<String, String> {
@Override
public String process(String i) throws Exception {
System.out.println("Processing " + i + " : documentId " + documentId);
return i;
}
}
public class MetadataItemWriter implements ItemWriter<String> {
@Override
public void write(List<? extends String> list) throws Exception {
System.out.println("Writing " + list);
}
}
作业按如下方式启动,但按计划每10秒启动一次。
long nanoBits = System.nanoTime() % 1000000L;
if (nanoBits < 0) {
nanoBits *= -1;
}
String dateParam = new Date().toString() + System.currentTimeMillis()
+ "." + nanoBits;
param = new JobParametersBuilder().addString("date", dateParam)
.toJobParameters();
JobExecution execution = jobLauncher.run(job, param);
应用程序启动时,我看到它读取、处理和写入传递给读取器的列表中的三个项目。
Reading data doc1.xkbml
Processing doc1.xkbml : documentId doc1
Writing [doc1.xkbml]
Reading data doc2.xkbml
Processing doc2.xkbml : documentId doc2
Writing [doc2.xkbml]
Reading data doc3.xkbml
Processing doc3.xkbml : documentId doc3
Writing [doc3.xkbml]
因为此sourceJob
使用的是计划计时器,所以我预计每隔10秒就会看到该列表被处理,但实际上我看到的是所有后续运行。
Reading data null
有人知道为什么会发生这种情况吗?我是Spring Batch的新手,对这个问题就是摸不着头脑。
谢谢/w
解决方案
问题是您将读者标记为scope="prototype"
。应为scope="step"
。
Spring-Batch中只有两个作用域:singleton
(默认值)和step
。
来自javadoc:
StepScope:
步骤上下文的范围。此范围内的对象使用 Spring容器作为对象工厂,因此只有一个实例 这样的bean的每个执行步骤。此作用域中的所有对象都 (不需要修饰Bean定义)。
和
需要使用STEP作用域才能使用后期绑定,因为 在步骤开始之前,bean实际上不能被实例化,这 允许查找属性。
在Spring上下文启动期间,请查看日志,您将看到以下行:
信息:已从类路径资源执行完SQL脚本 9毫秒[org/springframework/batch/core/schema-hsqldb.sql]。
读取数据列表[doc1.xkbml,doc2.xkbml,doc3.xkbml]
如您所见,您的读取器已经作为单例创建和管理;Spring-Batch上下文中的动态bean应该使用特殊的step
范围进行管理,以便Spring将在每次执行步骤时创建bean的新副本。
在您的阅读器中,ListItemReader.read()
写为:
public T read() {
if (!list.isEmpty()) {
return list.remove(0);
}
return null;
}
从原始列表中删除每个已读项目!读取器构建一次,在第二次执行作业时,列表为空!
相关文章