在我的Spring Batch应用程序中,我编写了一个CustomItemWriter,它使用DynamoDBAsyncClient在内部将项目写入DynamoDB,此客户端返回Future对象。我有一个包含数百万条记录的输入文件。由于CustomItemWriter立即返回未来对象,我的批处理作业在5秒内退出,状态为COMPLETED,但实际上将所有项目写入数据库需要3-4分钟,我希望该批处理作业仅在所有项目写入DataBase后完成。我怎么能这样做?
工作定义如下
<bean id="report" class="com.solution.model.Report" scope="prototype" />
<batch:job id="job" restartable="true">
<batch:step id="step1">
<batch:tasklet>
<batch:chunk reader="cvsFileItemReader" processor="filterReportProcessor" writer="customItemWriter"
commit-interval="20">
</batch:chunk>
</batch:tasklet>
</batch:step>
</batch:job>
<bean id="customItemWriter" class="com.solution.writer.CustomeWriter"></bean>
CustomeItemWriter定义如下
public class CustomeWriter implements ItemWriter<Report>{
public void write(List<? extends Report> item) throws Exception {
List<Future<PutItemResult>> list = new LinkedList();
AmazonDynamoDBAsyncClient client = new AmazonDynamoDBAsyncClient();
for(Report report : item) {
PutItemRequest req = new PutItemRequest();
req.setTableName("MyTable");
req.setReturnValue(ReturnValue.ALL_ODD);
req.addItemEntry("customerId",new
AttributeValue(item.getCustomeId()));
Future<PutItemResult> res = client.putItemAsync(req);
list.add(res);
}
}
}
主类包含
JobExecution execution = jobLauncher.run(job, new JobParameters());
System.out.println("Exit Status : " + execution.getStatus());
因为在ItemWriter中它返回的未来对象它不会等待完成操作。并且从主要提交所有项目以进行写入批处理状态显示COMPLETED并且作业终止。 我希望只有在DynamoDB中执行实际写入后才能终止此作业。 我们可以有一些其他的步骤来等待这个或一些听众可用吗?
答案 0 :(得分:1)
这是一种方法。由于ItemWriter::write
不返回任何内容,因此您可以使用侦听器功能。
@Component
@JobScope
public class YourWriteListener implements ItemWriteListener<WhatEverYourTypeIs> {
@Value("#{jobExecution.executionContext}")
private ExecutionContext executionContext;
@Override
public void afterWrite(final List<? extends WhatEverYourTypeIs> paramList) {
Future future = this.executionContext.readAndValidate("FutureKey", Future.class);
//wait till the job is done using future object
}
@Override
public void beforeWrite(final List<? extends WhatEverYourTypeIs> paramList) {
}
@Override
public void onWriteError(final Exception paramException, final List<? extends WhatEverYourTypeIs> paramList) {
}
}
在您的编写器类中,除了将未来对象添加到ExecutionContext之外,所有内容都保持不变。
public class YourItemWriter extends ItemWriter<WhatEverYourTypeIs> {
@Value("#{jobExecution.executionContext}")
private ExecutionContext executionContext;
@Override
protected void doWrite(final List<? extends WhatEverYourTypeIs> youritems)
//write to DynamoDb and get Future object
executionContext.put("FutureKey", future);
}
}
}
您可以在配置中注册监听器。这是一个java代码,您需要在xml中执行相同的操作
@Bean
public Step initStep() {
return this.stepBuilders.get("someStepName").<YourTypeX, YourTypeY>chunk(10)
.reader(yourReader).processor(yourProcessor)
.writer(yourWriter).listener(YourWriteListener)
.build();
}