Cannot autowired beans when separate configuration classes

懵懂的女人 提交于 2019-12-11 15:25:04

问题


I have a JavaConfig configurated Spring Batch job. The main job configuration file is CrawlerJobConfiguration. Before now, I have all the configuration (infrastructure, autowired beans, etc) in this class and it works fine. So I decided to separate the job configuration from autowired beans and infracstruture beans configuration and create another 2 configuration classes Beans and MysqlInfrastructureConfiguration.

But now I am having problems to run my job. I'm receiving a NullPointerException when the application try to use autowired fields indicating that the autowired is not working.

I put a breakpoint in the methods that create autowired beans to make sure that they are being called and really are, so I cannot realize what can be the problem.

java.lang.NullPointerException: null
    at br.com.alexpfx.supermarket.batch.tasklet.StartCrawlerTasklet.execute(StartCrawlerTasklet.java:27) ~[classes/:na]
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406) ~[spring-batch-core-3.0.6.RELEASE.jar:3.0.6.RELEASE]

Main job configuration class:

@Configuration
@EnableBatchProcessing
public class CrawlerJobConfiguration {


    @Autowired
    private InfrastructureConfiguration infrastructureConfiguration;

    @Autowired
    private StepBuilderFactory steps;
    @Autowired
    Environment environment;


    @Bean
    public Job job(JobBuilderFactory jobs) {
        Job theJob = jobs.get("job").start(crawlerStep()).next(processProductStep()).build();
        ((AbstractJob) theJob).setRestartable(true);
        return theJob;

    }

    @Bean
    public Step crawlerStep() {
        TaskletStep crawlerStep = steps.get("crawlerStep").tasklet(crawlerTasklet()).build();
        crawlerStep.setAllowStartIfComplete(true);
        return crawlerStep;
    }

    @Bean
    public Step processProductStep() {
        TaskletStep processProductStep = steps.get("processProductStep")
                .<TransferObject, Product>chunk(10)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .build();
        processProductStep.setAllowStartIfComplete(true);
        return processProductStep;
    }

    private Tasklet crawlerTasklet() {
        return new StartCrawlerTasklet();
    }

    private ItemProcessor<TransferObject, Product> processor() {
        return new ProductProcessor();
    }

    private ItemReader<TransferObject> reader() {
        return new ProductItemReader();
    }

    private ItemWriter<Product> writer() {
        return new HibernateProductsItemWriter();
    }        
}

Beans configuration class:

@Configuration
@EnableBatchProcessing
public class Beans {

    @Bean
    public Crawler crawler() {
        return new RibeiraoCrawler(new UserAgentFactory());
    }

    @Bean
    public ProductBo productBo() {
        return new ProductBoImpl();
    }

    @Bean
    public ProductDao productDao() {
        return new ProductDaoImpl();
    }


    @Bean
    public CrawlerListener listener() {
        CrawlerListener listener = new RibeiraoListener();
        return listener;
    }

    @Bean
    public ProductList getProductList() {
        return new ProductList();
    }


}

MysqlInfrastructureConfiguration:

@Configuration
@EnableBatchProcessing
@PropertySource("classpath:database.properties")
@EnableJpaRepositories(basePackages = {"br.com.alexpfx.supermarket.domain"})
public class MysqlInfrastructureConfiguration implements InfrastructureConfiguration {

    @Value("${jdbc.url}")
    String url;

    @Value("${jdbc.driverClassName}")
    String driverClassName;

    @Value("${jdbc.username}")
    String username;

    @Value("${jdbc.password}")
    String password;

    @Bean
    @Override
    public DataSource getDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }


    @Bean
    @Override
    public PlatformTransactionManager transactionManager() {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(entityManagerFactory());
        transactionManager.setDataSource(getDataSource());
        return transactionManager;
    }

    @Bean
    @Override
    public EntityManagerFactory entityManagerFactory() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(getDataSource());
        em.setPackagesToScan(new String[]{"br.com.alexpfx.supermarket.domain"});

        JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        em.setJpaProperties(additionalJpaProperties());
        em.afterPropertiesSet();
        return em.getObject();
    }

    private Properties additionalJpaProperties() {
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "create");
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
        properties.setProperty("hibernate.show_sql", "true");
        properties.setProperty("current_session_context_class", "thread");
        return properties;
    }


}

tasklet:

public class StartCrawlerTasklet implements Tasklet {

    @Autowired
    private Crawler crawler;

    @Autowired
    private CrawlerListener listener;

    @Override
    public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
        crawler.setListener(listener);
        crawler.setStopCondition(new TimeLimitStopCondition(1, TimeUnit.MINUTES));
        crawler.crawl();
        return RepeatStatus.FINISHED;
    }

}

回答1:


StartCrawlerTasklet use the autowired annotation, so it should be a bean as well. So change your code :

private Tasklet crawlerTasklet() {
    return new StartCrawlerTasklet();
}

to a bean definition:

@Bean
public Tasklet crawlerTasklet() {
    return new StartCrawlerTasklet();
}


来源:https://stackoverflow.com/questions/34779838/cannot-autowired-beans-when-separate-configuration-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!