java 当在Spring Batch中使用StepScope注解访问ItemReader中的参数时,ItemWriter不生成输出

kmbjn2e3  于 2023-08-02  发布在  Java
关注(0)|答案(1)|浏览(154)

我正在使用spring Boot 和spring batch application来测试通过下面的代码向ItemReader传递参数,但是当我使用StepScope annotation时,contact-out.dat文件(输出文件)的内容是空的。没有错误,它只是不产生任何结果:

@Bean
@StepScope
public ItemReader<Contact> reader(@Value("#{jobParameters['fileName']}") String fileName) {             
    
    BeanIOFlatFileItemReader<Contact> reader = new BeanIOFlatFileItemReader<>();
    try {           
        reader.setUseSpringExceptions(true);
        reader.setResource(new FileSystemResource(fileName));
        reader.setStreamName(inputContactStreamName);
        reader.setStreamMapping(new ClassPathResource(beanIoConfigurationXmlPath));
        reader.setStreamFactory(StreamFactory.newInstance());
        reader.getLineNumber();
        reader.afterPropertiesSet();
    } catch (Exception e) {
        log.error("ERROR: An issue occurred in the BeanIO Item Reader:: {} {}", e.getMessage(), e.getStackTrace());
    }
    
    return reader;      
    
}    

@Bean
public FlatFileItemWriter<Contact> writer() {
    
    FlatFileItemWriter<Contact> writer = new FlatFileItemWriter<>();
    writer.setResource(new FileSystemResource(fileOutputContact));
    writer.setLineAggregator(new DelimitedLineAggregator<Contact>() {
        {
            setDelimiter(",");
            setFieldExtractor(new BeanWrapperFieldExtractor<Contact>() {
                {
                    setNames(new String[] { "firstName", "lastName", "street", "city", "state", "zip" });
                }                   
            });
        }
    });
    
    return writer;
}
    
@Bean("InputJob")
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Job importUserJob(Step step) {
    return jobBuilderFactory.get("importUserJob")
      .incrementer(new RunIdIncrementer())          
      .flow(step)
      .end()
      .build();
}

@Bean
public Step step(ItemReader<Contact> reader) {      
    return stepBuilderFactory.get("step")
      .<Contact, Contact> chunk(10)
      .reader(reader(null))          
      .processor(contactItemProcessor)
      .writer(writer())          
      .build();
}

字符串
现在,如果我删除StepScope注解并进行以下更改,则contact-out.dat文件具有预期的内容:

@Bean
//@StepScope
public ItemReader<Contact> reader(/*@Value("#{jobParameters['fileName']}") String fileName*/) {...}

@Bean
public Step step(ItemReader<Contact> reader) {      
    return stepBuilderFactory.get("step")
      .<Contact, Contact> chunk(10)
      .reader(reader(/*null*/))          
      .processor(contactItemProcessor)
      .writer(writer())          
      .build();
}


当使用StepScope注解时,输出文件总是空的,我在这里做错了什么?

kd3sttzy

kd3sttzy1#

当使用@Configuration类时,对@Bean方法最好的做法是尽可能具体地说明类型。因为此类型信息在加载时用于确定要执行的回调或要创建的代理。
当你添加一个@StepScope时,会发生的是为方法的参数类型创建一个懒惰代理。在您的情况下,这是一个ItemReader<Contact>。如果你检查javadoc of the FlatFileItemReader,你会发现它实现了更多的接口。Spring Batch需要这些接口来执行适当的回调以初始化读取器。但是,如果是ItemReader,则这些回调不存在。

@Bean
@StepScope
public BeanIOFlatFileItemReader<Contact> reader(@Value("#{jobParameters['fileName']}") String fileName) {             
    BeanIOFlatFileItemReader<Contact> reader = new BeanIOFlatFileItemReader<>();
    reader.setUseSpringExceptions(true);
    reader.setResource(new FileSystemResource(fileName));
    reader.setStreamName(inputContactStreamName);
    reader.setStreamMapping(new ClassPathResource(beanIoConfigurationXmlPath));
    reader.setStreamFactory(StreamFactory.newInstance());
    reader.getLineNumber();
    return reader;          
}

字符串
这样就可以创建适当的代理,并且所有回调都将有效。
在您的配置中,您已经将ItemReader作为参数注入,请使用它而不是调用reader(null)

@Bean
public Step step(BeanIOFlatFileItemReader<Contact> reader) {      
    return stepBuilderFactory.get("step")
      .<Contact, Contact> chunk(10)
      .reader(reader)          
      .processor(contactItemProcessor)
      .writer(writer())          
      .build();
}

相关问题