'Get JobParameters on RepositoryItemReader

I have a problem with the execution of the batch process that I am developing. It comprises several steps.

The first one recovers data and inserts it into a table to keep track. So far, everything is correct. The problem is the next step, where the reader is a RepositoryItemReader and needs as a parameter the id of the job that has been assigned to it, not the one that is automatically generated by the ramework. I have seen several examples, which indicate that you can retrieve parameters with the @Value annotation.

If I assign @StepScope, the bean is not instantiated and an error is generated, but if I remove the annotation, the bean is instantiated correctly, but cannot find the property. I appreciate the help they can give me. I've been looking for a solution for several days, but I can't find it.

Thanks in advance!

Method

    private static JobResultDTO runJob(ApplicationContext context, String jobName, JobParameters jobParameters)
            throws DarwinException {
        LOGGER.info("Starting the batch job: {}", jobName);
        final JobLauncher jobLauncher = (JobLauncher) context.getBean("jobLauncher");
        final Job job = (Job) context.getBean(jobName);
        BatchStatus status = null;
        JobResultDTO jobResultDTO = null;
        try {
            // To enable multiple execution of a job with the same parameters
            JobParameters jobParams = new JobParametersBuilder()
                    .addJobParameters(jobParameters)
                    .toJobParameters();
            final JobExecution jobExecution = jobLauncher.run(job, jobParams);

            // Setting result
            jobResultDTO = settingJobResult(jobExecution, jobParameters);

            status = jobExecution.getStatus();
            LOGGER.info("Job Status : {}", status);

        } catch (final Exception e) {
            status = BatchStatus.FAILED;
            LOGGER.error("Job failed {}", e);
        }
        return jobResultDTO;
    }

Job process

@Component
public class JobMigrationProcess extends JobBase {
    static final Logger LOGGER = LoggerFactory.getLogger(JobMigrationProcess.class);
    @Value("${job.migration.concurrency.limit}")
    int concurrencyLimit;

    @Autowired
    JobBuilderFactory jobBuilderFactory;
    @Autowired
    StepBuilderFactory stepBuilderFactory;
    @Autowired
    DocumentStateTasklet documentStateTasklet;
    @Autowired
    SelectDocumentTasklet selectDocumentTasklet;
    @Autowired
    DocumentMigratorRepository documentMigratorRepository;

    @Bean(name = "JobMigrationProcess")
    public Job migrationProcessJob(Step selectionDocumentsStep, Step migrationSteps/*, Step updateDocumentStateStep*/) {

        Job job = jobBuilderFactory.get("jobMigrationProcess" + LocalDateTime.now())
                .incrementer(new RunIdIncrementer())
                .listener(protocolListener())
                .start(selectionDocumentsStep)
                .next(migrationSteps)
                .build();
        return job;
    }

    @Bean
//    @StepScope
    public Step selectionDocumentsStep(StepBuilderFactory stepBuilderFactory) {
        return stepBuilderFactory.get("step-select-documents")
                .tasklet(selectDocumentTasklet)
                .listener(logProcessListener())
                .build();
    }

    @Bean
//    @StepScope
    public Step updateDocumentStateStep(StepBuilderFactory stepBuilderFactory){
        return stepBuilderFactory.get("step-update-document-state")
            .tasklet(documentStateTasklet)
            .listener(logProcessListener())
            .build();
    }

    // MIGRATION STEP
    @Bean
//    @StepScope
    public Step migrationSteps(StepBuilderFactory stepBuilderFactory) {
        //String jobId = jobExecution.getJobParameters().getString("jobID");
        return stepBuilderFactory.get("step-migration-proc")
            .<DocumentMigrator, FilenetObjectVO>chunk(1000) //important to be one in this case to commit after every line read
            .reader(itemReaderMigration()).faultTolerant().skipPolicy(migrationSkipper())
            .processor(migrationProcessor())
            .writer(migrationWriter())
            .listener(logProcessListener())
            .faultTolerant()
            .build();
    }

    @Bean
//  @StepScope
    public SkipPolicy migrationSkipper() {
        return new DocumentMigrationSkipper();
    }

    @Bean
//  @StepScope
    public ItemProcessor<DocumentMigrator, FilenetObjectVO> migrationProcessor() {
        try {
            return new MigrationItemProcessor();
        } catch (Exception e) {
            LOGGER.error("Error on processor", e);
        }
        return null;
    }

    @Bean
//  @StepScope
    public RepositoryItemReader<DocumentMigrator> itemReaderMigration(/*@Value("#{jobParameters['jobID']}") String jobId*/) {
        List<Object> arguments = new ArrayList<>(0);
        //arguments.add(jobId);
        arguments.add("S");
        RepositoryItemReader<DocumentMigrator> reader = new RepositoryItemReader<>();
        reader.setRepository(documentMigratorRepository);
        reader.setMethodName("findByJobIdEqualsAndProcessEstateEquals");
        reader.setArguments(arguments);
        reader.setPageSize(1);
        reader.setSort(Collections.singletonMap("id", Sort.Direction.ASC));
        return reader;
    }

    @Bean
//  @StepScope
    public ItemWriter<FilenetObjectVO> migrationWriter() {
        try {
            return new MigrationItemWriter();
        } catch (Exception e) {
            LOGGER.error("Error on writer", e);
        }
        return null;
    }

}

This is the stack trace with the @Value enabled


org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'JobMigrationProcess' defined in class path resource [com/darwin/migrator/jobs/JobMigrationProcess.class]: Unsatisfied dependency expressed through method 'migrationProcessJob' parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'migrationSteps' defined in class path resource [com/darwin/migrator/jobs/JobMigrationProcess.class]: Unsatisfied dependency expressed through method 'migrationSteps' parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'itemReaderMigration' defined in class path resource [com/darwin/migrator/jobs/JobMigrationProcess.class]: Unsatisfied dependency expressed through method 'itemReaderMigration' parameter 0; 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?
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:769)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:509)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1321)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1160)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:847)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204)
    at com.darwin.migrator.DarwinMigratorApplication.main(DarwinMigratorApplication.java:89)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'migrationSteps' defined in class path resource [com/darwin/migrator/jobs/JobMigrationProcess.class]: Unsatisfied dependency expressed through method 'migrationSteps' parameter 1; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'itemReaderMigration' defined in class path resource [com/darwin/migrator/jobs/JobMigrationProcess.class]: Unsatisfied dependency expressed through method 'itemReaderMigration' parameter 0; 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?
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:769)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:509)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1321)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1160)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1255)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1175)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
    ... 18 common frames omitted
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'itemReaderMigration' defined in class path resource [com/darwin/migrator/jobs/JobMigrationProcess.class]: Unsatisfied dependency expressed through method 'itemReaderMigration' parameter 0; 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?
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:769)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:509)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1321)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1160)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:277)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1255)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1175)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
    ... 32 common frames omitted
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?
    at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:164)
    at org.springframework.beans.factory.support.AbstractBeanFactory.evaluateBeanDefinitionString(AbstractBeanFactory.java:1481)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1175)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:857)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:760)
    ... 46 common frames omitted
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?
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:217)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
    at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:91)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueRef(CompoundExpression.java:53)
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:89)
    at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:109)
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:265)
    at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:161)
    ... 51 common frames omitted



Solution 1:[1]

I've managed to use jobParameter as an argument to my RepositoryItemReader by extending it :


public class EntityReader extends RepositoryItemReader<Entity> {

  @Value("#{jobParameters['lastSync']}")
  private Date lastSync;

  @Autowired
  private EntityRepository EntityRepository;

  @Override
  public void afterPropertiesSet() throws Exception {
    setName(getClass().getSimpleName());
    setRepository(entityRepository);
    setMethodName("findAllSince");
    setArguments(List.of(lastSync.toInstant()
                                 .atZone(ZoneId.systemDefault())
                                 .toLocalDateTime()));
    setPageSize(10);
    setSort(Collections.singletonMap("modifiedDate", Sort.Direction.ASC));
    setSaveState(true);
    super.afterPropertiesSet();
  }
}

and using it as a bean annotated with @StepScope

  @Bean
  public Step jobStep() {
    return stepBuilderFactory.get("step-entity-sync")
                             .<Entity, TagetEntity>chunk(10)
                             .reader(entityReader())
                             .processor(...)
                             .writer(...)
                             .build();
  }

  @Bean
  @StepScope
  public EntityReader entityReader() {
    return new EntityReader();
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Manuel Eveno