'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 |