1

I need to create itemReader bean with parameters, that I defined in BeforeStep listener. It's necessary, because I need to set SQL and SQL parameters values. After running my app I'am getting exception:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.mappingReaderConfig': Scope 'step' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No context holder available for step scope

How I need to rewrite my code to avoid it? This is the example of my bean:

@Configuration
@StepScope
public class MappingReaderConfig {

private final DataSource ds;

@Autowired
public MappingReaderConfig(DataSource ds) {
    this.ds = ds;
}

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

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

@Value("#{jobExecutionContext['myProcessData']}")
private MyProcessData myProcessData;

@Value("#{jobParameters['PROCESS_ID']}")
private Long processId;

@Bean
@SuppressWarnings("unchecked")
public ItemReader<MapRowByMap> mappingItemReader() {
    return new JdbcCursorItemReaderBuilder<>()
            .dataSource(ds)
            .sql(myProcessData.getCursor())
            .verifyCursorPosition(true)
            .preparedStatementSetter(ps -> {
                ps.setDate(1, Date.valueOf(LocalDate.parse(startDate)));
                ps.setDate(2, Date.valueOf(LocalDate.parse(endDate)));
            })
            .rowMapper((RowMapper) (rs, rowNum) -> {
                MapRowByMap res = new MapRowByMap();
                ResultSetMetaData md = rs.getMetaData();
                int columns = md.getColumnCount();
                for(int i=1; i<=columns; ++i) {
                    MapColumn mapColumn = new MapColumn(md.getColumnName(i), rs.getObject(i));
                    res.getRowColumns().put(md.getColumnName(i),mapColumn);
                }
                return res;
            }).name(processId.toString()).build();
}
}
nm10
  • 61
  • 3
  • 1
    Your bean needs to be step or job scoped (as the error also indicates). You are currently working with a singleton if you want to do late binding make it `@StepScope` or `@JobScope` . Currently your config is step scoped, but not the bean it creates!. SO move the scope to the bean method. – M. Deinum Nov 07 '19 at 12:01
  • Thanks a lot M. Deinum, now it works. I also changed the return type of my bean to ItemStreamReader, as it mentioned at: https://stackoverflow.com/questions/23847661/spring-batch-org-springframework-batch-item-readernotopenexception-reader-must I made it because I got "Reader must be open before it can be read." – nm10 Nov 07 '19 at 12:28
  • For `@Bean` methods try to be as specific as possible in your return type so use `JdbcCursorItemReaderBuilder`. This has to do with how `@Configuration` classes and its `@Bean` methods are processed (at that time there is no instance and callbacks are determined based on info from bytecode). – M. Deinum Nov 07 '19 at 12:30

0 Answers0