我有一个SpringBatch作业,我跳过所有重复的项目写入平面文件。
但是,只要存在重复项,FlatFileItemWriter就会抛出以下错误:Writer must be open before it can be written to
下面是编写器和SkipListener配置-
@Bean(name = "duplicateItemWriter")
public FlatFileItemWriter<InventoryFileItem> dupItemWriter(){
return new FlatFileItemWriterBuilder<InventoryFileItem>()
.name("duplicateItemWriter")
.resource(new FileSystemResource("duplicateItem.txt"))
.lineAggregator(new PassThroughLineAggregator<>())
.append(true)
.shouldDeleteIfExists(true)
.build();
}
public class StepSkipListener implements SkipListener<InventoryFileItem, InventoryItem> {
private FlatFileItemWriter<InventoryFileItem> skippedItemsWriter;
public StepSkipListener(FlatFileItemWriter<InventoryFileItem> skippedItemsWriter) {
this.skippedItemsWriter = skippedItemsWriter;
}
@Override
public void onSkipInProcess(InventoryFileItem item, Throwable t) {
System.out.println(item.getBibNum() + " Process - " + t.getMessage());
try {
skippedItemsWriter.write(Collections.singletonList(item));
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
整个作业的定义如下,我使用的是SkipListener中的duplicateItemWriter。
@Bean(name = "fileLoadJob")
@Autowired
public Job fileLoadJob(JobBuilderFactory jobs, StepBuilderFactory steps,
FlatFileItemReader<inventoryFileItem> fileItemReader,
CompositeItemProcessor compositeItemProcessor,
@Qualifier(value = "itemWriter") ItemWriter<InventoryItem> itemWriter,
StepSkipListener skipListener) {
return jobs.get("libraryFileLoadJob")
.start(steps.get("step").<InventoryFileItem, InventoryItem>chunk(chunkSize)
.reader(FileItemReader)
.processor(compositeItemProcessor)
.writer(itemWriter)
.faultTolerant()
.skip(Exception.class)
.skipLimit(Integer.parseInt(skipLimit))
.listener(skipListener)
.build())
.build();
}
我也试过将所有数据写入FlatFileItemWriter --效果不太好。但是如果写入DB,就没有问题了。
我使用的Spring-Batch版本是-4.3.3,我也提到了以下线程:
3条答案
按热度按时间gk7wooem1#
这只是一个严重的疏忽,我忽略了FlatFileItemWriter需要一个流。我有点失望提出这个问题,但我张贴的答案,以防万一它帮助别人。
解决方案非常简单,只需向作业定义添加一个
stream(dupItemWriter)
。FlatfileItemWriter with Compositewriter example
u59ebvdq2#
包含
.stream(dupItemWriter)
不是绝对必要的,您也可以调用编写器的.open()
方法。在我的例子中,我创建的是动态/编程的ItemWriter,因此将它们添加到流中是不可行的。
相反,我自己调用了.open()方法:
oalqel3c3#
我遇到了同样的问题,我通过继承FlatFileItemWriter创建了两个编写器。在我添加@StepScope注解之前,这是可以工作的。但是在添加@StepScope注解之后,第一个编写器抛出了一个异常,并显示“Writer必须打开才能写入”错误消息。但是第二个编写器工作起来没有任何问题。我通过调用方法open(new ExecutionContext())解决了这个问题;但是我还是不明白为什么第二个有效而第一个不行。