Параметры пакетного задания Spring не работают в конфигурации java

Я пытаюсь запустить пакетное задание, в котором хочу сделать свой SQL-запрос динамическим. Но я получаю исключение при создании кода «Свойство или поле 'jobParameters' не может быть найдено в объекте типа 'org.springframework.beans.factory.config.BeanExpressionContext' - возможно, не общедоступный или недопустимый?». Ниже приведены фрагменты кода и трассировка исключения для него.

BatchConfig

@Configuration
@EnableBatchProcessing
public class StoreSalesBatchConfiguration {

@Autowired
@Qualifier("jobBuilderFactory")
private JobBuilderFactory jobBuilderFactory;

@Autowired
@Qualifier("stepBuilderFactory")
private StepBuilderFactory stepBuilderFactory;

@Autowired
@Qualifier("jobCompletionNotificationListener")
private JobCompletionNotificationListener jobCompletionNotificationListener;

@Autowired
@Qualifier("jobLauncher")
private JobLauncher jobLauncher;

@Autowired
@Qualifier("storeSalesJob")
private Job storeSalesJob;

@Autowired
private GameStoreSalesRepository storeSalesRepository;  

@Bean
@StepScope
ItemReader<GameStoreSales> gameStoreSalesReader(@Qualifier("gdwMpsBatch") final DataSource dataSource,
        @Value("#{jobParameters[maxDate]}") String maxDate) {
    JdbcCursorItemReader<GameStoreSales> databaseReader = new JdbcCursorItemReader<>();
    databaseReader.setDataSource(dataSource);
    databaseReader.setSql(CommonConstants.STORE_SALES_QUERY);
    databaseReader.setPreparedStatementSetter(new PreparedStatementSetter() {

        @Override
        public void setValues(PreparedStatement ps) throws SQLException {
            ps.setString(1, maxDate);
        }
    });
    databaseReader.setRowMapper(new BeanPropertyRowMapper<>(GameStoreSales.class));
    return databaseReader;
}

@Bean
public GameStoreSalesProcessor gameStoreSalesProcessor() {
    return new GameStoreSalesProcessor();
}

@Bean
public ItemWriter<GameStoreSales> gameStoreSalesWriter() throws Exception {
    return new GameStoreSalesWriter();
}

@Bean
public Step gameStoreSalesStep(@Qualifier("gdwMpsBatch") final DataSource dataSource,
                            @Value("#{jobParameters[maxDate]}") String maxDate) throws Exception {
    return stepBuilderFactory.get("gameStoreSalesStep").<GameStoreSales, GameStoreSales>chunk(1000)
            .reader(gameStoreSalesReader(dataSource,maxDate)).processor(gameStoreSalesProcessor()).writer(gameStoreSalesWriter()).build();
}

@Bean(name = "storeSalesJob")
public Job storeSalesJob(Step gameStoreSalesStep) {
    return jobBuilderFactory.get("storeSalesJob").incrementer(new RunIdIncrementer())
            .listener(jobCompletionNotificationListener).flow(gameStoreSalesStep).end().build();
}

@Scheduled(cron = "*/30 * * * * *")
public void runStoreSalesJob() throws JobExecutionAlreadyRunningException, JobRestartException,
        JobInstanceAlreadyCompleteException, JobParametersInvalidException {
    String dateParam = new Date().toString();
    String maxDate = storeSalesRepository.getMaxCalDate();
    JobParameters param = new JobParametersBuilder().addString("date", dateParam)
                                                    .addString("maxDate", weekEnd)
                                                    .toJobParameters();
    try{
        jobLauncher.run(storeSalesJob, param);
    } catch(Exception e){
        e.printStackTrace();
    }
}
}

Исключительная трассировка:

java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'storeSalesBatchConfiguration': Unsatisfied dependency expressed through field 'storeSalesJob'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'storeSalesJob' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'storeSalesJob' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gameStoreSalesStep' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'gameStoreSalesStep' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'storeSalesJob' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'storeSalesJob' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gameStoreSalesStep' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'gameStoreSalesStep' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?

Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'gameStoreSalesStep' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'gameStoreSalesStep' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?

Caused by: org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is 

org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?

Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?

Пожалуйста, укажите, почему параметры задания не распознаются и где происходит сбой в конфигурации.

Вы пробовали добавлять простые кавычки вокруг имени параметра? Нравится: @Value("#{jobParameters['maxDate']}")

Mahmoud Ben Hassine 06.07.2018 14:57

Да. Но я пока получаю такое же исключение. Кажется, он вообще не распознает параметры задания.

Sonam Bhardwaj 13.07.2018 11:04

Синтаксис, который я дал в моем предыдущем комментарии, правильный. Подробнее см. Здесь: docs.spring.io/spring-batch/4.0.x/reference/html/… Ваш bean-компонент снабжен аннотацией @StepScope. Это правильно. Я не вижу проблем с вашим кодом. Почему метод gameStoreSalesReader вашего компонента чтения элементов не является общедоступным? Вы пытались сделать это публичным, как и другие?

Mahmoud Ben Hassine 13.07.2018 11:27

@SonamBhardwaj Вы нашли корень проблемы? или возможное решение? Я столкнулся с той же проблемой.

Abhinandan Madaan 05.10.2020 10:45
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
2 421
1

Ответы 1

Объект Spring Batch StepScope - это объект, который уникален для определенного шага, а не для одного элемента. Как вы, наверное, знаете, область видимости bean-компонента в Spring по умолчанию - singleton. Но указание StepScope для компонента Spring Batch означает, что Spring Batch будет использовать контейнер Spring для создания нового экземпляра этого компонента для каждого выполнения шага.

Это часто полезно для выполнения позднего связывания параметра, когда параметр может быть указан либо на уровне StepContext, либо на уровне JobExecutionContext, и его необходимо заменить на заполнитель, как и в вашем примере с требованием имени файла.

Еще одна полезная причина для использования StepScope - это когда вы решили повторно использовать один и тот же компонент в параллельных шагах. Если компонент управляет каким-либо внутренним состоянием, важно, чтобы он был основан на StepScope, чтобы один поток не ухудшал состояние, управляемое другим потоком (например, каждый поток данного шага имеет свой собственный экземпляр компонента StepScope).

Попробуйте аннотировать с помощью StepScope:

    @Bean
    @StepScope
    public Step gameStoreSalesStep(@Qualifier("gdwMpsBatch") final DataSource dataSource,
                                @Value("#{jobParameters[maxDate]}") String maxDate) throws Exception {
        return stepBuilderFactory.get("gameStoreSalesStep").<GameStoreSales, GameStoreSales>chunk(1000)
                .reader(gameStoreSalesReader(dataSource,maxDate)).processor(gameStoreSalesProcessor()).writer(gameStoreSalesWriter()).build();
    }

Другие вопросы по теме