0
votes

I have a custom writer which works well ; however, I'd like to set the name of my output file through JobParameters instead of using a fixed string in my configuration. In order to do that, I added the @StepScope annotation and parameters, just like I did with my ItemReader.

ItemWriter declaration

@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;
}

Step declaration

@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();
}

This code doesn't work, I get a WriterNotOpenException because of the FlatFileItemWriter I use as a delegate.

I had the same error when I tried to use JobParameters for my ItemReader, I had to change the return type to "FlatFileItemReader" (instead of ItemReader). I can't do the same here because I need my custom ItemWriter and not a simple FlatFileItemWriter.

I don't understand why I get this error when I add the @StepScope while my reader has no problem without it. What am I doing wrong ?

Additional info :

  • My configuration worked when I was using the inputFile and outputFile strings.
  • It looks like I have an error when I add the @StepScope annotation (even without adding JobParameters as my writer parameters).
2

2 Answers

0
votes

You have to register delegate writer as stream; in this way SB will manage stream lifecycle in the right way.

0
votes

who CityItemWriter implements ?

try - change public ItemWriter to FlatFileItemWriter

ERROR

public ItemWriter leituraArquivoDelimitadoWriter(@Value("#{jobParameters['arquivoSaidaClientes']}") Resource arquivoClienteSaida) { //return items -> items.forEach(System.out::println);

    return new **FlatFileItemWriterBuilder**<Cliente>()
            .name("leituraArquivoDelimitadoWriter")
            .resource(arquivoClienteSaida)              
            .delimited()
            .names(new String [] {"nome", "sobrenome", "idade", "email"})
            .build();
}

}

MESSAGE ERROR

org.springframework.batch.item.WriterNotOpenException: Writer must be open before it can be written to

OK

public FlatFileItemWriter leituraArquivoDelimitadoWriter(@Value("#{jobParameters['arquivoSaidaClientes']}") Resource arquivoClienteSaida) { //return items -> items.forEach(System.out::println);

    return new **FlatFileItemWriterBuilder**<Cliente>()
            .name("leituraArquivoDelimitadoWriter")
            .resource(arquivoClienteSaida)              
            .delimited()
            .names(new String [] {"nome", "sobrenome", "idade", "email"})
            .build();
}

}

in this case change public ItemWriter to FlatFileItemWriter solve the problem.