package org.aksw.jena_sparql_api.batch.config;
import java.util.Date;
import java.util.List;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.batch.core.repository.dao.ExecutionContextDao;
import org.springframework.batch.core.repository.dao.JobExecutionDao;
import org.springframework.batch.core.repository.dao.JobInstanceDao;
import org.springframework.batch.core.repository.dao.StepExecutionDao;
import org.springframework.batch.core.repository.support.SimpleJobRepository;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.util.Assert;
/**
* At least up to spring batch 3.0.4 its not possible to create a job instance
* without any executions; doing so will cause a null pointer exception when calling
* jobLauncher.run().
*
*
* @author raven
*
*/
public class SimpleJobRepositoryFix
extends SimpleJobRepository
{
// Note: we have to duplicate all these attributes from the base class because they are
// private there
private JobInstanceDao jobInstanceDao;
private JobExecutionDao jobExecutionDao;
// private StepExecutionDao stepExecutionDao;
private ExecutionContextDao ecDao;
public SimpleJobRepositoryFix(JobInstanceDao jobInstanceDao, JobExecutionDao jobExecutionDao,
StepExecutionDao stepExecutionDao, ExecutionContextDao ecDao) {
super(jobInstanceDao, jobExecutionDao, stepExecutionDao, ecDao);
this.jobInstanceDao = jobInstanceDao;
this.jobExecutionDao = jobExecutionDao;
// this.stepExecutionDao = stepExecutionDao;
this.ecDao = ecDao;
}
@Override
public JobExecution createJobExecution(String jobName, JobParameters jobParameters)
throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
Assert.notNull(jobName, "Job name must not be null.");
Assert.notNull(jobParameters, "JobParameters must not be null.");
/*
* Find all jobs matching the runtime information.
*
* If this method is transactional, and the isolation level is
* REPEATABLE_READ or better, another launcher trying to start the same
* job in another thread or process will block until this transaction
* has finished.
*/
JobInstance jobInstance = jobInstanceDao.getJobInstance(jobName, jobParameters);
ExecutionContext executionContext = null;
// existing job instance found
if (jobInstance != null) {
List<JobExecution> executions = jobExecutionDao.findJobExecutions(jobInstance);
// check for running executions and find the last started
for (JobExecution execution : executions) {
if (execution.isRunning()) {
throw new JobExecutionAlreadyRunningException("A job execution for this job is already running: "
+ jobInstance);
}
BatchStatus status = execution.getStatus();
if (execution.getJobParameters().getParameters().size() > 0 && (status == BatchStatus.COMPLETED || status == BatchStatus.ABANDONED)) {
throw new JobInstanceAlreadyCompleteException(
"A job instance already exists and is complete for parameters=" + jobParameters
+ ". If you want to run this job again, change the parameters.");
}
}
JobExecution lastJobExecution = jobExecutionDao.getLastJobExecution(jobInstance);
if(lastJobExecution != null) {
executionContext = ecDao.getExecutionContext(lastJobExecution);
}
}
else {
// no job found, create one
jobInstance = jobInstanceDao.createJobInstance(jobName, jobParameters);
}
if(executionContext == null) {
executionContext = new ExecutionContext();
}
JobExecution jobExecution = new JobExecution(jobInstance, jobParameters, null);
jobExecution.setExecutionContext(executionContext);
jobExecution.setLastUpdated(new Date(System.currentTimeMillis()));
// Save the JobExecution so that it picks up an ID (useful for clients
// monitoring asynchronous executions):
jobExecutionDao.saveJobExecution(jobExecution);
ecDao.saveExecutionContext(jobExecution);
return jobExecution;
}
}