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:
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user