There is an @Aspect
that ensures that jobs in spring boot are not re-entrant. It is implemented in JobLauncherSynchronizer.java and documented here. It is in the spring batch admin artifact.
My Job is created through a @Bean
as follows:
@Bean
@Qualifier("synchronisationLauncher")
public JobLauncher synchronisationLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
My question:
how do I integrate the @Aspect
into my JobLauncher?
I naively tried to new it up, and set the properties in the method above, not surprisingly that didn't work very well. I was able to launch multiple instances.
My launch code is:
// dependencies from constructor.
// the launcher is qualified to 'synchronisationLauncher'
private JobLauncher launcher;
private Job mergeJob;
private JobQueryHelper jobQueryHelper;
@PostMapping("uri")
public ResponseEntity<APIResponse> SynchroniseRetailers()
throws JobParametersInvalidException,
JobExecutionAlreadyRunningException,
JobRestartException,
JobInstanceAlreadyCompleteException {
JobParametersBuilder builder = new JobParametersBuilder()
.addLong("run.id", jobQueryHelper.findLastBatchExecutionIndex() + 1);
launcher.run(mergeJob, builder.toJobParameters());
return buildEmptyResponse();
}
What you can do is override the SimpleJobLauncher#run
method and add the double check before running the job:
@Bean
public JobLauncher jobLauncher(JobRepository jobRepository, JobExplorer jobExplorer) {
SimpleJobLauncher simpleJobLauncher = new SimpleJobLauncher() {
@Override
public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException {
Set<JobExecution> running = jobExplorer.findRunningJobExecutions(job.getName());
if (!running.isEmpty()) {
throw new JobExecutionAlreadyRunningException("An instance of this job is already active: " + job.getName());
}
return super.run(job, jobParameters);
}
};
simpleJobLauncher.setJobRepository(jobRepository);
simpleJobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
simpleJobLauncher.afterPropertiesSet();
return simpleJobLauncher;
}
Note this is similar to the code in the aspect you shared but without needing any kind of AOP. As I mentioned in the comment, this check is already done in super.run(job, jobParameters)
, so we are only adding a double check here.