From 1b371c8cfd26aa9eec3766887ca69863f6bf3764 Mon Sep 17 00:00:00 2001 From: robokaso Date: Tue, 21 Oct 2008 13:12:30 +0000 Subject: [PATCH] IN PROGRESS - BATCH-858: Pause / resume of Job added getLastJobExecution to JobRepository so that JobLaucher can check it for PAUSED status --- .../launch/support/SimpleJobLauncher.java | 37 +++++++++++++------ .../batch/core/repository/JobRepository.java | 7 ++++ .../support/SimpleJobRepository.java | 5 +++ .../core/launch/SimpleJobLauncherTests.java | 21 ++++++++--- .../batch/core/step/JobRepositorySupport.java | 5 ++- .../step/item/TaskletStepExceptionTests.java | 5 +++ 6 files changed, 61 insertions(+), 19 deletions(-) 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; + } } }