spring-bootspring-batchspring-jdbcitemrenderer

Spring batch - org.springframework.batch.item.ReaderNotOpenException - jdbccursoritemreader


I get the reader not open exception when tried to read JdbcCursorItemReader in the Item Reader implementation. I checked the stack overflow, but couldnt get a discussion on jdbc item reader.

Here is the code of Batch config and Item reader implementation. Added only required code.

    public class BatchConfig extends DefaultBatchConfigurer {
@Bean
public ItemReader<Allocation> allocationReader() {
return new AllocationReader(dataSource);
}
@Bean
public Step step() {
return stepBuilderFactory.get("step").<Allocation, Allocation>chunk (1).reader(allocationReader()).processor(allocationProcessor()).writer(allocationWriter()).build();
}
}




    public class AllocationReader implements ItemReader<Allocation> {
private DataSource ds;
private string block;
public AllocationReader(DataSource ds) {
this.ds = ds;
}
@BeforeStep
public void readStep(StepExecution StepExecution) {
this.stepExecution = StepExecution;
block = StepExecution.getJobExecution().get ExecutionContext().get("blocks");
}
@Override
public Allocation read() {
JdbcCursorItemReader<Allocation> reader = new JdbcCursorItemReader<Allocation>();
reader.setSql("select * from blocks where block_ref = + block);
reader.setDataSource(this.ds);
reader.setRowMapper(new AllocationMapper());
return reader.read();
}}

I could not write Item reader as bean in batch config as i need to call before step in item reader to access stepexecution.

If the Item reader read() function return type is changed to jdbccursorItemReader type, it throws type exception in Step reader() .

Let me know what am i missing or any other code snippet is required .


Solution

  • You are creating a JdbcCursorItemReader instance in the read method of AllocationReader. This is not correct. The code of this method should be the implementation of the actual read operation, and not for creating an item reader.

    I could not write Item reader as bean in batch config as i need to call before step in item reader to access step execution.

    For this use case, you can define the reader as a step-scoped bean and inject attributes from the job execution context as needed. This is explained in the reference documentation here: Late Binding of Job and Step Attributes. In your case, the reader could be defined like this:

    @Bean
    @StepScoped
    public JdbcCursorItemReader<Allocation> itemReader(@Value("#{jobExecutionContext['block']}") String block) {
       // use "block" as needed to define the reader
       JdbcCursorItemReader<Allocation> reader = new JdbcCursorItemReader<Allocation>();
       reader.setSql("select * from blocks where block_ref = " + block);
       reader.setDataSource(this.ds);
       reader.setRowMapper(new AllocationMapper());
       return reader;
    }
    

    When you define an item reader bean that is an ItemStream, you need to make the bean definition method return at least ItemStreamReader (or the actual implementation type), so that Spring Batch correctly scopes the bean and calls open/update/close appropriately during the step. Otherwise, the open method will not be called and therefore you will get that ReaderNotOpenException.