public JobExecution(JobExecution original) { this.jobParameters = original.getJobParameters(); this.jobInstance = original.getJobInstance(); this.stepExecutions = original.getStepExecutions(); this.status = original.getStatus(); this.startTime = original.getStartTime(); this.createTime = original.getCreateTime(); this.endTime = original.getEndTime(); this.lastUpdated = original.getLastUpdated(); this.exitStatus = original.getExitStatus(); this.executionContext = original.getExecutionContext(); this.failureExceptions = original.getFailureExceptions(); this.jobConfigurationName = original.getJobConfigurationName(); this.setId(original.getId()); this.setVersion(original.getVersion()); }
/** * * SQL implementation using Sequences via the Spring incrementer * abstraction. Once a new id has been obtained, the JobExecution is saved * via a SQL INSERT statement. * * @see JobExecutionDao#saveJobExecution(JobExecution) * @throws IllegalArgumentException if jobExecution is null, as well as any * of it's fields to be persisted. */ @Override public void saveJobExecution(JobExecution jobExecution) { validateJobExecution(jobExecution); jobExecution.incrementVersion(); jobExecution.setId(jobExecutionIncrementer.nextLongValue()); Object[] parameters = new Object[] { jobExecution.getId(), jobExecution.getJobId(), jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(), jobExecution.getExitStatus().getExitCode(), jobExecution.getExitStatus().getExitDescription(), jobExecution.getVersion(), jobExecution.getCreateTime(), jobExecution.getLastUpdated(), jobExecution.getJobConfigurationName() }; getJdbcTemplate().update( getQuery(SAVE_JOB_EXECUTION), parameters, new int[] { Types.BIGINT, Types.BIGINT, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR }); insertJobParameters(jobExecution.getId(), jobExecution.getJobParameters()); }
@Override public void synchronizeStatus(JobExecution jobExecution) { JobExecution saved = getJobExecution(jobExecution.getId()); if (saved.getVersion().intValue() != jobExecution.getVersion().intValue()) { jobExecution.upgradeStatus(saved.getStatus()); jobExecution.setVersion(saved.getVersion()); } } }
/** * Validate JobExecution. At a minimum, JobId, StartTime, EndTime, and * Status cannot be null. * * @param jobExecution * @throws IllegalArgumentException */ private void validateJobExecution(JobExecution jobExecution) { Assert.notNull(jobExecution, "jobExecution cannot be null"); Assert.notNull(jobExecution.getJobId(), "JobExecution Job-Id cannot be null."); Assert.notNull(jobExecution.getStatus(), "JobExecution status cannot be null."); Assert.notNull(jobExecution.getCreateTime(), "JobExecution create time cannot be null"); }
Assert.notNull(jobExecution.getId(), "JobExecution ID cannot be null. JobExecution must be saved before it can be updated"); Assert.notNull(jobExecution.getVersion(), "JobExecution version cannot be null. JobExecution must be saved before it can be updated"); Integer version = jobExecution.getVersion() + 1; String exitDescription = jobExecution.getExitStatus().getExitDescription(); if (exitDescription != null && exitDescription.length() > exitMessageLength) { exitDescription = exitDescription.substring(0, exitMessageLength); Object[] parameters = new Object[] { jobExecution.getStartTime(), jobExecution.getEndTime(), jobExecution.getStatus().toString(), jobExecution.getExitStatus().getExitCode(), exitDescription, version, jobExecution.getCreateTime(), jobExecution.getLastUpdated(), jobExecution.getId(), jobExecution.getVersion() }; new Object[] { jobExecution.getId() }) != 1) { throw new NoSuchObjectException("Invalid JobExecution, ID " + jobExecution.getId() + " not found."); new Object[] { jobExecution.getId() }); throw new OptimisticLockingFailureException("Attempt to update job execution id=" + jobExecution.getId() + " with wrong version (" + jobExecution.getVersion() + "), where current version is " + currentVersion); jobExecution.incrementVersion();
private void checkRepository(BatchStatus status, ExitStatus exitStatus) { // because map dao stores in memory, it can be checked directly JobInstance jobInstance = jobExecution.getJobInstance(); JobExecution other = jobExecutionDao.findJobExecutions(jobInstance).get(0); assertEquals(jobInstance.getId(), other.getJobId()); assertEquals(status, other.getStatus()); if (exitStatus != null) { assertEquals(exitStatus.getExitCode(), other.getExitStatus().getExitCode()); } }
BatchStatus status = jobExecution.getStatus(); if (!(status == BatchStatus.STARTED || status == BatchStatus.STARTING)) { throw new JobExecutionNotRunningException("JobExecution must be running so that it can be stopped: "+jobExecution); jobExecution.setStatus(BatchStatus.STOPPING); jobRepository.update(jobExecution); Job job = jobRegistry.getJob(jobExecution.getJobInstance().getJobName()); if (job instanceof StepLocator) {//can only process as StepLocator is the only way to get the step object for (StepExecution stepExecution : jobExecution.getStepExecutions()) { if (stepExecution.getStatus().isRunning()) { try { Step step = ((StepLocator)job).getStep(stepExecution.getStepName()); if (step instanceof TaskletStep) { Tasklet tasklet = ((TaskletStep)step).getTasklet();
@Test public void testFailedStep() throws Exception { JobExecution jobExecution = jobLauncher.run(job, new JobParameters(Collections.singletonMap("item.three", new JobParameter("fail")))); assertEquals(BatchStatus.FAILED, jobExecution.getStatus()); StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); assertEquals(9, stepExecution.getReadCount()); // In principle the write count could be more than 2 and less than 9... assertEquals(7, stepExecution.getWriteCount()); }
@Override public Job convert(JobExecution source, Job job) { Job target = job != null ? job : new Job(source.getJobConfigurationName()); target.startTime(source.getStartTime()) .endTime(source.getEndTime()) .status(source.getStatus().toString()) .running(source.getStatus().isRunning()) .exitStatus(source.getExitStatus().getExitDescription()) .jobParameters(getJobParameters(source.getJobParameters())) .steps(new StepExecutionToSimpleStepConverter().convertAll(new ArrayList<>(source.getStepExecutions()))); return target; }
public static JobExecutionEventInfo transformToJobExecutionEventInfo(final JobExecution jobExecution, final String applicationName) { final JobExecutionEventInfo jobExecutionEventInfo = new JobExecutionEventInfo(); jobExecutionEventInfo.setApplicationName(applicationName); jobExecutionEventInfo.setExitStatus(BatchToResourceMapper.map(jobExecution.getExitStatus())); jobExecutionEventInfo.setStartDate(jobExecution.getStartTime()); jobExecutionEventInfo.setEndDate(jobExecution.getEndTime()); jobExecutionEventInfo.setJobExecutionId(jobExecution.getId()); jobExecutionEventInfo.setJobName(jobExecution.getJobInstance().getJobName()); return jobExecutionEventInfo; } }
BatchStatus status = jobExecution.getStatus(); if (!(status == BatchStatus.STARTED || status == BatchStatus.STARTING)) { throw new JobExecutionNotRunningException("JobExecution must be running so that it can be stopped: "+jobExecution); jobExecution.setStatus(BatchStatus.STOPPING); jobRepository.update(jobExecution); Job job = jobRegistry.getJob(jobExecution.getId()); if (job instanceof StepLocator) {//can only process as StepLocator is the only way to get the step object for (org.springframework.batch.core.StepExecution stepExecution : jobExecution.getStepExecutions()) { if (stepExecution.getStatus().isRunning()) { try { Step step = ((StepLocator)job).getStep(stepExecution.getStepName()); if (step instanceof TaskletStep) { Tasklet tasklet = ((TaskletStep)step).getTasklet();
private void launchAndAssert(String stepNames) throws JobInstanceAlreadyCompleteException, JobRestartException, JobExecutionAlreadyRunningException { JobExecution jobExecution = createJobExecution(); job.execute(jobExecution); assertEquals(stepNames, stepNamesList.toString()); assertEquals(BatchStatus.STOPPED, jobExecution.getStatus()); assertEquals(ExitStatus.STOPPED.getExitCode(), jobExecution.getExitStatus().getExitCode()); StepExecution stepExecution1 = getStepExecution(jobExecution, "fail"); assertEquals(BatchStatus.FAILED, stepExecution1.getStatus()); assertEquals(ExitStatus.FAILED.getExitCode(), stepExecution1.getExitStatus().getExitCode()); }
@Override public StepExecution handleStep(Step step, JobExecution execution) throws JobInterruptedException, JobRestartException, StartLimitExceededException { if (execution.isStopping()) { throw new JobInterruptedException("JobExecution interrupted."); JobInstance jobInstance = execution.getJobInstance(); StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step.getName()); if (stepExecutionPartOfExistingJobExecution(execution, lastStepExecution)) { .getJobName())); lastStepExecution = null; currentStepExecution = execution.createStepExecution(step.getName()); currentStepExecution.setExecutionContext(lastStepExecution.getExecutionContext()); if(lastStepExecution.getExecutionContext().containsKey("batch.executed")) { jobRepository.add(currentStepExecution); execution.setStatus(BatchStatus.STOPPING); throw e; jobRepository.updateExecutionContext(execution); execution.setStatus(BatchStatus.STOPPING); throw new JobInterruptedException("Job interrupted by step execution");
jobOperator.stop(jobExecution.getId()); while(jobExecution.isRunning()) { int numStepExecutions = jobExecution.getStepExecutions().size(); StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); String stepName = stepExecution.getStepName(); BatchStatus stepExecutionStatus = stepExecution.getStatus(); BatchStatus jobExecutionStatus = jobExecution.getStatus(); assertTrue("Step execution status should be STOPPED but got: " + stepExecutionStatus, stepExecutionStatus.equals(BatchStatus.STOPPED)); assertTrue("Job execution status should be STOPPED but got:" + jobExecutionStatus, jobExecutionStatus.equals(BatchStatus.STOPPED)); while(restartJobExecution.isRunning()) { int restartNumStepExecutions = restartJobExecution.getStepExecutions().size(); assertTrue("Should be two StepExecution's on restart but got: " + restartNumStepExecutions, restartNumStepExecutions == 2); for(StepExecution restartStepExecution : restartJobExecution.getStepExecutions()) { BatchStatus restartStepExecutionStatus = restartStepExecution.getStatus(); restartStepExecutionStatus.equals(BatchStatus.COMPLETED)); BatchStatus restartJobExecutionStatus = restartJobExecution.getStatus(); assertTrue("Job execution status should be COMPLETED but got:" + restartJobExecutionStatus, restartJobExecutionStatus.equals(BatchStatus.COMPLETED));
@Test public void testBuildWithCustomEndState() throws Exception { SimpleJobBuilder builder = new JobBuilder("flow").repository(jobRepository).start(step1); builder.on("COMPLETED").end("FOO"); builder.preventRestart(); builder.build().execute(execution); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); assertEquals("FOO", execution.getExitStatus().getExitCode()); assertEquals(1, execution.getStepExecutions().size()); }
private void assertExecutionsAreEqual(JobExecution lhs, JobExecution rhs) { assertEquals(lhs.getId(), rhs.getId()); assertEquals(lhs.getStartTime(), rhs.getStartTime()); assertEquals(lhs.getStatus(), rhs.getStatus()); assertEquals(lhs.getEndTime(), rhs.getEndTime()); assertEquals(lhs.getCreateTime(), rhs.getCreateTime()); assertEquals(lhs.getLastUpdated(), rhs.getLastUpdated()); assertEquals(lhs.getVersion(), rhs.getVersion()); }
/** * UNKNOWN status won't be changed by synchronizeStatus, because it is the * 'largest' BatchStatus (will not downgrade). */ @Transactional @Test public void testSynchronizeStatusDowngrade() { JobExecution exec1 = new JobExecution(jobInstance, jobParameters); exec1.setStatus(BatchStatus.STARTED); dao.saveJobExecution(exec1); JobExecution exec2 = new JobExecution(jobInstance, jobParameters); assertTrue(exec1.getId() != null); exec2.setId(exec1.getId()); exec2.setStatus(BatchStatus.UNKNOWN); exec2.setVersion(7); assertTrue(exec1.getVersion() != exec2.getVersion()); assertTrue(exec1.getStatus().isLessThan(exec2.getStatus())); dao.synchronizeStatus(exec2); assertEquals(exec1.getVersion(), exec2.getVersion()); assertEquals(BatchStatus.UNKNOWN, exec2.getStatus()); }
@Test public void testAbort() throws Exception { JobInstance jobInstance = new JobInstance(123L, job.getName()); JobExecution jobExecution = new JobExecution(jobInstance, 111L, jobParameters, null); jobExecution.setStatus(BatchStatus.STOPPING); when(jobExplorer.getJobExecution(123L)).thenReturn(jobExecution); jobRepository.update(jobExecution); jobOperator.abandon(123L); assertEquals(BatchStatus.ABANDONED, jobExecution.getStatus()); assertNotNull(jobExecution.getEndTime()); }
@Test public void testStepAlreadyComplete() throws Exception { stepExecution1.setStatus(BatchStatus.COMPLETED); jobRepository.add(stepExecution1); jobExecution.setEndTime(new Date()); jobRepository.update(jobExecution); jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters); job.execute(jobExecution); assertEquals(0, jobExecution.getFailureExceptions().size()); assertEquals(1, jobExecution.getStepExecutions().size()); assertEquals(stepExecution2.getStepName(), jobExecution.getStepExecutions().iterator().next().getStepName()); }
/** * Modifications to saved entity do not affect the persisted object. */ @Test public void testPersistentCopy() { JobExecutionDao tested = new MapJobExecutionDao(); JobExecution jobExecution = new JobExecution(new JobInstance((long) 1, "mapJob"), new JobParameters()); assertNull(jobExecution.getStartTime()); tested.saveJobExecution(jobExecution); jobExecution.setStartTime(new Date()); JobExecution retrieved = tested.getJobExecution(jobExecution.getId()); assertNull(retrieved.getStartTime()); tested.updateJobExecution(jobExecution); jobExecution.setEndTime(new Date()); assertNull(retrieved.getEndTime()); }