diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobLauncher.java b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobLauncher.java
index c8f4646c4..191b3f6f8 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobLauncher.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/SimpleJobLauncher.java
@@ -17,6 +17,7 @@ package org.springframework.batch.core.launch.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobInstance;
@@ -81,17 +82,29 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean {
Assert.notNull(job, "The Job must not be null.");
Assert.notNull(jobParameters, "The JobParameters must not be null.");
- boolean exists = jobRepository.isJobInstanceExists(job.getName(), jobParameters);
- if (exists && !job.isRestartable()) {
- throw new JobRestartException("JobInstance already exists and is not restartable");
+ final JobExecution jobExecution;
+ JobExecution lastExecution = jobRepository.getLastJobExecution(job.getName(), jobParameters);
+ if (lastExecution != null) {
+ if (lastExecution.getStatus() == BatchStatus.PAUSED) {
+ jobExecution = lastExecution;
+ }
+ else if (!job.isRestartable()) {
+ throw new JobRestartException("JobInstance already exists and is not restartable");
+ }
+ else {
+ /*
+ * There is a very small probability that a non-restartable job
+ * can be restarted, but only if another process or thread
+ * manages to launch and fail a job execution for this
+ * instance between the last assertion and the next method
+ * returning successfully.
+ */
+ jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters);
+ }
+ }
+ else {
+ jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters);
}
- /**
- * There is a very small probability that a non-restartable job can be
- * restarted, but only if another process or thread manages to launch
- * and fail a job execution for this instance between the last assertion
- * and the next method returning successfully.
- */
- final JobExecution jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters);
taskExecutor.execute(new Runnable() {
@@ -99,8 +112,8 @@ public class SimpleJobLauncher implements JobLauncher, InitializingBean {
try {
logger.info("Job: [" + job + "] launched with the following parameters: [" + jobParameters + "]");
job.execute(jobExecution);
- logger.info("Job: [" + job + "] completed with the following parameters: ["
- + jobParameters + "] and the following status: [" + jobExecution.getStatus() + "]");
+ logger.info("Job: [" + job + "] completed with the following parameters: [" + jobParameters
+ + "] and the following status: [" + jobExecution.getStatus() + "]");
}
catch (Throwable t) {
logger.info("Job: [" + job + "] failed with the following parameters: [" + jobParameters + "]", t);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java
index 57a5a26c1..76ca5e21f 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/JobRepository.java
@@ -124,4 +124,11 @@ public interface JobRepository {
*/
int getStepExecutionCount(JobInstance jobInstance, String stepName);
+ /**
+ * @param jobName the name of the job that might have run
+ * @param jobParameters parameters identifying the {@link JobInstance}
+ * @return the last execution of job if exists, null otherwise
+ */
+ JobExecution getLastJobExecution(String jobName, JobParameters jobParameters);
+
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java
index b14fef106..1955aef9f 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java
@@ -326,4 +326,9 @@ public class SimpleJobRepository implements JobRepository {
}
}
+ public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/SimpleJobLauncherTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/SimpleJobLauncherTests.java
index cccfcb23d..fe31d7ae6 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/launch/SimpleJobLauncherTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/launch/SimpleJobLauncherTests.java
@@ -32,6 +32,7 @@ import org.junit.Before;
import org.junit.Test;
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.job.JobSupport;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
@@ -74,7 +75,9 @@ public class SimpleJobLauncherTests {
JobExecution jobExecution = new JobExecution(null, null);
- expect(jobRepository.isJobInstanceExists(job.getName(), jobParameters)).andReturn(false);
+ // expect(jobRepository.isJobInstanceExists(job.getName(),
+ // jobParameters)).andReturn(false);
+ expect(jobRepository.getLastJobExecution(job.getName(), jobParameters)).andReturn(null);
expect(jobRepository.createJobExecution(job.getName(), jobParameters)).andReturn(jobExecution);
replay(jobRepository);
@@ -96,6 +99,7 @@ public class SimpleJobLauncherTests {
public boolean isRestartable() {
return false;
}
+
@Override
public void execute(JobExecution execution) {
execution.setExitStatus(ExitStatus.FINISHED);
@@ -106,7 +110,9 @@ public class SimpleJobLauncherTests {
testRun();
try {
reset(jobRepository);
- expect(jobRepository.isJobInstanceExists(job.getName(), jobParameters)).andReturn(true);
+// expect(jobRepository.isJobInstanceExists(job.getName(), jobParameters)).andReturn(true);
+ expect(jobRepository.getLastJobExecution(job.getName(), jobParameters)).andReturn(
+ new JobExecution(new JobInstance(1L, jobParameters, job.getName())));
replay(jobRepository);
jobLauncher.run(job, jobParameters);
fail("Expected JobRestartException");
@@ -141,7 +147,8 @@ public class SimpleJobLauncherTests {
try {
testRun();
fail("Expected RuntimeException");
- } catch (RuntimeException e) {
+ }
+ catch (RuntimeException e) {
assertEquals("foo", e.getMessage());
}
}
@@ -157,7 +164,8 @@ public class SimpleJobLauncherTests {
try {
testRun();
fail("Expected Error");
- } catch (RuntimeException e) {
+ }
+ catch (RuntimeException e) {
assertEquals("foo", e.getCause().getMessage());
}
}
@@ -167,10 +175,11 @@ public class SimpleJobLauncherTests {
try {
new SimpleJobLauncher().afterPropertiesSet();
fail("Expected IllegalArgumentException");
- } catch (IllegalStateException e) {
+ }
+ catch (IllegalStateException e) {
// expected
assertTrue("Message did not contain repository: " + e.getMessage(), contains(e.getMessage().toLowerCase(),
- "repository"));
+ "repository"));
}
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/JobRepositorySupport.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/JobRepositorySupport.java
index 78a3ec790..202ed7477 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/JobRepositorySupport.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/JobRepositorySupport.java
@@ -75,8 +75,11 @@ public class JobRepositorySupport implements JobRepository {
* @see org.springframework.batch.core.repository.JobRepository#isJobInstanceExists(java.lang.String, org.springframework.batch.core.JobParameters)
*/
public boolean isJobInstanceExists(String jobName, JobParameters jobParameters) {
- // TODO Auto-generated method stub
return false;
}
+ public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) {
+ return null;
+ }
+
}
diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/TaskletStepExceptionTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/TaskletStepExceptionTests.java
index c1c68e7c1..583694acd 100644
--- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/TaskletStepExceptionTests.java
+++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/TaskletStepExceptionTests.java
@@ -265,6 +265,11 @@ public class TaskletStepExceptionTests {
public int getUpdateCount() {
return updateCount;
}
+
+ public JobExecution getLastJobExecution(String jobName, JobParameters jobParameters) {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
}