I am attempting to create a simple Step for a batch process which takes ProductDetail information and other information from the item processor to create and write the new ProductResult to a Mongodb database. I am attempting to use a JdbcPagingItemReader for reading the data from a database. However, when I start the job it fails with an error
java.lang.NullPointerException: Cannot invoke “org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.getJdbcOperations()” because “this.namedParameterJdbcTemplate” is null. I also tested this with another reader and it works, so it is only the JdbcPagingItemReader that’s the issue.
I don’t know why the NamedParameterJdbcTemplate is needed since I have provided the select and from values and a configured row mapper.
Here is my code
import com.datacom.mapper.ProductDetailRowMapper;
import com.datacom.model.ProductDetail;
import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.data.MongoItemWriter;
import org.springframework.batch.item.data.builder.MongoItemWriterBuilder;
import org.springframework.batch.item.database.JdbcPagingItemReader;
import org.springframework.batch.item.database.Order;
import org.springframework.batch.item.database.support.OraclePagingQueryProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@RequiredArgsConstructor
public class ProductDetailConfigStep {
@Value("${db.pageSize}")
int pageSize;
final MongoOperations mongoOperations;
final @Qualifier("productsDataSource") DataSource dataSource;
final PlatformTransactionManager transactionManager;
final JobRepository jobRepository;
@Value("${batch.chunkSize}") int chunkSize;
final ProductResultProcessor productResultProcessor;
public ItemStreamReader<ProductDetail> itemReader() {
JdbcPagingItemReader<ProductDetail> itemReader = new JdbcPagingItemReader<>();
itemReader.setDataSource(productsDataSource);
itemReader.setFetchSize(chunkSize);
OraclePagingQueryProvider queryProvider = new OraclePagingQueryProvider();
queryProvider.setSelectClause(JDBCConstants.SELECT_QUERY);
queryProvider.setFromClause(JDBCConstants.FROM_CLAUSE_QUERY);
itemReader.setRowMapper(new ProductDetailRowMapper());
final Map<String, Order> sortKeys = new HashMap<>();
itemReader.setParameterValues(new HashMap<>());
sortKeys.put("product_id", Order.ASCENDING);
queryProvider.setSortKeys(sortKeys);
itemReader.setQueryProvider(queryProvider);
itemReader.setPageSize(pageSize);
itemReader.setPageSize(chunkSize);
return itemReader;
}
public ItemWriter<ProductResult> itemWriter() {
var writer = new MongoItemWriterBuilder<ProductResult>()
.collection(Documents.PRODUCT_CATALOG_COLLECTION)
.mode(MongoItemWriter.Mode.INSERT)
.template(mongoOperations)
.build();
writer.setTemplate(mongoOperations);
return writer;
}
@Bean("productProcessingDetailStep")
public Step productProcessingDetailStep() {
return new StepBuilder("productCreationStep", jobRepository)
.<ProductDetail, ProductResult>chunk(chunkSize, transactionManager)
.reader(itemReader())
.processor(productResultProcessor)
.writer(itemWriter())
.build();
}
}
What am I missing the configuration of the JdbcPagingItemReader looks fine to me.