无法在Spring Batch Tasklet中使用@PersistenceContext创建自定义存储库的@Bean?

时间:2018-08-11 17:14:21

标签: spring spring-boot spring-batch

我已经浏览了链接:Can we use @Autowired in a Tasklet in Spring Batch?,但仍然面临以下问题:

我所有的批处理作业都是基于xml的,似乎无法使用CustMstrCustomRepositoryTasklet bean自动连接到@PersistentContext

ABCDataTasklet.java

@Configuration
@Data
public class ABCDataTasklet implements Tasklet {

    @Autowired
    private CustMstrCustomRepository custMstrCustomRepository;

    @Override
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
        List<ABCCustomClass> result = custMstrCustomRepository.getData();

        chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext()
                .put("data", result);

        return RepeatStatus.FINISHED;
    }
}

错误

java.lang.NullPointerException: null
    at com.XXX.XXX.batch.tasklet.ABCDataTasklet.execute(ABCDataTasklet.java:29) ~[classes/:na]
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:272) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:81) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:375) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:145) ~[spring-batch-infrastructure-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:200) ~[spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:66) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:136) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:308) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:141) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) [spring-core-5.0.8.RELEASE.jar:5.0.8.RELEASE]
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:134) [spring-batch-core-4.0.1.RELEASE.jar:4.0.1.RELEASE]
    at com.XXX.jobLauncherService.BillingBatchJobLauncher.executeBillingJob(BillingBatchJobLauncher.java:30) [classes/:na]
    at com.mastercard.jpaApplication.run(jpaApplication.java:26) [classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:800) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:784) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1258) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
    at com.mastercard.jpaApplication.main(jpaApplication.java:21) [classes/:na]

2018-08-11 22:33:51.756  INFO 1808 --- [           main] o.s.b.c.l.support.SimpleJobLauncher      : Job: [FlowJob: [name=ABCDataBatchJob]] completed with the following parameters: [{runMode=YYYY, date=1534007031631, time=1534007031631}] and the following status: [FAILED]
2018-08-11 22:33:51.757  INFO 1808 --- [       Thread-5] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@5bfa9431: startup date [Sat Aug 11 22:33:40 IST 2018]; root of context hierarchy
2018-08-11 22:33:51.758  INFO 1808 --- [       Thread-5] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2018-08-11 22:33:51.759  INFO 1808 --- [       Thread-5] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans
2018-08-11 22:33:51.762  INFO 1808 --- [       Thread-5] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'devcloud'
2018-08-11 22:33:51.763  INFO 1808 --- [       Thread-5] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2018-08-11 22:33:53.923  INFO 1808 --- [       Thread-5] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

CustMstrCustomRepositoryImpl.java

@Service
@Transactional(readOnly = true)
public class CustMstrCustomRepositoryImpl implements CustMstrCustomRepository {
    private static final String SQL = "COMPLEX SQL QUERY";

    @PersistenceContext
    @Qualifier(value = "entityManagerFactory")
    private EntityManager entityManager;

    @SuppressWarnings("unchecked")
    @Override
    public List<ABCCustomClass> getData() {
        Query q = entityManager.createNativeQuery(SQL);
        q.setParameter("actv_sw", "Y");

        List<Object[]> resultList = q.getResultList();

        List<ABCCustomClass> results = new ArrayList<>();
        for (Object[] objects : resultList) {
            results.add(ABCCustomClass.builder()
                    .YY((BigDecimal) objects[0])
                    .YY((BigDecimal) objects[1])
                    .YY((Date) objects[2])
                    .YY((Date) objects[3])
                    .YY((String) objects[4]).build());           
        }
        return results;
    }
}

2 个答案:

答案 0 :(得分:0)

您可以确认是否在扫描用于创建Bean的程序包下定义了自定义存储库吗?

通常,这是作为Application.java的一部分给出的配置

据我所知,自动装配返回空值的问题可能是因为spring无法扫描该类。

答案 1 :(得分:0)

我能够通过使用@PostContruct注释解决此问题,并在@Configuration类的逻辑下面添加了

现在使用这种方式,我现在可以轻松地通过@EntityManager

@Configuration
@ComponentScan("com.XXXX")
@EnableBatchProcessing
@PropertySource("classpath:database.properties")
@ImportResource({ "classpath:jobs/XY.xml"})
@EnableJpaRepositories(basePackages = {"com.XX.repository"})
public class MyConfig {

    private PlatformTransactionManager transactionManager;

    @PostConstruct
    void initialize() throws Exception {
        if (this.transactionManager == null) {
            this.transactionManager = new ResourcelessTransactionManager();
        }
    }
}