public JobExecution launch(String jobName, JobParameters jobParameters)
      throws NoSuchJobException, JobExecutionAlreadyRunningException, JobRestartException,
          JobInstanceAlreadyCompleteException, JobParametersInvalidException {

    Job job = jobLocator.getJob(jobName);

    JobExecution lastJobExecution = jobRepository.getLastJobExecution(jobName, jobParameters);
    boolean restart = false;
    if (lastJobExecution != null) {
      BatchStatus status = lastJobExecution.getStatus();
      if (status.isUnsuccessful() && status != BatchStatus.ABANDONED) {
        restart = true;
      }
    }

    if (job.getJobParametersIncrementer() != null && !restart) {
      jobParameters = job.getJobParametersIncrementer().getNext(jobParameters);
    }

    JobExecution jobExecution = jobLauncher.run(job, jobParameters);

    if (jobExecution.isRunning()) {
      activeExecutions.add(jobExecution);
    }
    return jobExecution;
  }
  @Test
  public void testRunRestartableJobInstanceTwice() throws Exception {
    job =
        new JobSupport("foo") {
          @Override
          public boolean isRestartable() {
            return true;
          }

          @Override
          public void execute(JobExecution execution) {
            execution.setExitStatus(ExitStatus.COMPLETED);
            return;
          }
        };

    testRun();
    reset(jobRepository);
    expect(jobRepository.getLastJobExecution(job.getName(), jobParameters))
        .andReturn(new JobExecution(new JobInstance(1L, jobParameters, job.getName())));
    expect(jobRepository.createJobExecution(job.getName(), jobParameters))
        .andReturn(new JobExecution(new JobInstance(1L, jobParameters, job.getName())));
    replay(jobRepository);
    jobLauncher.run(job, jobParameters);
    verify(jobRepository);
  }
  @Test
  public void testTaskExecutorRejects() throws Exception {

    final List<String> list = new ArrayList<String>();
    jobLauncher.setTaskExecutor(
        new TaskExecutor() {
          @Override
          public void execute(Runnable task) {
            list.add("execute");
            throw new TaskRejectedException("Planned failure");
          }
        });

    JobExecution jobExecution = new JobExecution(null, null);

    expect(jobRepository.getLastJobExecution(job.getName(), jobParameters)).andReturn(null);
    expect(jobRepository.createJobExecution(job.getName(), jobParameters)).andReturn(jobExecution);
    jobRepository.update(jobExecution);
    expectLastCall();
    replay(jobRepository);

    jobLauncher.afterPropertiesSet();
    try {
      jobLauncher.run(job, jobParameters);
    } finally {
      assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
      assertEquals(ExitStatus.FAILED.getExitCode(), jobExecution.getExitStatus().getExitCode());
      verify(jobRepository);
    }

    assertEquals(1, list.size());
  }
  private void run(ExitStatus exitStatus) throws Exception {
    JobExecution jobExecution = new JobExecution(null, null);

    expect(jobRepository.getLastJobExecution(job.getName(), jobParameters)).andReturn(null);
    expect(jobRepository.createJobExecution(job.getName(), jobParameters)).andReturn(jobExecution);
    replay(jobRepository);

    jobLauncher.afterPropertiesSet();
    try {
      jobLauncher.run(job, jobParameters);
    } finally {
      assertEquals(exitStatus, jobExecution.getExitStatus());
      verify(jobRepository);
    }
  }
  @Test(expected = JobParametersInvalidException.class)
  public void testRunWithValidator() throws Exception {

    job.setJobParametersValidator(
        new DefaultJobParametersValidator(new String[] {"missing-and-required"}, new String[0]));

    expect(jobRepository.getLastJobExecution(job.getName(), jobParameters)).andReturn(null);
    replay(jobRepository);

    jobLauncher.afterPropertiesSet();
    try {
      jobLauncher.run(job, jobParameters);
    } finally {
      verify(jobRepository);
    }
  }