Spring 批处理似乎没有正确关闭项目编写器
Spring batch doesn't seem to be closing item writers properly
我有一份工作,将每一项都写在一个单独的文件中。为了做到这一点,作业使用了一个 ClassifierCompositeItemWriter,其 ClassifierCompositeItemWriter returns 每个项目都有一个新的 FlatFileItemWriter(代码如下)。
@Bean
@StepScope
public ClassifierCompositeItemWriter<ProcessorResult> writer(@Value("#{jobParameters['outputPath']}") String outputPath) {
ClassifierCompositeItemWriter<MyItem> compositeItemWriter = new ClassifierCompositeItemWriter<>();
compositeItemWriter.setClassifier((item) -> {
String filePath = outputPath + "/" + item.getFileName();
BeanWrapperFieldExtractor<MyItem> fieldExtractor = new BeanWrapperFieldExtractor<>();
fieldExtractor.setNames(new String[]{"content"});
DelimitedLineAggregator<MyItem> lineAggregator = new DelimitedLineAggregator<>();
lineAggregator.setFieldExtractor(fieldExtractor);
FlatFileItemWriter<MyItem> itemWriter = new FlatFileItemWriter<>();
itemWriter.setResource(new FileSystemResource(filePath));
itemWriter.setLineAggregator(lineAggregator);
itemWriter.setShouldDeleteIfEmpty(true);
itemWriter.setShouldDeleteIfExists(true);
itemWriter.open(new ExecutionContext());
return itemWriter;
});
return compositeItemWriter;
}
作业的配置方式如下:
@Bean
public Step step1() {
return stepBuilderFactory
.get("step1")
.<String, MyItem>chunk(1)
.reader(reader(null))
.processor(processor(null, null, null))
.writer(writer(null))
.build();
}
@Bean
public Job job() {
return jobBuilderFactory
.get("job")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
一切正常。所有文件都按我的预期生成。但是,无法删除其中一个文件。只有一个。如果我尝试删除它,我会收到一条消息,指出“OpenJDK 平台二进制文件”正在使用它。如果我将块增加到比我生成的文件数量更大的大小,则可以删除 none 个文件。似乎删除最后一个块中生成的文件存在问题,就像 Spring 批处理生命周期或其他东西没有正确关闭相应的编写器一样。
如果我杀死应用程序进程,我可以删除文件。
我知道为什么会这样吗?提前致谢!
PS:我称之为“itemWriter.open(new ExecutionContext());”因为如果我不这样做,我会得到一个“org.springframework.batch.item.WriterNotOpenException:写入器必须先打开才能写入”。
编辑:
如果有人遇到类似问题,我建议阅读 Mahmoud 对这个问题的回答。
可能您在执行此操作时在步骤范围之外使用了 itemwriter:
itemWriter.open(new ExecutionContext());
请查看this question,希望对您有所帮助。
我有一份工作,将每一项都写在一个单独的文件中。为了做到这一点,作业使用了一个 ClassifierCompositeItemWriter,其 ClassifierCompositeItemWriter returns 每个项目都有一个新的 FlatFileItemWriter(代码如下)。
@Bean
@StepScope
public ClassifierCompositeItemWriter<ProcessorResult> writer(@Value("#{jobParameters['outputPath']}") String outputPath) {
ClassifierCompositeItemWriter<MyItem> compositeItemWriter = new ClassifierCompositeItemWriter<>();
compositeItemWriter.setClassifier((item) -> {
String filePath = outputPath + "/" + item.getFileName();
BeanWrapperFieldExtractor<MyItem> fieldExtractor = new BeanWrapperFieldExtractor<>();
fieldExtractor.setNames(new String[]{"content"});
DelimitedLineAggregator<MyItem> lineAggregator = new DelimitedLineAggregator<>();
lineAggregator.setFieldExtractor(fieldExtractor);
FlatFileItemWriter<MyItem> itemWriter = new FlatFileItemWriter<>();
itemWriter.setResource(new FileSystemResource(filePath));
itemWriter.setLineAggregator(lineAggregator);
itemWriter.setShouldDeleteIfEmpty(true);
itemWriter.setShouldDeleteIfExists(true);
itemWriter.open(new ExecutionContext());
return itemWriter;
});
return compositeItemWriter;
}
作业的配置方式如下:
@Bean
public Step step1() {
return stepBuilderFactory
.get("step1")
.<String, MyItem>chunk(1)
.reader(reader(null))
.processor(processor(null, null, null))
.writer(writer(null))
.build();
}
@Bean
public Job job() {
return jobBuilderFactory
.get("job")
.incrementer(new RunIdIncrementer())
.flow(step1())
.end()
.build();
}
一切正常。所有文件都按我的预期生成。但是,无法删除其中一个文件。只有一个。如果我尝试删除它,我会收到一条消息,指出“OpenJDK 平台二进制文件”正在使用它。如果我将块增加到比我生成的文件数量更大的大小,则可以删除 none 个文件。似乎删除最后一个块中生成的文件存在问题,就像 Spring 批处理生命周期或其他东西没有正确关闭相应的编写器一样。
如果我杀死应用程序进程,我可以删除文件。
我知道为什么会这样吗?提前致谢!
PS:我称之为“itemWriter.open(new ExecutionContext());”因为如果我不这样做,我会得到一个“org.springframework.batch.item.WriterNotOpenException:写入器必须先打开才能写入”。
编辑:
如果有人遇到类似问题,我建议阅读 Mahmoud 对这个问题的回答
可能您在执行此操作时在步骤范围之外使用了 itemwriter:
itemWriter.open(new ExecutionContext());
请查看this question,希望对您有所帮助。