我正在使用带有4.2.1.RELEASE版本的spring batch。我有一份工作,我使用不同的工作参数多次运行。同步执行作业时,一切正常。当我尝试异步运行作业时,在尝试从CustomItemWriter的执行上下文中获取某些值时,我得到了NullPointerException。作业由作业调度程序调度。
CustomItemWriter
public class CustomWriter ItemWriter<T>, StepExecutionListener {
private CustomObject customObject;
@Override
public void beforeStep(StepExecution stepExecution) {
ExecutionContext executionContext = stepExecution.getJobExecution().getExecutionContext();
customObject = (CustomObject) Objects.requireNonNull(executionContext.get("custom_object")); -> Exception when running asynchronous
}
@Override
public void write(List<? extends CustomWriter> list) {
// do something
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return ExitStatus.COMPLETED;
}
}
BatchConfig
public class BatchConfig extends DefaultBatchConfigurer {
@Autowired
@Qualifier("batchDataSource")
private DataSource batchDataSource;
@Autowired
private PlatformTransactionManager platformTransactionManager;
@Autowired
private JobRepository jobRepository;
@Override
@Autowired
public void setDataSource(@Qualifier("batchDataSource") final DataSource batchDataSource) {
super.setDataSource(batchDataSource);
}
@Bean
public BatchDataSourceInitializer batchDataSourceInitializer(
@Qualifier("batchDataSource") final DataSource batchDataSource, final ResourceLoader resourceLoader) {
return new BatchDataSourceInitializer(batchDataSource, resourceLoader, new BatchProperties());
}
@Override
public JobRepository createJobRepository() throws Exception {
Jackson2ExecutionContextStringSerializer defaultSerializer = new Jackson2ExecutionContextStringSerializer();
defaultSerializer.setObjectMapper(JsonUtils.getObjectMapper());
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDataSource(batchDataSource);
factory.setTransactionManager(platformTransactionManager);
factory.setSerializer(defaultSerializer);
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
public JobLauncher asyncJobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
}
MainClass
@EnableScheduling
@EnableAsync
@SpringBootApplication
@Import({BatchConfig.class, DataSourceConfig.class, MainJobConfig.class})
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
异常(仅在异步执行作业时发生)
java.lang.NullPointerException: null
at java.util.Objects.requireNonNull(Objects.java:203)
at com.aldisued.tcmapp.chunks.writer.CustomItemWriter.beforeStep(CustomItemWriter.java:22)
at org.springframework.batch.core.listener.CompositeStepExecutionListener.beforeStep(CompositeStepExecutionListener.java:79)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:204)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:68)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:68)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:137)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:319)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:147)
at java.lang.Thread.run(Thread.java:748)
JobScheduler
@Component
public class JobScheduler {
@Autowired
private Environment environment;
@Autowired
@Qualifier("asyncJobLauncher")
private JobLauncher jobLauncher;
@Autowired
private Job job;
@Scheduled(cron = "${job.cron.expr}")
public void runJob() throws JobParametersInvalidException, JobExecutionAlreadyRunningException,
JobRestartException, JobInstanceAlreadyCompleteException, InterruptedException {
runJobs(getStringList();
}
private void runJobs(List<String> stringList) throws JobParametersInvalidException,
JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
for (String string : stringList) {
JobParameters params = new JobParametersBuilder()
.addDate("exec_time", new Date())
.addString("exec_time", string)
.toJobParameters();
jobLauncher.run(job, params);
}
}
private List<Strings> getStringList() {
// get some strings
}
}
我如何使执行线程安全或我做错了什么?