【问题标题】:Custom ItemReader with spring-data-jpa使用 spring-data-jpa 自定义 ItemReader
【发布时间】:2016-09-10 11:38:47
【问题描述】:

我正在使用现有实体和存储库创建一个 Spring 批处理项目。对于使用现有 jpa 存储库读取数据的作业,我需要使用自定义 ItemReader。

自定义阅读器

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;
    }
}

但我无法在itemreader 中自动连接ProductService。报错如下:

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

批处理配置文件

@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();
    }
}

产品服务实现

@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;
    }
}

【问题讨论】:

  • 什么是null,productService?你是如何创建 InMemoryReader 的?

标签: java spring-boot spring-batch spring-data-jpa


【解决方案1】:

您正在从构造函数调用initialize(),即在ProductService 依赖项被连接之前。

从构造函数中移除对 initialize() 的调用,而是让 Spring 在连接依赖项后调用它,方法是使用 @PostConstruct 注释它或使用此处概述的其他方法之一:

How to call a method after bean initialization is complete?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 2015-03-25
    • 2018-10-06
    • 1970-01-01
    • 2015-12-07
    • 2012-09-13
    相关资源
    最近更新 更多