RESOLVED - issue BATCH-464: Throw exception if restart is attempted on job instance that was already completed successfully
This commit is contained in:
@@ -18,6 +18,7 @@ package org.springframework.batch.core.launch;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
|
||||
@@ -47,8 +48,10 @@ public interface JobLauncher {
|
||||
* null.
|
||||
* @throws JobRestartException if the job has been run before and
|
||||
* circumstances that preclude a re-start.
|
||||
* @throws JobInstanceAlreadyCompleteException if the job has been run
|
||||
* before with the same parameters and completed successfully
|
||||
*/
|
||||
public JobExecution run(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException,
|
||||
JobRestartException;
|
||||
JobRestartException, JobInstanceAlreadyCompleteException;
|
||||
|
||||
}
|
||||
|
||||
@@ -22,14 +22,13 @@ import java.util.Properties;
|
||||
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobExecutionException;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.configuration.JobLocator;
|
||||
import org.springframework.batch.core.converter.DefaultJobParametersConverter;
|
||||
import org.springframework.batch.core.converter.JobParametersConverter;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.NoSuchJobException;
|
||||
import org.springframework.batch.support.PropertiesConverter;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
@@ -160,13 +159,9 @@ public class SimpleExportedJobLauncher implements ExportedJobLauncher, Initializ
|
||||
try {
|
||||
execution = launcher.run(job, jobParameters);
|
||||
}
|
||||
catch (JobExecutionAlreadyRunningException e) {
|
||||
catch (JobExecutionException e) {
|
||||
return e.getClass().getName() + ": " + e.getMessage();
|
||||
}
|
||||
catch (JobRestartException e) {
|
||||
return e.getClass().getName() + ": " + e.getMessage();
|
||||
}
|
||||
|
||||
registry.put(name + params, execution);
|
||||
|
||||
return execution.toString();
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.launch.JobLauncher;
|
||||
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
@@ -71,9 +72,10 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean {
|
||||
* exists and has an execution already running.
|
||||
* @throws JobRestartException if the execution would be a re-start, but a
|
||||
* re-start is either not allowed or not needed.
|
||||
* @throws JobInstanceAlreadyCompleteException
|
||||
*/
|
||||
public JobExecution run(final Job job, final JobParameters jobParameters)
|
||||
throws JobExecutionAlreadyRunningException, JobRestartException {
|
||||
throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
|
||||
|
||||
Assert.notNull(job, "The Job must not be null.");
|
||||
Assert.notNull(jobParameters, "The JobParameters must not be null.");
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2006-2007 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.batch.core.repository;
|
||||
|
||||
import org.springframework.batch.core.JobExecutionException;
|
||||
|
||||
/**
|
||||
* An exception indicating an illegal attempt to restart a job that was already
|
||||
* completed successfully.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class JobInstanceAlreadyCompleteException extends JobExecutionException {
|
||||
|
||||
/**
|
||||
* @param string the message
|
||||
*/
|
||||
public JobInstanceAlreadyCompleteException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param msg the cause
|
||||
* @param t the message
|
||||
*/
|
||||
public JobInstanceAlreadyCompleteException(String msg, Throwable t) {
|
||||
super(msg, t);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,10 +26,10 @@ import org.springframework.batch.item.ExecutionContext;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Repository for storing batch {@link JobExecution} and {@link StepExecution}s.
|
||||
* Before using any methods, a {@link JobExecution}
|
||||
* must first be obtained using the createJobExecution method. Once a {@link JobExecution}
|
||||
* is obtained, they can be updated.
|
||||
* Repository for storing batch {@link JobExecution} and {@link StepExecution}s.
|
||||
* Before using any methods, a {@link JobExecution} must first be obtained using
|
||||
* the createJobExecution method. Once a {@link JobExecution} is obtained, they
|
||||
* can be updated.
|
||||
* </p>
|
||||
*
|
||||
* @author Lucas Ward
|
||||
@@ -39,25 +39,28 @@ public interface JobRepository {
|
||||
|
||||
/**
|
||||
* Find or create a {@link JobExecution} for a given {@link Job} and
|
||||
* {@link JobParameters}. If the {@link Job} that is uniquely identified by
|
||||
* {@link JobParameters} already exists, its persisted values (including ID)
|
||||
* will be returned in a new {@link JobInstance} object, associated with the
|
||||
* returned {@link JobExecution}. If no previous run
|
||||
* is found, the execution will be associated with a new {@link JobInstance}
|
||||
* {@link JobParameters}. If the {@link Job} was already executed with
|
||||
* these {@link JobParameters}, its persisted values (including ID) will be
|
||||
* returned in a new {@link JobInstance}, associated with the
|
||||
* {@link JobExecution}. If no previous instance is found, the execution
|
||||
* will be associated with a new {@link JobInstance}
|
||||
*
|
||||
* @param jobParameters the runtime parameters for the job
|
||||
* @param job the job the execution should be associated with.
|
||||
*
|
||||
* @return a valid job {@link JobExecution} for the arguments provided
|
||||
* @throws JobExecutionAlreadyRunningException if there is a
|
||||
* {@link JobExecution} alrady running for the job instance that would
|
||||
* otherwise be returned
|
||||
* @throws JobRestartException if more than one JobInstance if found or if
|
||||
* JobInstance.getJobExecutionCount() is greater than Job.getStartLimit()
|
||||
* {@link JobExecution} already running for the job instance with the
|
||||
* provided job and parameters.
|
||||
* @throws JobRestartException if one or more existing {@link JobInstance}s
|
||||
* is found with the same parameters and {@link Job#isRestartable()} is
|
||||
* false.
|
||||
* @throws JobInstanceAlreadyCompleteException if a {@link JobInstance} is
|
||||
* found and was already completed successfully.
|
||||
*
|
||||
*/
|
||||
JobExecution createJobExecution(Job job, JobParameters jobParameters)
|
||||
throws JobExecutionAlreadyRunningException, JobRestartException;
|
||||
JobExecution createJobExecution(Job job, JobParameters jobParameters) throws JobExecutionAlreadyRunningException,
|
||||
JobRestartException, JobInstanceAlreadyCompleteException;
|
||||
|
||||
/**
|
||||
* Save or Update a {@link JobExecution}. If no ID is found a new instance
|
||||
|
||||
@@ -20,15 +20,17 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.batch.core.BatchStatus;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.Step;
|
||||
import org.springframework.batch.core.StepExecution;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
|
||||
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
|
||||
import org.springframework.batch.core.repository.JobRepository;
|
||||
import org.springframework.batch.core.repository.JobRestartException;
|
||||
import org.springframework.batch.core.repository.dao.JobExecutionDao;
|
||||
import org.springframework.batch.core.repository.dao.JobInstanceDao;
|
||||
import org.springframework.batch.core.repository.dao.StepExecutionDao;
|
||||
@@ -134,7 +136,7 @@ public class SimpleJobRepository implements JobRepository {
|
||||
*
|
||||
*/
|
||||
public JobExecution createJobExecution(Job job, JobParameters jobParameters)
|
||||
throws JobExecutionAlreadyRunningException, JobRestartException {
|
||||
throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException {
|
||||
|
||||
Assert.notNull(job, "Job must not be null.");
|
||||
Assert.notNull(jobParameters, "JobParameters must not be null.");
|
||||
@@ -157,7 +159,7 @@ public class SimpleJobRepository implements JobRepository {
|
||||
}
|
||||
|
||||
List executions = jobExecutionDao.findJobExecutions(jobInstance);
|
||||
|
||||
|
||||
// check for running executions and find the last started
|
||||
for (Iterator iterator = executions.iterator(); iterator.hasNext();) {
|
||||
JobExecution execution = (JobExecution) iterator.next();
|
||||
@@ -165,19 +167,24 @@ public class SimpleJobRepository implements JobRepository {
|
||||
throw new JobExecutionAlreadyRunningException("A job execution for this job is already running: "
|
||||
+ jobInstance);
|
||||
}
|
||||
if (execution.getStatus() == BatchStatus.COMPLETED) {
|
||||
throw new JobInstanceAlreadyCompleteException(
|
||||
"A job instance already exists is complete for parameters=" + jobParameters
|
||||
+ ". If you want to run this job again, change the parameters.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no job found, create one
|
||||
jobInstance = jobInstanceDao.createJobInstance(job, jobParameters);
|
||||
}
|
||||
|
||||
|
||||
JobExecution jobExecution = new JobExecution(jobInstance);
|
||||
|
||||
|
||||
// Save the JobExecution so that it picks up an ID (useful for clients
|
||||
// monitoring asynchronous executions):
|
||||
saveOrUpdate(jobExecution);
|
||||
|
||||
|
||||
return jobExecution;
|
||||
|
||||
}
|
||||
@@ -222,7 +229,7 @@ public class SimpleJobRepository implements JobRepository {
|
||||
Assert.notNull(stepExecution, "StepExecution cannot be null.");
|
||||
Assert.notNull(stepExecution.getStepName(), "StepExecution's step name cannot be null.");
|
||||
Assert.notNull(stepExecution.getJobExecutionId(), "StepExecution must belong to persisted JobExecution");
|
||||
|
||||
|
||||
if (stepExecution.getId() == null) {
|
||||
stepExecutionDao.saveStepExecution(stepExecution);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user