if(jobExecution.getCreateTime().compareTo(previousJobExecution.getCreateTime()) > 0) {
throw new JobExecutionNotMostRecentException("The requested JobExecution to restart was not the most recently run");
}
if(jobExecution.getStatus().equals(BatchStatus.ABANDONED)) {
throw new JobRestartException("JobExecution ID: " + jobExecution.getId() + " is abandoned and attempted to be restarted.");
}
}
final String jobName = previousJobExecution.getJobInstance().getJobName();
Properties jobRestartProperties = getJobRestartProperties(params, previousJobExecution);
final JsrXmlApplicationContext batchContext = new JsrXmlApplicationContext(jobRestartProperties);
batchContext.setValidating(false);
Resource batchXml = new ClassPathResource("/META-INF/batch.xml");
Resource jobXml = new ClassPathResource(previousJobExecution.getJobConfigurationName());
if(batchXml.exists()) {
batchContext.load(batchXml);
}
if(jobXml.exists()) {
batchContext.load(jobXml);
}
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.jsr.JsrJobContextFactoryBean").getBeanDefinition();
beanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
batchContext.registerBeanDefinition(JSR_JOB_CONTEXT_BEAN_NAME, beanDefinition);
batchContext.setParent(baseContext);
try {
batchContext.refresh();
} catch (BeanCreationException e) {
throw new JobRestartException(e);
}
final org.springframework.batch.core.JobExecution jobExecution;
try {
JobParameters jobParameters = jobParametersConverter.getJobParameters(jobRestartProperties);
jobExecution = jobRepository.createJobExecution(previousJobExecution.getJobInstance(), jobParameters, previousJobExecution.getJobConfigurationName());
} catch (Exception e) {
throw new JobRestartException(e);
}
try {
final Semaphore semaphore = new Semaphore(1);
final List<Exception> exceptionHolder = Collections.synchronizedList(new ArrayList<Exception>());
semaphore.acquire();
taskExecutor.execute(new Runnable() {
@Override
public void run() {
JsrJobContextFactoryBean factoryBean = null;
try {
factoryBean = (JsrJobContextFactoryBean) batchContext.getBean("&" + JSR_JOB_CONTEXT_BEAN_NAME);
factoryBean.setJobExecution(jobExecution);
final Job job = batchContext.getBean(Job.class);
if(!job.isRestartable()) {
throw new JobRestartException("Job " + jobName + " is not restartable");
}
semaphore.release();
// Initialization of the JobExecution for job level dependencies
jobRegistry.register(job, jobExecution);
job.execute(jobExecution);
jobRegistry.remove(jobExecution);
}
catch (Exception e) {
exceptionHolder.add(e);
} finally {
if(factoryBean != null) {
factoryBean.close();
}
batchContext.close();
if(semaphore.availablePermits() == 0) {
semaphore.release();
}
}
}
});
semaphore.acquire();
if(exceptionHolder.size() > 0) {
semaphore.release();
throw new JobRestartException(exceptionHolder.get(0));
}
}
catch (Exception e) {
jobExecution.upgradeStatus(BatchStatus.FAILED);
if (jobExecution.getExitStatus().equals(ExitStatus.UNKNOWN)) {
jobExecution.setExitStatus(ExitStatus.FAILED.addExitDescription(e));
}
jobRepository.update(jobExecution);
if(batchContext.isActive()) {
batchContext.close();
}
throw new JobRestartException(e);
}
return jobExecution.getId();
}