javaspringspring-bootspring-batchspring-batch-admin

How to access JobParameters in Spring Batch ItemReader?


I am trying to access job parameters in an ItemReader as shown below, but when trying some the value cannot be passed or I get some errors e.g.

"Failed to initialize the reader: Cannot determine collection name from type 'org.bson.Document'. Is it a store native type?"

or

"Error while closing item reader. Cannot invoke "org.springframework.data.util.CloseableIterator.close()" because "this.cursor" is null"


In order to pass jobParameters to ItemReader, I am using StepExecution as shown below, but as constructor of CustomDataReader is executed before the beforeStep method, I get error on setCollection(collectionName) line. So, how to fix it?

@Getter
@Setter
@StepScope
@Component
public class CustomDataReader extends MongoCursorItemReader<Document> {

    @Value("#{jobParameters['collectionName']}")
    private String collectionName;

    @BeforeStep
    public void beforeStep(final StepExecution stepExecution) {
        JobParameters jobParameters = 
stepExecution.getJobParameters();        
        setCollectionName(parameters.getParameter("collectionName")
            .getValue().toString());
    }

    // @Autowired
    public CustomDataReader(
            @Qualifier("mongoTemplate") MongoTemplate mongoTemplate
    ) {
        setName("customDataReader");
        setTargetType(Document.class);
        setTemplate(mongoTemplate);
        setCollection(collectionName);
        setBatchSize(DEFAULT_CHUNK_SIZE);
        setLimit(DEFAULT_LIMIT_SIZE);
        setQuery(query);
    }

}

I am looking for a solution without using these job parameters in BatchConfig and only modifying this reader.


Solution

  • @StepScope is used on any @Bean that needs to inject @Values from the step context and on any bean that needs to share a lifecycle with a step execution. https://docs.spring.io/spring-batch/docs/current/api/org/springframework/batch/core/configuration/annotation/StepScope.html

    Here is the code without @StepScope and setting the default query.

    @Component
    public class CustomDataReader extends MongoCursorItemReader<Document> {
    
        @BeforeStep
        public void beforeStep(final StepExecution stepExecution) {
            JobParameters jobParameters = stepExecution.getJobParameters();
            setCollection(jobParameters.getString("collectionName"));
        }
    
        public CustomDataReader(@Autowired MongoTemplate mongoTemplate) {
    
            setName("reader");
            setTargetType(Document.class);
            setTemplate(mongoTemplate);
            setBatchSize(DEFAULT_CHUNK_SIZE);
            setLimit(DEFAULT_LIMIT_SIZE);
            setSort(new HashMap<>());
            setQuery(new Query());
        }
    
    }