Spring Batch:从未调用过FlatFileItemWriter标头 [英] Spring batch : FlatFileItemWriter header never called
问题描述
我的FlatFileItemWriter回调有一个奇怪的问题。 我有一个实现FlatFileFooterCallback和FlatFileHeaderCallback的自定义ItemWriter。因此,我在FlatFileItemWriter中设置了页眉和页脚回调,如下所示:
ItemWriter Bean
@Bean
@StepScope
public ItemWriter<CityItem> writer(FlatFileItemWriter<CityProcessed> flatWriter, @Value("#{jobExecutionContext[inputFile]}") String inputFile) {
CityItemWriter itemWriter = new CityItemWriter();
flatWriter.setHeaderCallback(itemWriter);
flatWriter.setFooterCallback(itemWriter);
itemWriter.setDelegate(flatWriter);
itemWriter.setInputFileName(inputFile);
return itemWriter;
}
FlatFileItemWriter Bean
@Bean
@StepScope
public FlatFileItemWriter<CityProcessed> flatFileWriterArchive(@Value("#{jobExecutionContext[outputFileArchive]}") String outputFile) {
FlatFileItemWriter<CityProcessed> flatWriter = new FlatFileItemWriter<CityProcessed>();
FileSystemResource isr;
isr = new FileSystemResource(new File(outputFile));
flatWriter.setResource(isr);
DelimitedLineAggregator<CityProcessed> aggregator = new DelimitedLineAggregator<CityProcessed>();
aggregator.setDelimiter(";");
BeanWrapperFieldExtractor<CityProcessed> beanWrapper = new BeanWrapperFieldExtractor<CityProcessed>();
beanWrapper.setNames(new String[]{
"country", "name", "population", "popUnder25", "pop25To50", "pop50to75", "popMoreThan75"
});
aggregator.setFieldExtractor(beanWrapper);
flatWriter.setLineAggregator(aggregator);
flatWriter.setEncoding("ISO-8859-1");
return flatWriter;
}
步骤Bean
@Bean
public Step stepImport(StepBuilderFactory stepBuilderFactory, ItemReader<CityFile> reader, ItemWriter<CityItem> writer, ItemProcessor<CityFile, CityItem> processor,
@Qualifier("flatFileWriterArchive") FlatFileItemWriter<CityProcessed> flatFileWriterArchive, ExecutionContextPromotionListener executionContextListener) {
return stepBuilderFactory.get("stepImport").<CityFile, CityItem> chunk(10).reader(reader(null)).processor(processor).writer(writer).stream(flatFileWriterArchive)
.listener(executionContextListener).build();
}
我的WriteFooter、WriteHeader和Wire方法中包含经典内容。
ItemWriter代码
public class CityItemWriter implements ItemWriter<CityItem>, FlatFileFooterCallback, FlatFileHeaderCallback, ItemStream {
private FlatFileItemWriter<CityProcessed> writer;
private static int totalUnknown = 0;
private static int totalSup10000 = 0;
private static int totalInf10000 = 0;
private String inputFileName = "-";
public void setDelegate(FlatFileItemWriter<CityProcessed> delegate) {
writer = delegate;
}
public void setInputFileName(String name) {
inputFileName = name;
}
private Predicate<String> isNullValue() {
return p -> p == null;
}
@Override
public void write(List<? extends CityItem> cities) throws Exception {
List<CityProcessed> citiesCSV = new ArrayList<>();
for (CityItem item : cities) {
String populationAsString = "";
String less25AsString = "";
String more25AsString = "";
/*
* Some processing to get total Unknown/Sup 10000/Inf 10000
* and other data
*/
// Write in CSV file
CityProcessed cre = new CityProcessed();
cre.setCountry(item.getCountry());
cre.setName(item.getName());
cre.setPopulation(populationAsString);
cre.setLess25(less25AsString);
cre.setMore25(more25AsString);
citiesCSV.add(cre);
}
writer.write(citiesCSV);
}
@Override
public void writeFooter(Writer fileWriter) throws IOException {
String newLine = "
";
String totalUnknown= "Subtotal:;Unknown;" + String.valueOf(nbUnknown) + newLine;
String totalSup10000 = ";Sum Sup 10000;" + String.valueOf(nbSup10000) + newLine;
String totalInf10000 = ";Sum Inf 10000;" + String.valueOf(nbInf10000) + newLine;
String total = "Total:;;" + String.valueOf(nbSup10000 + nbInf10000 + nbUnknown) + newLine;
fileWriter.write(newLine);
fileWriter.write(totalUnknown);
fileWriter.write(totalSup10000);
fileWriter.write(totalInf10000);
fileWriter.write(total );
}
@Override
public void writeHeader(Writer fileWriter) throws IOException {
String newLine = "
";
String firstLine= "FILE PROCESSED ON: ;" + new SimpleDateFormat("MM/dd/yyyy").format(new Date()) + newLine;
String secondLine= "Filename: ;" + inputFileName + newLine;
String colNames= "Country;Name;Population...;...having less than 25;...having more than 25";
fileWriter.write(firstLine);
fileWriter.write(secondLine);
fileWriter.write(newLine);
fileWriter.write(colNames);
}
@Override
public void close() throws ItemStreamException {
writer.close();
}
@Override
public void open(ExecutionContext context) throws ItemStreamException {
writer.open(context);
}
@Override
public void update(ExecutionContext context) throws ItemStreamException {
writer.update(context);
}
}
当我运行我的批处理时,我只有每个城市(写入方法部分)和脚注行的数据。如果我注释WRITE方法和页脚回调的整个内容,我仍然没有标题行。我尝试在标头回调中添加System.out.println()文本,但它看起来从未被调用过。
以下是我的批次生成的CSV文件的示例:
France;Paris;2240621;Unknown;Unknown
France;Toulouse;439553;Unknown;Unknown
Spain;Barcelona;1620943;Unknown;Unknown
Spain;Madrid;3207247;Unknown;Unknown
[...]
Subtotal:;Unknown;2
;Sum Sup 10000;81
;Sum Inf 10000;17
Total:;;100
奇怪的是,以前我的页眉可以正常工作,当时我同时添加了页脚和页眉回调。我没有更改它们,我也不知道我在代码中做了什么来"破坏"我的头回调……当然,除了我的第一个代码,我别无选择。因为我现在才看到我的头文件消失了(我检查了我的最后几个文件,看起来我的头文件丢失了一段时间,但我没有看到它),所以我不能只是删除我的修改来查看它何时/为什么会发生。
您有什么办法解决这个问题吗?
谢谢
推荐答案
使用Java配置时,最好尽可能返回最具体的类型(与Java编程中通常要求您做的相反)。在本例中,您的编写器返回ItemWriter
,但属于步骤作用域。因此,创建了一个代理,它只能看到您的Java配置返回的类型,在本例中为ItemWriter
,并且不公开ItemStream
接口上的方法。如果您返回CityItemWriter
,我希望一切正常。
这篇关于Spring Batch:从未调用过FlatFileItemWriter标头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!