Spring Пакет: org.springframework.batch.item.ReaderNotOpenException: Reader должен быть открыт, прежде чем его можно будет прочитать

Я прочитал связанные вопросы, но решения для меня не работают.

Я получаю исключение 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, и ReaderNotOpenException возникает, когда член читателя класса читателя не установлен. Элемент чтения установлен в doOpen. Похоже, doOpen не вызван. Вопрос в том, почему?

Ответ 1

Проблема исчезла, когда я изменил возвращаемый тип моего читателя bean с Item на FlatFileItemReader. Мне все еще не ясно, почему это проблема, поскольку chunk(). Reader() принимает ItemReader в качестве входа. Я предполагаю, что под капотом есть какая-то AOP-магия, которая делает FlatFileReader init и соответствует типу return.

Ответ 2

Поскольку вы помещаете читателя в 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 также возвращает ItemReader, поэтому я думаю, что другие люди будут бороться с теми же проблемами.

Ответ 3

Это потому, что ItemReader не имеет открытого метода, используя hte. StepScope создаст прокси-класс на основе типа возврата. Также нормально возвращать ItemStreamReader

Ответ 4

Я думаю, вы должны увеличить размер вашего куска в processPlayerStats() step bean class, т.е. из chunk (10) в chunk (может быть 100 и более).

Ответ 5

Такая же проблема. Изменение возвращаемого типа моего читателя на реальную реализацию и добавление к читателю

implements ItemStream

Сделал трюк для меня

Ответ 6

Метод, который я определил, выглядит следующим образом:

    @Bean
    @StepScope
    public ItemReader<BP> BPReader(){
       
        JdbcCursorItemReader<BP> itemReader = new JdbcCursorItemReader<BP>();
        ...
        return itemReader;
    }

Ответ 7

Я исправил это:

reader.open(new ExecutionContext());