首页 文章

Spring Batch WriterNotOpenException

提问于
浏览
0

我创建了一个简单的单步Spring批处理作业,它从DB读取项目,处理它们并将结果写入csv . 在运行期间,我最终得到了一个

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

相关代码:

@Configuration
@EnableBatchProcessing
@EnableAutoConfiguration
public class CleanEmailJob {

@Autowired
private JobBuilderFactory jobBuilderFactory;

@Autowired
private StepBuilderFactory stepBuilderFactory;

@Autowired
public DataSource dataSource;

@Bean
public ResourcelessTransactionManager transactionManager() {
    return new ResourcelessTransactionManager();
}

@Bean
public MapJobRepositoryFactoryBean mapJobRepositoryFactory(ResourcelessTransactionManager txManager)
        throws Exception {
    MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(txManager);
    factory.afterPropertiesSet();
    return factory;
}

@Bean
public JobRepository jobRepository(MapJobRepositoryFactoryBean factory) throws Exception {
    return factory.getObject();
}

@Bean
public JobExplorer jobExplorer(MapJobRepositoryFactoryBean factory) {
    return new SimpleJobExplorer(factory.getJobInstanceDao(), factory.getJobExecutionDao(),
            factory.getStepExecutionDao(), factory.getExecutionContextDao());
}

@Bean
public SimpleJobLauncher jobLauncher(JobRepository jobRepository) {
    SimpleJobLauncher launcher = new SimpleJobLauncher();
    launcher.setJobRepository(jobRepository);
    return launcher;
}


@Bean
public Job cleanEmailAddressesJob() throws Exception {
    return jobBuilderFactory.get("cleanEmailAddresses")
            .incrementer(new RunIdIncrementer())
            .start(processEmailAddresses())
            .build();
}

@Bean
public Step processEmailAddresses() throws UnexpectedInputException, ParseException, Exception {
    return stepBuilderFactory.get("processAffiliates")
            .<AffiliateEmailAddress, VerifiedAffiliateEmailAddress> chunk(10)
            .reader(reader())
            .processor(processor())     
            .writer(report())
            .build();
}

@Bean
public ItemWriter<VerifiedAffiliateEmailAddress> report(){
    FlatFileItemWriter<VerifiedAffiliateEmailAddress> reportWriter = new FlatFileItemWriter<VerifiedAffiliateEmailAddress>();
    reportWriter.setResource(new ClassPathResource("report.csv"));
    DelimitedLineAggregator<VerifiedAffiliateEmailAddress> delLineAgg = new DelimitedLineAggregator<VerifiedAffiliateEmailAddress>();
    delLineAgg.setDelimiter(",");
    BeanWrapperFieldExtractor<VerifiedAffiliateEmailAddress> fieldExtractor = new BeanWrapperFieldExtractor<VerifiedAffiliateEmailAddress>();
    fieldExtractor.setNames(new String[] {"uniekNr", "reason"});
    delLineAgg.setFieldExtractor(fieldExtractor);
    reportWriter.setLineAggregator(delLineAgg);
    reportWriter.setShouldDeleteIfExists(true);
    return reportWriter;
}

正如文档中所描述的那样,我希望生命周期事件(打开,关闭)会自动处理,因为我处于单线程和单个编写器作业中?

2 回答

  • 0

    最后,结果是Spring Dev Tools干扰了我的批处理应用程序 . report.csv在我的类路径中,当写入报告文件时,Spring Dev Tools检测到我的类路径中的更改并触发重新加载应用程序,导致report.csv资源被关闭...

    spring.devtools.restart.enabled=false
    

    在我的application.properties使它再次工作

  • 0

    为了详细说明留下的评论,Spring Batch会在找到它们时自动注册任何 ItemStream 实现,以便在步骤开始时自动打开它们 . 使用java配置时,Spring只知道返回类型是什么 . 由于您要返回 ItemReader ,我们不知道您的实现也实现 ItemStream . 使用java配置时,我通常建议如果已知(而不是接口)则返回实现 . 这允许Spring完全反省它 . 因此,在此示例中,返回 FlatFileItemReader 而不是 ItemReader 将解决此问题 .

相关问题