我有一个JavaConfig可配置的Spring Batch作业。主作业配置文件是CrawlerJobConfiguration。在此之前,我在此类中拥有所有配置(基础结构,自动装配的bean等),并且它可以正常工作。所以我决定将作业配置与autowired beans和infracstruture beans配置分开,并创建另外两个配置类Beans和MysqlInfrastructureConfiguration。
但是现在我的工作遇到了问题。当应用程序尝试使用指示自动装配不起作用的自动装配字段时,我收到NullPointerException。
我在创建自动装配的bean的方法中放置了一个断点,以确保它们被调用并且确实是,所以我无法意识到可能存在的问题。
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]
主要工作配置类:
@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
@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;
}
}
微进程:
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;
}
}
答案 0 :(得分:1)
StartCrawlerTasklet使用autowired
注释,因此它也应该是一个bean。所以改变你的代码:
private Tasklet crawlerTasklet() {
return new StartCrawlerTasklet();
}
到bean定义:
@Bean
public Tasklet crawlerTasklet() {
return new StartCrawlerTasklet();
}