diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java b/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java index e4d449ccc..bb4436d3e 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java @@ -54,12 +54,13 @@ public class SimpleJob extends AbstractJob { JobInstance jobInstance = execution.getJobInstance(); - boolean isJobRestart = getJobRepository().getJobExecutionCount(jobInstance) > 0; - if (isJobRestart) { - execution.setExecutionContext(getJobRepository().getLastJobExecution(jobInstance).getExecutionContext()); - } else { - execution.setExecutionContext(new ExecutionContext()); - } +// boolean isJobRestart = getJobRepository().getJobExecutionCount(jobInstance) > 1; +// if (isJobRestart) { +// ExecutionContext restartContext = getJobRepository().getLastJobExecution(jobInstance).getExecutionContext(); +// execution.setExecutionContext(restartContext); +// } else { +// execution.setExecutionContext(new ExecutionContext()); +// } StepExecution currentStepExecution = null; int startedCount = 0; 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 e848a79b9..0b6ea5c13 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 @@ -111,16 +111,5 @@ public interface JobRepository { * @return the execution count of the step within the given job instance. */ int getStepExecutionCount(JobInstance jobInstance, Step step); - - /** - * @return the execution count of the given job instance. - */ - int getJobExecutionCount(JobInstance jobInstance); - - /** - * @return the last execution of the given job instance. - */ - JobExecution getLastJobExecution(JobInstance jobInstance); - } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java index 10d40b6ff..8281d6e18 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/JdbcJobExecutionDao.java @@ -192,7 +192,7 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements * @author Dave Syer * */ - private static class JobExecutionRowMapper implements RowMapper { + private class JobExecutionRowMapper implements RowMapper { private JobInstance job; @@ -208,6 +208,7 @@ public class JdbcJobExecutionDao extends AbstractJdbcBatchMetadataDao implements jobExecution.setEndTime(rs.getTimestamp(3)); jobExecution.setStatus(BatchStatus.getStatus(rs.getString(4))); jobExecution.setExitStatus(new ExitStatus("Y".equals(rs.getString(5)), rs.getString(6), rs.getString(7))); + jobExecution.setExecutionContext(findExecutionContext(jobExecution)); return jobExecution; } 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 ffc1a18d0..41f534994 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 @@ -34,6 +34,7 @@ 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; +import org.springframework.batch.item.ExecutionContext; import org.springframework.transaction.annotation.Isolation; import org.springframework.util.Assert; @@ -152,6 +153,7 @@ public class SimpleJobRepository implements JobRepository { */ JobInstance jobInstance = jobInstanceDao.getJobInstance(job, jobParameters); + ExecutionContext executionContext; // existing job instance found if (jobInstance != null) { @@ -174,13 +176,16 @@ public class SimpleJobRepository implements JobRepository { + ". If you want to run this job again, change the parameters."); } } + executionContext = jobExecutionDao.getLastJobExecution(jobInstance).getExecutionContext(); } else { // no job found, create one jobInstance = jobInstanceDao.createJobInstance(job, jobParameters); + executionContext = new ExecutionContext(); } JobExecution jobExecution = new JobExecution(jobInstance); + jobExecution.setExecutionContext(executionContext); // Save the JobExecution so that it picks up an ID (useful for clients // monitoring asynchronous executions): @@ -290,28 +295,5 @@ public class SimpleJobRepository implements JobRepository { } return count; } - - /** - * @return number of executions of the given job instance - */ - public int getJobExecutionCount(JobInstance jobInstance) { - - return jobExecutionDao.findJobExecutions(jobInstance).size(); - } - - public JobExecution getLastJobExecution(JobInstance jobInstance) { - List jobExecutions = jobExecutionDao.findJobExecutions(jobInstance); - if (jobExecutions.isEmpty()) { - return null; - } - JobExecution lastExecution = (JobExecution) jobExecutions.get(0); - for (Iterator iterator = jobExecutions.iterator(); iterator.hasNext();) { - JobExecution exec = (JobExecution) iterator.next(); - if (lastExecution.getStartTime().getTime() < exec.getStartTime().getTime()) { - lastExecution = exec; - } - } - return lastExecution; - } } diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java index 1e816d97a..edb10e1f3 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/job/SimpleJobTests.java @@ -373,6 +373,43 @@ public class SimpleJobTests extends TestCase { control.verify(); } + + /** + * Execution context should be restored on restart. + */ + public void testRestartScenario() throws Exception { + + job.setRestartable(true); + + step1.setAllowStartIfComplete(true); + final RuntimeException exception = new RuntimeException("Foo!"); + step2.setProcessException(exception); + + try { + job.execute(jobExecution); + fail(); + } + catch (RuntimeException e) { + assertSame(exception, e); + } + + assertTrue(step1.passedInJobContext.isEmpty()); + assertFalse(step2.passedInJobContext.isEmpty()); + + assertFalse(jobExecution.getExecutionContext().isEmpty()); + + jobExecution = jobRepository.createJobExecution(job, jobParameters); + + try { + job.execute(jobExecution); + fail(); + } + catch (RuntimeException e) { + assertSame(exception, e); + } + assertFalse(step1.passedInJobContext.isEmpty()); + assertFalse(step2.passedInJobContext.isEmpty()); + } /* * Check JobRepository to ensure status is being saved. diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobExecutionDaoTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobExecutionDaoTests.java index 05af860da..f66c9744d 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobExecutionDaoTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/AbstractJobExecutionDaoTests.java @@ -16,9 +16,9 @@ public abstract class AbstractJobExecutionDaoTests extends AbstractTransactional JobExecutionDao dao; JobInstance jobInstance = new JobInstance(new Long(1), new JobParameters(), "execTestJob"); - + JobExecution execution = new JobExecution(jobInstance); - + /** * @return tested object ready for use */ @@ -32,7 +32,7 @@ public abstract class AbstractJobExecutionDaoTests extends AbstractTransactional * Save and find a job execution. */ public void testSaveAndFind() { - + dao.saveJobExecution(execution); List executions = dao.findJobExecutions(jobInstance); @@ -44,7 +44,7 @@ public abstract class AbstractJobExecutionDaoTests extends AbstractTransactional * Saving sets id to the entity. */ public void testSaveAddsIdAndVersion() { - + assertNull(execution.getId()); assertNull(execution.getVersion()); dao.saveJobExecution(execution); @@ -57,7 +57,7 @@ public abstract class AbstractJobExecutionDaoTests extends AbstractTransactional * instance. */ public void testGetExecutionCount() { - + JobExecution exec1 = new JobExecution(jobInstance); JobExecution exec2 = new JobExecution(jobInstance); @@ -75,30 +75,40 @@ public abstract class AbstractJobExecutionDaoTests extends AbstractTransactional public void testUpdateExecution() { execution.setStatus(BatchStatus.STARTED); dao.saveJobExecution(execution); - + execution.setStatus(BatchStatus.COMPLETED); dao.updateJobExecution(execution); - + JobExecution updated = (JobExecution) dao.findJobExecutions(jobInstance).get(0); assertEquals(execution, updated); assertEquals(BatchStatus.COMPLETED, updated.getStatus()); } - + /** * Check the execution with most recent start time is returned */ public void testGetLastExecution() { JobExecution exec1 = new JobExecution(jobInstance); exec1.setStartTime(new Date(0)); + + ExecutionContext ctx = new ExecutionContext() { + { + put("key", "value"); + } + }; JobExecution exec2 = new JobExecution(jobInstance); + exec2.setExecutionContext(ctx); exec2.setStartTime(new Date(1)); - + dao.saveJobExecution(exec1); dao.saveJobExecution(exec2); - - assertEquals(exec2, dao.getLastJobExecution(jobInstance)); + dao.saveOrUpdateExecutionContext(exec2); + + JobExecution last = dao.getLastJobExecution(jobInstance); + assertEquals(exec2, last); + assertEquals("value", last.getExecutionContext().getString("key")); } - + public void testSaveAndFindContext() { dao.saveJobExecution(execution); ExecutionContext ctx = new ExecutionContext(new HashMap() { @@ -112,7 +122,7 @@ public abstract class AbstractJobExecutionDaoTests extends AbstractTransactional ExecutionContext retrieved = dao.findExecutionContext(execution); assertEquals(ctx, retrieved); } - + public void testSaveAndFindEmptyContext() { dao.saveJobExecution(execution); ExecutionContext ctx = new ExecutionContext();