I'm creating a Spring batch project using existing entities and repositories. I need to use custom ItemReader
for the job which reads data using the existing jpa repositories.
Custom reader
public class InMemoryReader implements ItemReader<Product> {
@Autowired
private ProductService productService;
private int nextStudentIndex;
private List<Product> studentData;
public InMemoryReader() {
initialize();
}
private void initialize() {
studentData = new ArrayList<Product>();
studentData.add(new Product("hi"));
for (Product p : productService.get())
studentData.add(p);
nextStudentIndex = 0;
}
@Override
public Product read() throws Exception {
Product nextStudent = null;
if (nextStudentIndex < studentData.size()) {
nextStudent = studentData.get(nextStudentIndex);
nextStudentIndex++;
}
return nextStudent;
}
}
But I can't Autowire the ProductService
in the itemreader
. It throwing error as follows:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'reader' defined in class path resource [wariyum/sb/emailNotifier/BatchConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'reader' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:599)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1123)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1018)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:689)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:969)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:958)
at wariyum.sb.emailNotifier.Application.main(Application.java:15)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.batch.item.ItemReader]: Factory method 'reader' threw exception; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:189)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:588)
... 16 common frames omitted
Caused by: java.lang.NullPointerException: null
at wariyum.sb.emailNotifier.service.InMemoryReader.initialize(InMemoryReader.java:31)
at wariyum.sb.emailNotifier.service.InMemoryReader.<init>(InMemoryReader.java:24)
at wariyum.sb.emailNotifier.BatchConfiguration.reader(BatchConfiguration.java:41)
at wariyum.sb.emailNotifier.BatchConfiguration$$EnhancerBySpringCGLIB$$df186b4e.CGLIB$reader$0(<generated>)
at wariyum.sb.emailNotifier.BatchConfiguration$$EnhancerBySpringCGLIB$$df186b4e$$FastClassBySpringCGLIB$$724d6a16.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:318)
at wariyum.sb.emailNotifier.BatchConfiguration$$EnhancerBySpringCGLIB$$df186b4e.reader(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 17 common frames omitted
Batch configuration file
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
@Autowired
public JobBuilderFactory jobBuilderFactory;
@Autowired
private DataSource dataSource;
@Autowired
public StepBuilderFactory stepBuilderFactory;
@Bean
public ItemReader<Product> reader() throws Exception {
return new InMemoryReader();
}
@Bean
public ProductItemProcessor processor() {
return new ProductItemProcessor();
}
@Bean
public ItemWriter<Product> writer() {
return new ItemWriter<Product>() {
@Override
public void write(List<? extends Product> items) throws Exception {
}
};
}
// end::readerwriterprocessor[]
// tag::listener[]
@Bean
public JobExecutionListener listener() {
return null;
}
// end::listener[]
// tag::jobstep[]
@Bean
public Job importPerson(JobBuilderFactory jobs, Step s1) {
return jobs.get("import")
.incrementer(new RunIdIncrementer()) // because a spring config bug, this incrementer is not really useful
.flow(s1)
.end()
.build();
}
@Bean
public Step step1() throws Exception {
return stepBuilderFactory.get("step1")
.<Product, Product>chunk(10)
.reader(reader())
.processor(processor())
.writer(writer())
.build();
}
}
Product service implementation
@Service("productService")
public class ProductServiceImpl implements ProductService {
private ProductRepository repository;
@Autowired
public ProductServiceImpl(ProductRepository repository) {
this.repository = repository;
}
@Override
public List<Product> get() {
List<Product> list = new ArrayList<Product>();
for (Product p : repository.findAll())
list.add(p);
return list;
}
}
You are calling initialize()
from the constructor ie before the ProductService
dependency has been wired.
Remove the call to initialize()
from the constructor and instead have Spring invoke it after the dependencies have been wired by annotating it with @PostConstruct
or using one of the other methods outlined here:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.