我阅读了相关问题,但解决方案对我不起作用。
我收到org.springframework.batch.item.ReaderNotOpenException: Reader must be open before it can be read
例外。
以下是我的配置:
@Bean
@StepScope
public ItemReader<Player> reader(@Value("#{jobParameters[inputZipfile]}") String inputZipfile) {
final String [] header = { .. this part omitted for brevity ... };
FlatFileItemReader<Player> reader = new FlatFileItemReader<Player>();
System.out.println("\t\t\t\t\t"+inputZipfile);
reader.setResource(new ClassPathResource(inputZipfile));
reader.setLineMapper(new DefaultLineMapper<Player>() {{
setLineTokenizer(new DelimitedLineTokenizer() {{
setNames( header );
}});
setFieldSetMapper(new BeanWrapperFieldSetMapper<Player>() {{
setTargetType(Player.class);
}});
}});
reader.setComments( header );
return reader;
}
@Bean
@StepScope
public ItemProcessor<Player, PlayersStats> processor(@Value("#{jobParameters[statType]}") String statType,
@Value("#{jobParameters[season]}") String season){
PlayersStatsProcessor psp = new PlayersStatsProcessor();
psp.setStatisticType( StatisticType.valueOf(statType) );
psp.setSeason( season );
return psp;
}
@Bean
@StepScope
public ItemWriter<PlayersStats> writer(){
return new CustomWriter();
}
@Bean
public Job generateStatisticsJob() {
return this.jobs.get("generateStatisticsJob")
.incrementer(new RunIdIncrementer())
.start(processPlayerStats())
//.end()
.build();
}
@Bean
public Step processPlayerStats() {
return this.steps.get("processPlayerStats")
.<Player, PlayersStats> chunk(10)
.reader(reader(null))
.processor(processor(null,null))
.writer(writer())
.build();
}
inputZipFile变量设置正确,文件存在于驱动器上。 我检查了FlatFileItemReader代码,并且在未设置reader类的reader成员时发生ReaderNotOpenException。读者成员在doOpen方法中设置。 它看起来没有调用doOpen。问题是为什么?
答案 0 :(得分:23)
当我将读者bean的返回类型从Item更改为FlatFileItemReader时,问题就消失了。我仍然不清楚为什么这是一个问题,因为chunk()。reader()接受ItemReader作为输入。我假设在引擎盖下有一些AOP魔法,它执行FlatFileReader初始化并匹配返回类型。
答案 1 :(得分:17)
由于您将阅读器放在StepScope
中,因此bean返回类型应该是实现类型FlatFileItemReader
:
@Bean
@StepScope
public FlatFileItemReader<Player> reader(@Value("#{jobParameters[inputZipfile]}") String inputZipfile) {
...
return reader;
}
如果指定接口,则Spring代理只能访问接口ItemReader
上指定的方法和注释,并且缺少重要的注释。日志中还有一个警告(带有拼写错误):
2015-05-07 10:40:22,733 WARN [main] org.springframework.batch.item.ItemReader is an interface. The implementing class will not be queried for annotation based listener configurations. If using @StepScope on a @Bean method, be sure to return the implementing class so listner annotations can be used.
2015-05-07 10:40:22,748 WARN [main] org.springframework.batch.item.ItemReader is an interface. The implementing class will not be queried for annotation based listener configurations. If using @StepScope on a @Bean method, be sure to return the implementing class so listner annotations can be used.
目前Spring Boot Batch示例也返回了ItemReader,所以我猜其他人也会遇到同样的问题。
答案 2 :(得分:9)
这是因为ItemReader没有open方法,使用hte StepScope将根据返回类型创建一个代理类。返回ItemStreamReader
也可以答案 3 :(得分:1)
我认为你应该在processPlayerStats()步骤bean类中增加你的块大小,即从chunk(10)到chunk(100 /更多)。
答案 4 :(得分:0)
这里的问题相同。 将我的阅读器的返回类型更改为真实的实现并添加到阅读器
implements ItemStream
我的诀窍
答案 5 :(得分:0)
我定义的方法如下:
@Bean
@StepScope
public ItemReader<BP> BPReader(){
JdbcCursorItemReader<BP> itemReader = new JdbcCursorItemReader<BP>();
...
return itemReader;
}
我在方法中定义的类型是ItemReader,它是一个接口,返回类型是JdbcCursorItemReader,它是它的子类。通过将返回类型定义更改为JdbcCursorItemReader,解决了我的问题
答案 6 :(得分:-1)
我已经通过以下方式解决了这个问题:
reader.open(new ExecutionContext());