Example usage for org.springframework.batch.core BatchStatus STOPPED

List of usage examples for org.springframework.batch.core BatchStatus STOPPED

Introduction

In this page you can find the example usage for org.springframework.batch.core BatchStatus STOPPED.

Prototype

BatchStatus STOPPED

To view the source code for org.springframework.batch.core BatchStatus STOPPED.

Click Source Link

Usage

From source file:de.codecentric.batch.test.StopJobIntegrationTest.java

@Test
public void testRunJob() throws InterruptedException {
    Long executionId = restTemplate
            .postForObject("http://localhost:" + port + "/batch/operations/jobs/delayJob", "", Long.class);
    Thread.sleep(500);/* w  w  w  . ja  v a 2  s  . c  om*/
    String runningExecutions = restTemplate.getForObject(
            "http://localhost:" + port + "/batch/monitoring/jobs/runningexecutions", String.class);
    assertThat(runningExecutions.contains(executionId.toString()), is(true));
    String runningExecutionsForDelayJob = restTemplate.getForObject(
            "http://localhost:" + port + "/batch/monitoring/jobs/runningexecutions/delayJob", String.class);
    assertThat(runningExecutionsForDelayJob.contains(executionId.toString()), is(true));
    restTemplate.delete("http://localhost:" + port + "/batch/operations/jobs/executions/{executionId}",
            executionId);
    Thread.sleep(1500);

    JobExecution jobExecution = jobExplorer.getJobExecution(executionId);
    assertThat(jobExecution.getStatus(), is(BatchStatus.STOPPED));
    String jobExecutionString = restTemplate.getForObject(
            "http://localhost:" + port + "/batch/monitoring/jobs/executions/{executionId}", String.class,
            executionId);
    assertThat(jobExecutionString.contains("STOPPED"), is(true));
}

From source file:org.jasig.ssp.util.importer.job.BatchPartialUploadTest.java

@SuppressWarnings("unchecked")
@Test//from  ww w .  jav  a 2s . c  om
public void testDirectoryNoFiles() throws Exception {

    deleteDirectory(inputDirectoryPath);
    createDirectory(inputDirectoryPath);
    Assert.assertTrue(directoryExists(inputDirectoryPath));

    JobExecution jobExecution = jobLauncherTestUtils.launchJob();
    BatchStatus exitStatus = jobExecution.getStatus();

    Map<String, ReportEntry> report = (Map<String, ReportEntry>) jobExecution.getExecutionContext()
            .get("report");
    Assert.assertNull(report);

    Assert.assertEquals(BatchStatus.STOPPED, exitStatus);

    Assert.assertTrue(directoryExists(inputDirectoryPath));

}

From source file:com.enterra.batch.admin.sample.BootstrapTests.java

@Test
public void testServletConfiguration() throws Exception {
    ClassPathXmlApplicationContext parent = new ClassPathXmlApplicationContext(
            "classpath:/org/springframework/batch/admin/web/resources/webapp-config.xml");
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
            new String[] { "classpath:/org/springframework/batch/admin/web/resources/servlet-config.xml" },
            parent);/*w  w w .j  av  a  2  s .c  o m*/

    assertTrue(context.containsBean("jobRepository"));
    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context.getBeanFactory(),
            JobController.class);
    assertEquals(1, beanNames.length);

    Job job = context.getBean(JobRegistry.class).getJob("job1");
    final JobExecution jobExecution = parent.getBean(JobLauncher.class).run(job,
            new JobParametersBuilder().addString("fail", "false").toJobParameters());

    new DirectPoller<BatchStatus>(100).poll(new Callable<BatchStatus>() {
        public BatchStatus call() throws Exception {
            BatchStatus status = jobExecution.getStatus();
            if (status.isLessThan(BatchStatus.STOPPED) && status != BatchStatus.COMPLETED) {
                return null;
            }
            return status;
        }
    }).get(2000, TimeUnit.MILLISECONDS);

    context.close();
    parent.close();

    assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());

}

From source file:org.jasig.ssp.util.importer.job.BatchPartialUploadTest.java

@SuppressWarnings("unchecked")
@Test/*w ww. j a  v a2s.  c  o m*/
public void testPartialUploadGuard() throws Exception {

    deleteDirectory(inputDirectoryPath);
    createFiles(inputDirectoryPath);

    Assert.assertTrue(directoryContainsFiles(inputDirectoryPath, 3, csvFilter));

    JobExecution jobExecution = jobLauncherTestUtils.launchJob();
    BatchStatus exitStatus = jobExecution.getStatus();

    Map<String, ReportEntry> report = (Map<String, ReportEntry>) jobExecution.getExecutionContext()
            .get("report");
    Assert.assertNull(report);

    Assert.assertEquals(BatchStatus.STOPPED, exitStatus);

    Assert.assertTrue(directoryExists(inputDirectoryPath));
    Assert.assertTrue(directoryContainsFiles(inputDirectoryPath, 3, csvFilter));

}

From source file:org.geoserver.backuprestore.web.BackupRestorePage.java

void initComponents(final IModel<T> model) {
    add(new Label("id", new PropertyModel(model, "id")));
    add(new Label("clazz", new Model(
            this.clazz.getSimpleName().substring(0, this.clazz.getSimpleName().indexOf("Execution")))));

    BackupRestoreExecutionsProvider provider = new BackupRestoreExecutionsProvider(getType()) {
        @Override//from  w  ww  .j a  v  a2 s  .  c  o  m
        protected List<Property<AbstractExecutionAdapter>> getProperties() {
            return Arrays.asList(ID, STATE, STARTED, PROGRESS, ARCHIVEFILE, OPTIONS);
        }

        @Override
        protected List<T> getItems() {
            return Collections.singletonList(model.getObject());
        }
    };

    final BackupRestoreExecutionsTable headerTable = new BackupRestoreExecutionsTable("header", provider,
            getType());

    headerTable.setOutputMarkupId(true);
    headerTable.setFilterable(false);
    headerTable.setPageable(false);
    add(headerTable);

    final T bkp = model.getObject();
    boolean selectable = bkp.getStatus() != BatchStatus.COMPLETED;

    add(new Icon("icon", COMPRESS_ICON));
    add(new Label("title", new DataTitleModel(bkp))
            .add(new AttributeModifier("title", new DataTitleModel(bkp, false))));

    @SuppressWarnings("rawtypes")
    Form<?> form = new Form("form");
    add(form);

    try {
        if (params != null && params.getNamedKeys().contains(DETAILS_LEVEL)) {
            if (params.get(DETAILS_LEVEL).toInt() > 0) {
                expand = params.get(DETAILS_LEVEL).toInt();
            }
        }
    } catch (Exception e) {
        LOGGER.log(Level.WARNING, "Error parsing the 'details level' parameter: ",
                params.get(DETAILS_LEVEL).toString());
    }

    form.add(new SubmitLink("refresh") {
        @Override
        public void onSubmit() {
            setResponsePage(BackupRestorePage.class, new PageParameters().add("id", params.get("id").toLong())
                    .add("clazz", getType().getSimpleName()).add(DETAILS_LEVEL, expand));
        }
    });

    NumberTextField<Integer> expand = new NumberTextField<Integer>("expand",
            new PropertyModel<Integer>(this, "expand"));
    expand.add(RangeValidator.minimum(0));
    form.add(expand);

    TextArea<String> details = new TextArea<String>("details", new BKErrorDetailsModel(bkp));
    details.setOutputMarkupId(true);
    details.setMarkupId("details");
    add(details);

    String location = bkp.getArchiveFile().path();
    if (location == null) {
        location = getGeoServerApplication().getGeoServer().getLogging().getLocation();
    }
    backupFile = new File(location);
    if (!backupFile.isAbsolute()) {
        // locate the geoserver.log file
        GeoServerDataDirectory dd = getGeoServerApplication().getBeanOfType(GeoServerDataDirectory.class);
        backupFile = dd.get(Paths.convert(backupFile.getPath())).file();
    }

    if (!backupFile.exists()) {
        error("Could not find the Backup Archive file: " + backupFile.getAbsolutePath());
    }

    /***
     * DOWNLOAD LINK
     */
    final Link<Object> downLoadLink = new Link<Object>("download") {

        @Override
        public void onClick() {
            IResourceStream stream = new FileResourceStream(backupFile) {
                public String getContentType() {
                    return "application/zip";
                }
            };
            ResourceStreamRequestHandler handler = new ResourceStreamRequestHandler(stream,
                    backupFile.getName());
            handler.setContentDisposition(ContentDisposition.ATTACHMENT);

            RequestCycle.get().scheduleRequestHandlerAfterCurrent(handler);
        }
    };
    add(downLoadLink);

    /***
     * PAUSE LINK
     */
    final AjaxLink pauseLink = new AjaxLink("pause") {

        @Override
        protected void disableLink(ComponentTag tag) {
            super.disableLink(tag);
            tag.setName("a");
            tag.addBehavior(AttributeModifier.replace("class", "disabled"));
        }

        @Override
        public void onClick(AjaxRequestTarget target) {
            AbstractExecutionAdapter bkp = model.getObject();
            if (bkp.getStatus() == BatchStatus.STOPPED) {
                setLinkEnabled((AjaxLink) downLoadLink.getParent().get("pause"), false, target);
            } else {
                try {
                    backupFacade().stopExecution(bkp.getId());

                    setResponsePage(BackupRestoreDataPage.class);
                } catch (NoSuchJobExecutionException | JobExecutionNotRunningException e) {
                    LOGGER.log(Level.WARNING, "", e);
                    getSession().error(e);
                    setResponsePage(BackupRestoreDataPage.class);
                }
            }
        }

    };
    pauseLink.setEnabled(doSelectReady(bkp) && bkp.getStatus() != BatchStatus.STOPPED);
    add(pauseLink);

    /***
     * RESUME LINK
     */
    final AjaxLink resumeLink = new AjaxLink("resume") {

        @Override
        protected void disableLink(ComponentTag tag) {
            super.disableLink(tag);
            tag.setName("a");
            tag.addBehavior(AttributeModifier.replace("class", "disabled"));
        }

        @Override
        public void onClick(AjaxRequestTarget target) {
            AbstractExecutionAdapter bkp = model.getObject();
            if (bkp.getStatus() != BatchStatus.STOPPED) {
                setLinkEnabled((AjaxLink) downLoadLink.getParent().get("pause"), false, target);
            } else {
                try {
                    Long id = backupFacade().restartExecution(bkp.getId());

                    PageParameters pp = new PageParameters();
                    pp.add("id", id);
                    if (bkp instanceof BackupExecutionAdapter) {
                        pp.add("clazz", BackupExecutionAdapter.class.getSimpleName());
                    } else if (bkp instanceof RestoreExecutionAdapter) {
                        pp.add("clazz", RestoreExecutionAdapter.class.getSimpleName());
                    }

                    setResponsePage(BackupRestorePage.class, pp);
                } catch (NoSuchJobExecutionException | JobInstanceAlreadyCompleteException | NoSuchJobException
                        | JobRestartException | JobParametersInvalidException e) {
                    LOGGER.log(Level.WARNING, "", e);
                    getSession().error(e);
                    setResponsePage(BackupRestoreDataPage.class);
                }
            }
        }

    };
    resumeLink.setEnabled(bkp.getStatus() == BatchStatus.STOPPED);
    add(resumeLink);

    /***
     * ABANDON LINK
     */
    final AjaxLink cancelLink = new AjaxLink("cancel") {

        @Override
        protected void disableLink(ComponentTag tag) {
            super.disableLink(tag);
            tag.setName("a");
            tag.addBehavior(AttributeModifier.replace("class", "disabled"));
        }

        @Override
        public void onClick(AjaxRequestTarget target) {
            AbstractExecutionAdapter bkp = model.getObject();
            if (!doSelectReady(bkp)) {
                setLinkEnabled((AjaxLink) downLoadLink.getParent().get("cancel"), false, target);
            } else {
                try {
                    backupFacade().abandonExecution(bkp.getId());

                    PageParameters pp = new PageParameters();
                    pp.add("id", bkp.getId());
                    if (bkp instanceof BackupExecutionAdapter) {
                        pp.add("clazz", BackupExecutionAdapter.class.getSimpleName());
                    } else if (bkp instanceof RestoreExecutionAdapter) {
                        pp.add("clazz", RestoreExecutionAdapter.class.getSimpleName());
                    }

                    setResponsePage(BackupRestorePage.class, pp);
                } catch (NoSuchJobExecutionException | JobExecutionAlreadyRunningException e) {
                    error(e);
                    LOGGER.log(Level.WARNING, "", e);
                }
            }
        }

    };
    cancelLink.setEnabled(doSelectReady(bkp));
    add(cancelLink);

    /***
     * DONE LINK
     */
    final AjaxLink doneLink = new AjaxLink("done") {

        @Override
        protected void disableLink(ComponentTag tag) {
            super.disableLink(tag);
            tag.setName("a");
            tag.addBehavior(AttributeModifier.replace("class", "disabled"));
        }

        @Override
        public void onClick(AjaxRequestTarget target) {
            setResponsePage(BackupRestoreDataPage.class);
            return;
        }

    };
    add(doneLink);

    /**
     * FINALIZE
     */
    add(dialog = new GeoServerDialog("dialog"));
}

From source file:org.springframework.batch.admin.BootstrapTests.java

@Test
public void testServletConfiguration() throws Exception {
    ClassPathXmlApplicationContext parent = new ClassPathXmlApplicationContext(
            "classpath:/org/springframework/batch/admin/web/resources/webapp-config.xml");
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
            new String[] { "classpath:/org/springframework/batch/admin/web/resources/servlet-config.xml" },
            parent);/*from www .  j  av  a  2  s. c o  m*/

    assertTrue(context.containsBean("jobRepository"));
    String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context.getBeanFactory(),
            JobController.class);
    assertEquals(1, beanNames.length);

    MenuManager menuManager = context.getBean(MenuManager.class);
    assertEquals(4, menuManager.getMenus().size());

    context.refresh();

    ClassPathXmlApplicationContext child = new ClassPathXmlApplicationContext(
            new String[] { "classpath:/test-job-context.xml" }, parent);
    Job job = child.getBean(Job.class);
    final JobExecution jobExecution = parent.getBean(JobLauncher.class).run(job, new JobParameters());

    new DirectPoller<BatchStatus>(100).poll(new Callable<BatchStatus>() {
        public BatchStatus call() throws Exception {
            BatchStatus status = jobExecution.getStatus();
            if (status.isLessThan(BatchStatus.STOPPED) && status != BatchStatus.COMPLETED) {
                return null;
            }
            return status;
        }
    }).get(2000, TimeUnit.MILLISECONDS);

    HomeController metaData = new HomeController();
    metaData.setApplicationContext(context);
    metaData.afterPropertiesSet();
    MockHttpServletRequest request = new MockHttpServletRequest();
    ModelMap model = new ModelMap();
    metaData.getResources(request, model);
    @SuppressWarnings("unchecked")
    List<ResourceInfo> resources = (List<ResourceInfo>) model.get("resources");
    StringBuilder content = new StringBuilder();
    for (ResourceInfo resourceInfo : resources) {
        content.append(resourceInfo.getMethod() + resourceInfo.getUrl() + "=\n");
    }
    FileUtils.writeStringToFile(new File("target/resources.properties"), content.toString());

    HomeController home = context.getBean(HomeController.class);
    // System.err.println(home.getUrlPatterns());
    assertTrue(home.getUrlPatterns().contains("/jobs/{jobName}"));

    String message = context.getMessage("GET/jobs/{jobName}", new Object[0], Locale.getDefault());
    assertTrue("No message for /jobs/{jobName}", StringUtils.hasText(message));

    child.close();
    context.close();
    parent.close();

    assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());

}

From source file:org.springframework.batch.admin.web.server.JsonIntegrationTests.java

@Test
public void testJobStop() throws Exception {

    RestTemplate template = new RestTemplate();
    ResponseEntity<String> result = template.exchange(serverRunning.getUrl()
            + "/jobs/infinite.json?jobParameters=timestamp=" + System.currentTimeMillis(), HttpMethod.POST,
            null, String.class);
    JsonWrapper wrapper = new JsonWrapper(result.getBody());
    // System.err.println(wrapper);
    assertNotNull(wrapper.get("jobExecution.resource"));
    assertNotNull(wrapper.get("jobExecution.status"));
    assertNotNull(wrapper.get("jobExecution.id"));

    template.exchange(wrapper.get("jobExecution.resource", String.class), HttpMethod.DELETE, null,
            String.class);

    // Poll for the completed job execution
    final String resource = wrapper.get("jobExecution.resource", String.class);
    Poller<JsonWrapper> poller = new DirectPoller<JsonWrapper>(100L);
    Future<JsonWrapper> poll = poller.poll(new Callable<JsonWrapper>() {
        public JsonWrapper call() throws Exception {
            RestTemplate template = new RestTemplate();
            ResponseEntity<String> result = template.exchange(resource, HttpMethod.GET, null, String.class);
            JsonWrapper wrapper = new JsonWrapper(result.getBody());
            // System.err.println(wrapper);
            BatchStatus status = wrapper.get("jobExecution.status", BatchStatus.class);
            return status.isGreaterThan(BatchStatus.STOPPING) ? wrapper : null;
        }/*w ww  . j  av  a 2 s.c  o  m*/
    });
    JsonWrapper jobExecution = poll.get(500L, TimeUnit.MILLISECONDS);
    assertNotNull(jobExecution);

    BatchStatus status = jobExecution.get("jobExecution.status", BatchStatus.class);
    assertEquals(BatchStatus.STOPPED, status);

}

From source file:org.springframework.batch.core.job.AbstractJob.java

/**
 * Run the specified job, handling all listener and repository calls, and
 * delegating the actual processing to {@link #doExecute(JobExecution)}.
 *
 * @see Job#execute(JobExecution)/*  w w  w  .j  av a 2 s.c  om*/
 * @throws StartLimitExceededException
 *             if start limit of one of the steps was exceeded
 */
@Override
public final void execute(JobExecution execution) {

    if (logger.isDebugEnabled()) {
        logger.debug("Job execution starting: " + execution);
    }

    JobSynchronizationManager.register(execution);

    try {

        jobParametersValidator.validate(execution.getJobParameters());

        if (execution.getStatus() != BatchStatus.STOPPING) {

            execution.setStartTime(new Date());
            updateStatus(execution, BatchStatus.STARTED);

            listener.beforeJob(execution);

            try {
                doExecute(execution);
                if (logger.isDebugEnabled()) {
                    logger.debug("Job execution complete: " + execution);
                }
            } catch (RepeatException e) {
                throw e.getCause();
            }
        } else {

            // The job was already stopped before we even got this far. Deal
            // with it in the same way as any other interruption.
            execution.setStatus(BatchStatus.STOPPED);
            execution.setExitStatus(ExitStatus.COMPLETED);
            if (logger.isDebugEnabled()) {
                logger.debug("Job execution was stopped: " + execution);
            }

        }

    } catch (JobInterruptedException e) {
        logger.info("Encountered interruption executing job: " + e.getMessage());
        if (logger.isDebugEnabled()) {
            logger.debug("Full exception", e);
        }
        execution.setExitStatus(getDefaultExitStatusForFailure(e, execution));
        execution.setStatus(BatchStatus.max(BatchStatus.STOPPED, e.getStatus()));
        execution.addFailureException(e);
    } catch (Throwable t) {
        logger.error("Encountered fatal error executing job", t);
        execution.setExitStatus(getDefaultExitStatusForFailure(t, execution));
        execution.setStatus(BatchStatus.FAILED);
        execution.addFailureException(t);
    } finally {
        try {
            if (execution.getStatus().isLessThanOrEqualTo(BatchStatus.STOPPED)
                    && execution.getStepExecutions().isEmpty()) {
                ExitStatus exitStatus = execution.getExitStatus();
                ExitStatus newExitStatus = ExitStatus.NOOP
                        .addExitDescription("All steps already completed or no steps configured for this job.");
                execution.setExitStatus(exitStatus.and(newExitStatus));
            }

            execution.setEndTime(new Date());

            try {
                listener.afterJob(execution);
            } catch (Exception e) {
                logger.error("Exception encountered in afterStep callback", e);
            }

            jobRepository.update(execution);
        } finally {
            JobSynchronizationManager.release();
        }

    }

}

From source file:org.springframework.batch.core.job.SimpleStepHandler.java

@Override
public StepExecution handleStep(Step step, JobExecution execution)
        throws JobInterruptedException, JobRestartException, StartLimitExceededException {
    if (execution.isStopping()) {
        throw new JobInterruptedException("JobExecution interrupted.");
    }/* ww  w . ja  v a2s . co  m*/

    JobInstance jobInstance = execution.getJobInstance();

    StepExecution lastStepExecution = jobRepository.getLastStepExecution(jobInstance, step.getName());
    if (stepExecutionPartOfExistingJobExecution(execution, lastStepExecution)) {
        // If the last execution of this step was in the same job, it's
        // probably intentional so we want to run it again...
        logger.info(String.format(
                "Duplicate step [%s] detected in execution of job=[%s]. "
                        + "If either step fails, both will be executed again on restart.",
                step.getName(), jobInstance.getJobName()));
        lastStepExecution = null;
    }
    StepExecution currentStepExecution = lastStepExecution;

    if (shouldStart(lastStepExecution, execution, step)) {

        currentStepExecution = execution.createStepExecution(step.getName());

        boolean isRestart = (lastStepExecution != null
                && !lastStepExecution.getStatus().equals(BatchStatus.COMPLETED));

        if (isRestart) {
            currentStepExecution.setExecutionContext(lastStepExecution.getExecutionContext());

            if (lastStepExecution.getExecutionContext().containsKey("batch.executed")) {
                currentStepExecution.getExecutionContext().remove("batch.executed");
            }
        } else {
            currentStepExecution.setExecutionContext(new ExecutionContext(executionContext));
        }

        jobRepository.add(currentStepExecution);

        logger.info("Executing step: [" + step.getName() + "]");
        try {
            step.execute(currentStepExecution);
            currentStepExecution.getExecutionContext().put("batch.executed", true);
        } catch (JobInterruptedException e) {
            // Ensure that the job gets the message that it is stopping
            // and can pass it on to other steps that are executing
            // concurrently.
            execution.setStatus(BatchStatus.STOPPING);
            throw e;
        }

        jobRepository.updateExecutionContext(execution);

        if (currentStepExecution.getStatus() == BatchStatus.STOPPING
                || currentStepExecution.getStatus() == BatchStatus.STOPPED) {
            // Ensure that the job gets the message that it is stopping
            execution.setStatus(BatchStatus.STOPPING);
            throw new JobInterruptedException("Job interrupted by step execution");
        }

    }

    return currentStepExecution;
}

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 www.j  a  v a2 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
 */
@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());
    }
}