IN PROGRESS - BATCH-505: Job-level ExecutionContext

JobExecutionContext is now persisted (together with StepExecutionContext) and retrieved on restart
(changed jobExecution's start time to be not null so that last execution can be always found).
This commit is contained in:
robokaso
2008-05-23 10:26:29 +00:00
parent abc9111b20
commit fd6fad60dc
17 changed files with 102 additions and 19 deletions

View File

@@ -38,13 +38,13 @@ public class JobExecution extends Entity {
private volatile BatchStatus status = BatchStatus.STARTING;
private volatile Date startTime = null;
private volatile Date startTime = new Date(System.currentTimeMillis());
private volatile Date endTime = null;
private volatile ExitStatus exitStatus = ExitStatus.UNKNOWN;
private ExecutionContext executionContext;
private ExecutionContext executionContext = new ExecutionContext();
/**
* Because a JobExecution isn't valid unless the job is set, this

View File

@@ -54,6 +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());
}
StepExecution currentStepExecution = null;
int startedCount = 0;
List steps = getSteps();

View File

@@ -111,5 +111,16 @@ 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);
}

View File

@@ -247,6 +247,7 @@ public class SimpleJobRepository implements JobRepository {
public void saveOrUpdateExecutionContext(StepExecution stepExecution) {
saveOrUpdate(stepExecution);
stepExecutionDao.saveOrUpdateExecutionContext(stepExecution);
jobExecutionDao.saveOrUpdateExecutionContext(stepExecution.getJobExecution());
}
/**
@@ -289,5 +290,28 @@ 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;
}
}

View File

@@ -21,7 +21,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID BIGINT PRIMARY KEY ,
VERSION BIGINT,
JOB_INSTANCE_ID BIGINT NOT NULL,
START_TIME TIMESTAMP DEFAULT NULL,
START_TIME TIMESTAMP NOT NULL,
END_TIME TIMESTAMP DEFAULT NULL,
STATUS VARCHAR(10),
CONTINUABLE CHAR(1),

View File

@@ -21,7 +21,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID BIGINT PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
VERSION BIGINT,
JOB_INSTANCE_ID BIGINT NOT NULL,
START_TIME TIMESTAMP DEFAULT NULL,
START_TIME TIMESTAMP NOT NULL,
END_TIME TIMESTAMP DEFAULT NULL,
STATUS VARCHAR(10),
CONTINUABLE CHAR(1),

View File

@@ -21,7 +21,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID BIGINT IDENTITY PRIMARY KEY ,
VERSION BIGINT,
JOB_INSTANCE_ID BIGINT NOT NULL,
START_TIME TIMESTAMP DEFAULT NULL,
START_TIME TIMESTAMP NOT NULL,
END_TIME TIMESTAMP DEFAULT NULL,
STATUS VARCHAR(10),
CONTINUABLE CHAR(1),

View File

@@ -21,7 +21,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID BIGINT PRIMARY KEY ,
VERSION BIGINT,
JOB_INSTANCE_ID BIGINT NOT NULL,
START_TIME DATETIME DEFAULT NULL,
START_TIME DATETIME NOT NULL,
END_TIME DATETIME DEFAULT NULL,
STATUS VARCHAR(10),
CONTINUABLE CHAR(1),

View File

@@ -21,7 +21,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID NUMBER(38) PRIMARY KEY ,
VERSION NUMBER(38),
JOB_INSTANCE_ID NUMBER(38) NOT NULL,
START_TIME TIMESTAMP DEFAULT NULL,
START_TIME TIMESTAMP NOT NULL,
END_TIME TIMESTAMP DEFAULT NULL,
STATUS VARCHAR2(10),
CONTINUABLE CHAR(1),

View File

@@ -21,7 +21,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID BIGINT PRIMARY KEY ,
VERSION BIGINT,
JOB_INSTANCE_ID BIGINT NOT NULL,
START_TIME TIMESTAMP DEFAULT NULL,
START_TIME TIMESTAMP NOT NULL,
END_TIME TIMESTAMP DEFAULT NULL,
STATUS VARCHAR(10),
CONTINUABLE CHAR(1),

View File

@@ -10,7 +10,7 @@ CREATE TABLE BATCH_JOB_EXECUTION (
JOB_EXECUTION_ID ${BIGINT} $!{IDENTITY} PRIMARY KEY $!{GENERATED},
VERSION ${BIGINT},
JOB_INSTANCE_ID ${BIGINT} NOT NULL,
START_TIME ${TIMESTAMP} DEFAULT NULL,
START_TIME ${TIMESTAMP} NOT NULL,
END_TIME ${TIMESTAMP} DEFAULT NULL,
STATUS ${VARCHAR}(10),
CONTINUABLE CHAR(1),

View File

@@ -71,7 +71,6 @@ public class JobExecutionTests extends TestCase {
* {@link org.springframework.batch.core.JobExecution#getStartTime()}.
*/
public void testGetStartTime() {
assertNull(execution.getStartTime());
execution.setStartTime(new Date(0L));
assertEquals(0L, execution.getStartTime().getTime());
}

View File

@@ -164,6 +164,9 @@ public class SimpleJobTests extends TestCase {
checkRepository(BatchStatus.COMPLETED);
assertNotNull(jobExecution.getEndTime());
assertNotNull(jobExecution.getStartTime());
assertTrue(step1.passedInJobContext.isEmpty());
assertFalse(step2.passedInJobContext.isEmpty());
}
public void testRunNormallyWithListener() throws Exception {
@@ -342,8 +345,8 @@ public class SimpleJobTests extends TestCase {
catch (RuntimeException e) {
assertSame(exception, e);
}
assertTrue(step1.passedInContext.isEmpty());
assertFalse(step2.passedInContext.isEmpty());
assertTrue(step1.passedInStepContext.isEmpty());
assertFalse(step2.passedInStepContext.isEmpty());
}
@@ -397,7 +400,9 @@ public class SimpleJobTests extends TestCase {
private JobRepository jobRepository;
private Properties passedInContext;
private Properties passedInStepContext;
private Properties passedInJobContext;
/**
* @param string
@@ -427,8 +432,10 @@ public class SimpleJobTests extends TestCase {
public void execute(StepExecution stepExecution) throws JobInterruptedException,
UnexpectedJobExecutionException {
passedInContext = stepExecution.getExecutionContext().getProperties();
stepExecution.getExecutionContext().putString("key", "value");
passedInJobContext = stepExecution.getJobExecution().getExecutionContext().getProperties();
passedInStepContext = stepExecution.getExecutionContext().getProperties();
stepExecution.getExecutionContext().putString("stepKey", "stepValue");
stepExecution.getJobExecution().getExecutionContext().putString("jobKey", "jobValue");
jobRepository.saveOrUpdateExecutionContext(stepExecution);
if (exception instanceof RuntimeException) {

View File

@@ -112,6 +112,16 @@ public abstract class AbstractJobExecutionDaoTests extends AbstractTransactional
ExecutionContext retrieved = dao.findExecutionContext(execution);
assertEquals(ctx, retrieved);
}
public void testSaveAndFindEmptyContext() {
dao.saveJobExecution(execution);
ExecutionContext ctx = new ExecutionContext();
execution.setExecutionContext(ctx);
dao.saveOrUpdateExecutionContext(execution);
ExecutionContext retrieved = dao.findExecutionContext(execution);
assertEquals(ctx, retrieved);
}
public void testUpdateContext() {
dao.saveJobExecution(execution);

View File

@@ -161,6 +161,16 @@ public abstract class AbstractStepExecutionDaoTests extends AbstractTransactiona
ExecutionContext retrieved = dao.findExecutionContext(stepExecution);
assertEquals(ctx, retrieved);
}
public void testSaveAndFindEmptyContext() {
dao.saveStepExecution(stepExecution);
ExecutionContext ctx = new ExecutionContext();
stepExecution.setExecutionContext(ctx);
dao.saveOrUpdateExecutionContext(stepExecution);
ExecutionContext retrieved = dao.findExecutionContext(stepExecution);
assertEquals(ctx, retrieved);
}
public void testUpdateContext() {
dao.saveStepExecution(stepExecution);

View File

@@ -89,7 +89,8 @@ public class SimpleJobRepositoryIntegrationTests extends AbstractTransactionalDa
job.setRestartable(true);
JobExecution firstExecution = jobRepository.createJobExecution(job, jobParameters);
firstExecution.setEndTime(new Date());
firstExecution.setStartTime(new Date(0));
firstExecution.setEndTime(new Date(1));
jobRepository.saveOrUpdate(firstExecution);
JobExecution secondExecution = jobRepository.createJobExecution(job, jobParameters);
@@ -163,6 +164,8 @@ public class SimpleJobRepositoryIntegrationTests extends AbstractTransactionalDa
}
};
JobExecution jobExec = jobRepository.createJobExecution(job, jobParameters);
jobExec.setStartTime(new Date(0));
jobExec.setExecutionContext(ctx);
Step step = new StepSupport("step1");
StepExecution stepExec = new StepExecution(step.getName(), jobExec);
stepExec.setExecutionContext(ctx);
@@ -170,9 +173,13 @@ public class SimpleJobRepositoryIntegrationTests extends AbstractTransactionalDa
jobRepository.saveOrUpdate(stepExec);
jobRepository.saveOrUpdateExecutionContext(stepExec);
StepExecution retrievedExec = jobRepository.getLastStepExecution(jobExec.getJobInstance(), step);
assertEquals(stepExec, retrievedExec);
assertEquals(ctx, retrievedExec.getExecutionContext());
StepExecution retrievedStepExec = jobRepository.getLastStepExecution(jobExec.getJobInstance(), step);
assertEquals(stepExec, retrievedStepExec);
assertEquals(ctx, retrievedStepExec.getExecutionContext());
// JobExecution retrievedJobExec = jobRepository.getLastJobExecution(jobExec.getJobInstance());
// assertEquals(jobExec, retrievedJobExec);
// assertEquals(ctx, retrievedJobExec.getExecutionContext());
}
/**

View File

@@ -68,4 +68,12 @@ public class JobRepositorySupport implements JobRepository {
return 0;
}
public int getJobExecutionCount(JobInstance jobInstance) {
return 0;
}
public JobExecution getLastJobExecution(JobInstance jobInstance) {
return null;
}
}