Parameters 在Spring批处理中使用StepScope注释时的WriterNotOpenException

Parameters 在Spring批处理中使用StepScope注释时的WriterNotOpenException,parameters,spring-batch,writer,Parameters,Spring Batch,Writer,我有一个习惯性的作家,他写得很好;但是,我希望通过JobParameters设置输出文件的名称,而不是在配置中使用固定字符串。 为了做到这一点,我添加了@StepScope注释和参数,就像我对ItemReader所做的那样 项目编写器声明 @Bean @StepScope public ItemWriter<CityProcessed> writer(@Value("#{jobParameters[inputFile]}") String inputFile, @Value("#{j

我有一个习惯性的作家,他写得很好;但是,我希望通过JobParameters设置输出文件的名称,而不是在配置中使用固定字符串。 为了做到这一点,我添加了@StepScope注释和参数,就像我对ItemReader所做的那样

项目编写器声明

@Bean
@StepScope
public ItemWriter<CityProcessed> writer(@Value("#{jobParameters[inputFile]}") String inputFile, @Value("#{jobParameters[outputFile]}") String outputFile) {
    // String inputFile = "D:/cities.csv";
    // String outputFile = "D:/compterendu.csv";
    FlatFileItemWriter<CityCRE> writer = new FlatFileItemWriter<CityCRE>();
    FileSystemResource isr;
    isr = new FileSystemResource(new File(outputFile));
    writer.setResource(isr);
    DelimitedLineAggregator<CityCRE> aggregator = new DelimitedLineAggregator<CityCRE>();
    aggregator.setDelimiter(";");
    BeanWrapperFieldExtractor<CityCRE> beanWrapper = new BeanWrapperFieldExtractor<CityCRE>();
    beanWrapper.setNames(new String[]{
        "nom", "pays", "identifiantBase", "c/m"
    });
    aggregator.setFieldExtractor(beanWrapper);
    writer.setLineAggregator(aggregator);
    CityItemWriter itemWriter = new CityItemWriter();
    writer.setFooterCallback(itemWriter);
    writer.setHeaderCallback(itemWriter);
    itemWriter.setDelegate(writer);
    itemWriter.setInputFileName(inputFile);
    return itemWriter;
}
@Bean
public Step stepImport(StepBuilderFactory stepBuilderFactory, ItemReader<CityFile> reader, ItemWriter<CityProcessed> writer, ItemProcessor<CityFile, CityProcessed> processor) {
    return stepBuilderFactory
        .get("step1")
        .<CityFile, CityProcessed> chunk(10)
        .reader(reader(null))
        .processor(processor)
        .writer(writer(null, null))
        .build();
}
@Bean
@步进镜
公共ItemWriter编写器(@Value(“{jobParameters[inputFile]}”)字符串输入文件,@Value(“{jobParameters[outputFile]}”)字符串输出文件){
//字符串inputFile=“D:/cities.csv”;
//字符串outputFile=“D:/compterendu.csv”;
FlatFileItemWriter writer=新的FlatFileItemWriter();
文件系统资源isr;
isr=新文件系统资源(新文件(outputFile));
编写器设置资源(isr);
DelimitedLineAggregator aggregator=新的DelimitedLineAggregator();
aggregator.setDelimiter(“;”);
BeanWrapperFieldExtractor beanwraper=新的BeanWrapperFieldExtractor();
beanWrapper.setNames(新字符串[]){
“名称”、“付款”、“标识基础”、“付款方式”
});
聚合器。setFieldExtractor(BeanRapper);
writer.setLineAggregator(聚合器);
CityItemWriter itemWriter=新的CityItemWriter();
setFooterCallback(itemWriter);
writer.setHeaderCallback(itemWriter);
itemWriter.setDelegate(编写器);
setInputFileName(inputFile);
返回项目编写器;
}
步骤声明

@Bean
@StepScope
public ItemWriter<CityProcessed> writer(@Value("#{jobParameters[inputFile]}") String inputFile, @Value("#{jobParameters[outputFile]}") String outputFile) {
    // String inputFile = "D:/cities.csv";
    // String outputFile = "D:/compterendu.csv";
    FlatFileItemWriter<CityCRE> writer = new FlatFileItemWriter<CityCRE>();
    FileSystemResource isr;
    isr = new FileSystemResource(new File(outputFile));
    writer.setResource(isr);
    DelimitedLineAggregator<CityCRE> aggregator = new DelimitedLineAggregator<CityCRE>();
    aggregator.setDelimiter(";");
    BeanWrapperFieldExtractor<CityCRE> beanWrapper = new BeanWrapperFieldExtractor<CityCRE>();
    beanWrapper.setNames(new String[]{
        "nom", "pays", "identifiantBase", "c/m"
    });
    aggregator.setFieldExtractor(beanWrapper);
    writer.setLineAggregator(aggregator);
    CityItemWriter itemWriter = new CityItemWriter();
    writer.setFooterCallback(itemWriter);
    writer.setHeaderCallback(itemWriter);
    itemWriter.setDelegate(writer);
    itemWriter.setInputFileName(inputFile);
    return itemWriter;
}
@Bean
public Step stepImport(StepBuilderFactory stepBuilderFactory, ItemReader<CityFile> reader, ItemWriter<CityProcessed> writer, ItemProcessor<CityFile, CityProcessed> processor) {
    return stepBuilderFactory
        .get("step1")
        .<CityFile, CityProcessed> chunk(10)
        .reader(reader(null))
        .processor(processor)
        .writer(writer(null, null))
        .build();
}
@Bean
公共步骤stepImport(StepBuilderFactory StepBuilderFactory、ItemReader阅读器、ItemWriter编写器、ItemProcessor处理器){
返回stepBuilderFactory
.get(“步骤1”)
.chunk(10)
.读卡器(读卡器(空))
.处理器(处理器)
.writer(writer(null,null))
.build();
}
这段代码不起作用,我得到一个WriterNotOpenException,因为我使用FlatFileItemWriter作为委托

当我尝试为ItemReader使用JobParameters时,我遇到了相同的错误,我必须将返回类型更改为“FlatFileItemReader”(而不是ItemReader)。我不能在这里做同样的事情,因为我需要我的自定义ItemWriter,而不是一个简单的FlatFileItemWriter

我不明白为什么我在添加@StepScope时会出现这个错误,而我的读者没有它就没有问题。我做错了什么

其他信息:

  • 当我使用inputFile和outputFile字符串时,我的配置工作正常
  • 当我添加@StepScope注释时(即使没有将JobParameters添加为我的writer参数),看起来我有一个错误

您必须将代理编写器注册为流;通过这种方式,SB将以正确的方式管理流生命周期。

CityItemWriter由谁实施

尝试-将public ItemWriter更改为FlatFileItemWriter

错误

publicItemWriter LeiturarQuivodeLimitadoWriter(@Value(“#{jobParameters['arquivoSaidaClientes']}”)资源arquivoClienteSaida){ //返回项目->项目.forEach(系统输出::println)

返回新的**FlatFileItemWriterBuilder**()
.姓名(“LeiturarquivodeLimitadoWriter”)
.资源(arquivoClienteSaida)
.delimited()
.names(新字符串[]{“nome”、“sobrenome”、“idade”、“email”})
.build();
}
}

消息错误

org.springframework.batch.item.WriterNotOpenException:必须先打开Writer,然后才能将其写入

正常

publicFlatFileItemWriter LeiturarQuivodeLimitadoWriter(@Value(“#{jobParameters['arquivoSaidaClientes']}”)资源arquivoClienteSaida){ //返回项目->项目.forEach(系统输出::println)

返回新的**FlatFileItemWriterBuilder**()
.姓名(“LeiturarquivodeLimitadoWriter”)
.资源(arquivoClienteSaida)
.delimited()
.names(新字符串[]{“nome”、“sobrenome”、“idade”、“email”})
.build();
}
}


在这种情况下,将publicItemWriter更改为FlatFileItemWriter可以解决这个问题。

它可以工作(谢谢),但我仍然不明白为什么我只使用固定字符串,而不必将委托注册为流。对此有什么解释吗?我帮不了你,对不起:(我想静态/范围注册的工作原理不同,但是@MMinella可能会给你正确的解释。