I am new to Spring Batch and trying my hands on to get gain some knowledge on this. I have written the following method to read data from a table but I am getting an exception telling "The SQL query must be provided" although I have provided the query in the method.
@Configuration
public class ReadingObjectItemReader extends JdbcCursorItemReader<Person> {
public DataSource getDataSource() { return dataSource; }
@Resource
public void setDataSource(DataSource dataSource) { super.setDataSource(dataSource); }
@Autowired
DataSource dataSource;
@Bean
public JdbcCursorItemReader<DimInstitutionalClaim> cursorReader() {
JdbcCursorItemReader<Person> databaseReader = new JdbcCursorItemReader<>();
databaseReader.setDataSource(dataSource);
databaseReader.setSql("select TOP(10) * from dbo.Person ");
databaseReader.setFetchSize(5);
databaseReader.setRowMapper(new BeanPropertyRowMapper<>(Person.class));
return databaseReader;
}
}
and on the Step I am calling it like this:
@Autowired
ReadingObjectItemReader readingObject;
@Bean
public Step step1() {
return stepBuilderFactory.get("step1").<Person,Person>chunk(2).reader(readingObject.cursorReader())
.writer(itemWriter()).listener(promotionListener()).build();
}
when running the above code in my step InputReader I am getting
Caused by: java.lang.IllegalArgumentException: The SQL query must be provided
If I write the above logic in the same class where my job builder and steps are defined and without extending JdbcCursorItemReader like my code below it is working fine.
@Bean
public Step step1() {
return stepBuilderFactory.get("step1").<Person, Person>chunk(2).reader(itemReader())
.writer(itemWriter()).listener(promotionListener()).build();
}
@Bean
public ItemReader<Person> itemReader() {
JdbcCursorItemReader<Person> databaseReader = new JdbcCursorItemReader<>();
databaseReader.setDataSource(dataSource);
databaseReader.setSql("select TOP(10) * from dbo.Person ");
databaseReader.setFetchSize(5);
databaseReader.setRowMapper(new BeanPropertyRowMapper<>(Person.class));
return databaseReader;
}
Can some one suggest me what is wrong with my implementation when defining it in a new class and extending it with JdbcCursorItemReader and also is there any other way that I can use JPA queries like findAll() and JPQL on InputReader other than PaginationReaders?
When Spring tries to inject this:
@Autowired
ReadingObjectItemReader readingObject;
It sees that ReadingObjectItemReader
implements InitializingBean
and calls afterPropertiesSet
. In this method, there is a check that validates the sql query is provided but it is not the case, and this happen before even arriving to reader(readingObject.cursorReader())
.
Creating a configuration class that extends JdbcCursorItemReader
is not correct. A configuration class is used to declare bean definitions. You actually don't need this class, you can declare the reader bean next to your step definition and inject it in the step:
@Bean
public JdbcCursorItemReader<DimInstitutionalClaim> cursorReader() {
JdbcCursorItemReader<Person> databaseReader = new JdbcCursorItemReader<>();
databaseReader.setDataSource(dataSource);
databaseReader.setSql("select TOP(10) * from dbo.Person ");
databaseReader.setFetchSize(5);
databaseReader.setRowMapper(new BeanPropertyRowMapper<>(Person.class));
return databaseReader;
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1").<Person, Person>chunk(2)
.reader(cursorReader())
.writer(itemWriter())
.listener(promotionListener())
.build();
}