List of usage examples for org.springframework.batch.core StepExecution getStatus
public BatchStatus getStatus()
From source file:org.springframework.batch.core.job.SimpleStepHandler.java
/** * Given a step and configuration, return true if the step should start, * false if it should not, and throw an exception if the job should finish. * @param lastStepExecution the last step execution * @param jobExecution/*from w w w. j a va2 s . c o m*/ * @param step * * @throws StartLimitExceededException if the start limit has been exceeded * for this step * @throws JobRestartException if the job is in an inconsistent state from * an earlier failure */ protected boolean shouldStart(StepExecution lastStepExecution, JobExecution jobExecution, Step step) throws JobRestartException, StartLimitExceededException { BatchStatus stepStatus; if (lastStepExecution == null) { stepStatus = BatchStatus.STARTING; } else { stepStatus = lastStepExecution.getStatus(); } if (stepStatus == BatchStatus.UNKNOWN) { throw new JobRestartException("Cannot restart step from UNKNOWN status. " + "The last execution ended with a failure that could not be rolled back, " + "so it may be dangerous to proceed. Manual intervention is probably necessary."); } if ((stepStatus == BatchStatus.COMPLETED && !step.isAllowStartIfComplete()) || stepStatus == BatchStatus.ABANDONED) { // step is complete, false should be returned, indicating that the // step should not be started logger.info("Step already complete or not restartable, so no action to execute: " + lastStepExecution); return false; } if (jobRepository.getStepExecutionCount(jobExecution.getJobInstance(), step.getName()) < step .getStartLimit()) { // step start count is less than start max, return true return true; } else { // start max has been exceeded, throw an exception. throw new StartLimitExceededException("Maximum start limit exceeded for step: " + step.getName() + "StartMax: " + step.getStartLimit()); } }
From source file:org.springframework.batch.core.jsr.job.DefaultStepHandler.java
/** * Given a step and configuration, return true if the step should start, * false if it should not, and throw an exception if the job should finish. * @param lastStepExecution the last step execution * @param jobInstance//from w w w. j av a 2 s . co m * @param step * * @throws StartLimitExceededException if the start limit has been exceeded * for this step * @throws JobRestartException if the job is in an inconsistent state from * an earlier failure */ @Override protected boolean shouldStart(StepExecution lastStepExecution, JobExecution jobExecution, Step step) throws JobRestartException, StartLimitExceededException { BatchStatus stepStatus; String restartStep = null; if (lastStepExecution == null) { jobExecution.getExecutionContext().put("batch.startedStep", step.getName()); stepStatus = BatchStatus.STARTING; } else { stepStatus = lastStepExecution.getStatus(); JobExecution lastJobExecution = getLastJobExecution(jobExecution); if (lastJobExecution.getExecutionContext().containsKey("batch.restartStep")) { restartStep = lastJobExecution.getExecutionContext().getString("batch.restartStep"); if (CollectionUtils.isEmpty(jobExecution.getStepExecutions()) && lastJobExecution.getStatus() == BatchStatus.STOPPED && StringUtils.hasText(restartStep)) { if (!restartStep.equals(step.getName()) && !jobExecution.getExecutionContext().containsKey("batch.startedStep")) { logger.info("Job was stopped and should restart at step " + restartStep + ". The current step is " + step.getName()); return false; } else { // Indicates the starting point for execution evaluation per JSR-352 jobExecution.getExecutionContext().put("batch.startedStep", step.getName()); } } } } if (stepStatus == BatchStatus.UNKNOWN) { throw new JobRestartException("Cannot restart step from UNKNOWN status. " + "The last execution ended with a failure that could not be rolled back, " + "so it may be dangerous to proceed. Manual intervention is probably necessary."); } if ((stepStatus == BatchStatus.COMPLETED && step.isAllowStartIfComplete() == false) || stepStatus == BatchStatus.ABANDONED) { // step is complete, false should be returned, indicating that the // step should not be started logger.info("Step already complete or not restartable, so no action to execute: " + lastStepExecution); return false; } if (getJobRepository().getStepExecutionCount(jobExecution.getJobInstance(), step.getName()) < step .getStartLimit()) { // step start count is less than start max, return true return true; } else { // start max has been exceeded, throw an exception. throw new StartLimitExceededException("Maximum start limit exceeded for step: " + step.getName() + "StartMax: " + step.getStartLimit()); } }
From source file:org.springframework.batch.core.launch.support.SimpleJobLauncher.java
/** * Run the provided job with the given {@link JobParameters}. The * {@link JobParameters} will be used to determine if this is an execution * of an existing job instance, or if a new one should be created. * * @param job the job to be run.//from ww w . jav a2 s .com * @param jobParameters the {@link JobParameters} for this particular * execution. * @return JobExecutionAlreadyRunningException if the JobInstance already * exists and has an execution already running. * @throws JobRestartException if the execution would be a re-start, but a * re-start is either not allowed or not needed. * @throws JobInstanceAlreadyCompleteException if this instance has already * completed successfully * @throws JobParametersInvalidException */ @Override public JobExecution run(final Job job, final JobParameters jobParameters) throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException { Assert.notNull(job, "The Job must not be null."); Assert.notNull(jobParameters, "The JobParameters must not be null."); final JobExecution jobExecution; JobExecution lastExecution = jobRepository.getLastJobExecution(job.getName(), jobParameters); if (lastExecution != null) { if (!job.isRestartable()) { throw new JobRestartException("JobInstance already exists and is not restartable"); } /* * validate here if it has stepExecutions that are UNKNOWN, STARTING, STARTED and STOPPING * retrieve the previous execution and check */ for (StepExecution execution : lastExecution.getStepExecutions()) { BatchStatus status = execution.getStatus(); if (status.isRunning() || status == BatchStatus.STOPPING) { throw new JobExecutionAlreadyRunningException( "A job execution for this job is already running: " + lastExecution); } else if (status == BatchStatus.UNKNOWN) { throw new JobRestartException("Cannot restart step [" + execution.getStepName() + "] from UNKNOWN status. " + "The last execution ended with a failure that could not be rolled back, " + "so it may be dangerous to proceed. Manual intervention is probably necessary."); } } } // Check the validity of the parameters before doing creating anything // in the repository... job.getJobParametersValidator().validate(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 * <i>and</i> fail a job execution for this instance between the last * assertion and the next method returning successfully. */ jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters); try { taskExecutor.execute(new Runnable() { @Override public void run() { 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() + "]"); } catch (Throwable t) { logger.info("Job: [" + job + "] failed unexpectedly and fatally with the following parameters: [" + jobParameters + "]", t); rethrow(t); } } private void rethrow(Throwable t) { if (t instanceof RuntimeException) { throw (RuntimeException) t; } else if (t instanceof Error) { throw (Error) t; } throw new IllegalStateException(t); } }); } catch (TaskRejectedException e) { jobExecution.upgradeStatus(BatchStatus.FAILED); if (jobExecution.getExitStatus().equals(ExitStatus.UNKNOWN)) { jobExecution.setExitStatus(ExitStatus.FAILED.addExitDescription(e)); } jobRepository.update(jobExecution); } return jobExecution; }
From source file:org.springframework.batch.core.launch.support.SimpleJobOperator.java
@Override @Transactional//from ww w . ja v a 2s .co m public boolean stop(long executionId) throws NoSuchJobExecutionException, JobExecutionNotRunningException { JobExecution jobExecution = findExecutionById(executionId); // Indicate the execution should be stopped by setting it's status to // 'STOPPING'. It is assumed that // the step implementation will check this status at chunk boundaries. 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); try { 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 //get the current stepExecution for (StepExecution stepExecution : jobExecution.getStepExecutions()) { if (stepExecution.getStatus().isRunning()) { try { //have the step execution that's running -> need to 'stop' it Step step = ((StepLocator) job).getStep(stepExecution.getStepName()); if (step instanceof TaskletStep) { Tasklet tasklet = ((TaskletStep) step).getTasklet(); if (tasklet instanceof StoppableTasklet) { StepSynchronizationManager.register(stepExecution); ((StoppableTasklet) tasklet).stop(); StepSynchronizationManager.release(); } } } catch (NoSuchStepException e) { logger.warn("Step not found", e); } } } } } catch (NoSuchJobException e) { logger.warn("Cannot find Job object", e); } return true; }
From source file:org.springframework.batch.core.repository.dao.JdbcStepExecutionDao.java
private List<Object[]> buildStepExecutionParameters(StepExecution stepExecution) { Assert.isNull(stepExecution.getId(), "to-be-saved (not updated) StepExecution can't already have an id assigned"); Assert.isNull(stepExecution.getVersion(), "to-be-saved (not updated) StepExecution can't already have a version assigned"); validateStepExecution(stepExecution); stepExecution.setId(stepExecutionIncrementer.nextLongValue()); stepExecution.incrementVersion(); //Should be 0 List<Object[]> parameters = new ArrayList<Object[]>(); String exitDescription = truncateExitDescription(stepExecution.getExitStatus().getExitDescription()); Object[] parameterValues = new Object[] { stepExecution.getId(), stepExecution.getVersion(), stepExecution.getStepName(), stepExecution.getJobExecutionId(), stepExecution.getStartTime(), stepExecution.getEndTime(), stepExecution.getStatus().toString(), stepExecution.getCommitCount(), stepExecution.getReadCount(), stepExecution.getFilterCount(), stepExecution.getWriteCount(), stepExecution.getExitStatus().getExitCode(), exitDescription, stepExecution.getReadSkipCount(), stepExecution.getWriteSkipCount(), stepExecution.getProcessSkipCount(), stepExecution.getRollbackCount(), stepExecution.getLastUpdated() }; Integer[] parameterTypes = new Integer[] { Types.BIGINT, Types.INTEGER, Types.VARCHAR, Types.BIGINT, Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.TIMESTAMP }; parameters.add(0, Arrays.copyOf(parameterValues, parameterValues.length)); parameters.add(1, Arrays.copyOf(parameterTypes, parameterTypes.length)); return parameters; }
From source file:org.springframework.batch.core.repository.dao.JdbcStepExecutionDao.java
/** * Validate StepExecution. At a minimum, JobId, StartTime, and Status cannot * be null. EndTime can be null for an unfinished job. * * @throws IllegalArgumentException/*from w w w . j a va2 s .c om*/ */ private void validateStepExecution(StepExecution stepExecution) { Assert.notNull(stepExecution); Assert.notNull(stepExecution.getStepName(), "StepExecution step name cannot be null."); Assert.notNull(stepExecution.getStartTime(), "StepExecution start time cannot be null."); Assert.notNull(stepExecution.getStatus(), "StepExecution status cannot be null."); }
From source file:org.springframework.batch.core.repository.dao.JdbcStepExecutionDao.java
@Override public void updateStepExecution(StepExecution stepExecution) { validateStepExecution(stepExecution); Assert.notNull(stepExecution.getId(), "StepExecution Id cannot be null. StepExecution must saved" + " before it can be updated."); // Do not check for existence of step execution considering // it is saved at every commit point. String exitDescription = truncateExitDescription(stepExecution.getExitStatus().getExitDescription()); // Attempt to prevent concurrent modification errors by blocking here if // someone is already trying to do it. synchronized (stepExecution) { Integer version = stepExecution.getVersion() + 1; Object[] parameters = new Object[] { stepExecution.getStartTime(), stepExecution.getEndTime(), stepExecution.getStatus().toString(), stepExecution.getCommitCount(), stepExecution.getReadCount(), stepExecution.getFilterCount(), stepExecution.getWriteCount(), stepExecution.getExitStatus().getExitCode(), exitDescription, version, stepExecution.getReadSkipCount(), stepExecution.getProcessSkipCount(), stepExecution.getWriteSkipCount(), stepExecution.getRollbackCount(), stepExecution.getLastUpdated(), stepExecution.getId(), stepExecution.getVersion() }; int count = getJdbcTemplate().update(getQuery(UPDATE_STEP_EXECUTION), parameters, new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.TIMESTAMP, Types.BIGINT, Types.INTEGER }); // Avoid concurrent modifications... if (count == 0) { int curentVersion = getJdbcTemplate().queryForObject(getQuery(CURRENT_VERSION_STEP_EXECUTION), new Object[] { stepExecution.getId() }, Integer.class); throw new OptimisticLockingFailureException( "Attempt to update step execution id=" + stepExecution.getId() + " with wrong version (" + stepExecution.getVersion() + "), where current version is " + curentVersion); }/*from w w w . j ava 2 s . c o m*/ stepExecution.incrementVersion(); } }
From source file:org.springframework.batch.core.step.AbstractStep.java
/** * Template method for step execution logic - calls abstract methods for resource initialization ( * {@link #open(ExecutionContext)}), execution logic ({@link #doExecute(StepExecution)}) and resource closing ( * {@link #close(ExecutionContext)})./* www. ja va2 s .co m*/ */ @Override public final void execute(StepExecution stepExecution) throws JobInterruptedException, UnexpectedJobExecutionException { if (logger.isDebugEnabled()) { logger.debug("Executing: id=" + stepExecution.getId()); } stepExecution.setStartTime(new Date()); stepExecution.setStatus(BatchStatus.STARTED); getJobRepository().update(stepExecution); // Start with a default value that will be trumped by anything ExitStatus exitStatus = ExitStatus.EXECUTING; doExecutionRegistration(stepExecution); try { getCompositeListener().beforeStep(stepExecution); open(stepExecution.getExecutionContext()); try { doExecute(stepExecution); } catch (RepeatException e) { throw e.getCause(); } exitStatus = ExitStatus.COMPLETED.and(stepExecution.getExitStatus()); // Check if someone is trying to stop us if (stepExecution.isTerminateOnly()) { throw new JobInterruptedException("JobExecution interrupted."); } // Need to upgrade here not set, in case the execution was stopped stepExecution.upgradeStatus(BatchStatus.COMPLETED); if (logger.isDebugEnabled()) { logger.debug("Step execution success: id=" + stepExecution.getId()); } } catch (Throwable e) { stepExecution.upgradeStatus(determineBatchStatus(e)); exitStatus = exitStatus.and(getDefaultExitStatusForFailure(e)); stepExecution.addFailureException(e); if (stepExecution.getStatus() == BatchStatus.STOPPED) { logger.info(String.format("Encountered interruption executing step %s in job %s : %s", name, stepExecution.getJobExecution().getJobInstance().getJobName(), e.getMessage())); if (logger.isDebugEnabled()) { logger.debug("Full exception", e); } } else { logger.error(String.format("Encountered an error executing step %s in job %s", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); } } finally { try { // Update the step execution to the latest known value so the // listeners can act on it exitStatus = exitStatus.and(stepExecution.getExitStatus()); stepExecution.setExitStatus(exitStatus); exitStatus = exitStatus.and(getCompositeListener().afterStep(stepExecution)); } catch (Exception e) { logger.error(String.format("Exception in afterStep callback in step %s in job %s", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); } try { getJobRepository().updateExecutionContext(stepExecution); } catch (Exception e) { stepExecution.setStatus(BatchStatus.UNKNOWN); exitStatus = exitStatus.and(ExitStatus.UNKNOWN); stepExecution.addFailureException(e); logger.error(String.format( "Encountered an error saving batch meta data for step %s in job %s. " + "This job is now in an unknown state and should not be restarted.", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); } stepExecution.setEndTime(new Date()); stepExecution.setExitStatus(exitStatus); try { getJobRepository().update(stepExecution); } catch (Exception e) { stepExecution.setStatus(BatchStatus.UNKNOWN); stepExecution.setExitStatus(exitStatus.and(ExitStatus.UNKNOWN)); stepExecution.addFailureException(e); logger.error(String.format( "Encountered an error saving batch meta data for step %s in job %s. " + "This job is now in an unknown state and should not be restarted.", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); } try { close(stepExecution.getExecutionContext()); } catch (Exception e) { logger.error(String.format("Exception while closing step execution resources in step %s in job %s", name, stepExecution.getJobExecution().getJobInstance().getJobName()), e); stepExecution.addFailureException(e); } doExecutionRelease(); if (logger.isDebugEnabled()) { logger.debug("Step execution complete: " + stepExecution.getSummary()); } } }
From source file:org.springframework.batch.core.step.item.FaultTolerantStepFactoryBeanNonBufferingTests.java
/** * Check items causing errors are skipped as expected. *//*from w w w . ja va 2 s . c om*/ @Test public void testSkip() throws Exception { @SuppressWarnings("unchecked") SkipListener<Integer, String> skipListener = mock(SkipListener.class); skipListener.onSkipInWrite("3", exception); skipListener.onSkipInWrite("4", exception); factory.setListeners(new SkipListener[] { skipListener }); Step step = factory.getObject(); StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); step.execute(stepExecution); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(2, stepExecution.getSkipCount()); assertEquals(0, stepExecution.getReadSkipCount()); assertEquals(2, stepExecution.getWriteSkipCount()); // only one exception caused rollback, and only once in this case // because all items in that chunk were skipped immediately assertEquals(1, stepExecution.getRollbackCount()); assertFalse(writer.written.contains("4")); List<String> expectedOutput = Arrays.asList(StringUtils.commaDelimitedListToStringArray("1,2,5")); assertEquals(expectedOutput, writer.written); // 5 items + 1 rollbacks reading 2 items each time assertEquals(7, stepExecution.getReadCount()); }
From source file:org.springframework.batch.core.step.item.FaultTolerantStepFactoryBeanRetryTests.java
@Test public void testRestartAfterFailedWrite() throws Exception { factory.setSkipLimit(0);/* ww w . ja va 2 s .c o m*/ factory.setCommitInterval(3); AbstractItemCountingItemStreamItemReader<String> reader = new AbstractItemCountingItemStreamItemReader<String>() { private ItemReader<String> reader; @Override protected void doClose() throws Exception { reader = null; } @Override protected void doOpen() throws Exception { reader = new ListItemReader<String>(Arrays.asList("a", "b", "c", "d", "e", "f")); } @Override protected String doRead() throws Exception { return reader.read(); } }; // Need to set name or else reader will fail to open reader.setName("foo"); factory.setItemReader(reader); factory.setStreams(new ItemStream[] { reader }); factory.setItemWriter(new ItemWriter<String>() { @Override public void write(List<? extends String> items) throws Exception { if (fail && items.contains("e")) { throw new RuntimeException("Planned failure"); } processed.addAll(items); } }); factory.setRetryLimit(0); Step step = factory.getObject(); fail = true; StepExecution stepExecution = new StepExecution(step.getName(), jobExecution); repository.add(stepExecution); step.execute(stepExecution); assertEquals(BatchStatus.FAILED, stepExecution.getStatus()); assertEquals(4, stepExecution.getWriteCount()); assertEquals(6, stepExecution.getReadCount()); fail = false; ExecutionContext executionContext = stepExecution.getExecutionContext(); stepExecution = new StepExecution(step.getName(), jobExecution); stepExecution.setExecutionContext(executionContext); repository.add(stepExecution); step.execute(stepExecution); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); assertEquals(2, stepExecution.getWriteCount()); assertEquals(2, stepExecution.getReadCount()); }