Fix OptimisticLockingFailureTests#testAsyncStopOfStartingJob

This test was failing intermittently due to an incorrect
way of waiting for a job execution to finish, which is:

```
while(jobExecution.isRunning()) {
   // wait for async launched job to complete execution
}
```

`JobExecution#isRunning()` is based on the status
of the job execution in memory which might not be
persisted yet. Here is an excerpt from the Javadoc:

```
Test if this JobExecution indicates that it is
running. It should be noted that this does not
necessarily mean that it has been persisted as
such yet.
```

That's why in the case where `isRunning` returns
false and the JobExecution is not persisted yet
(which is still in a running status in db),
the second attempt of re-running the job fails
with a `JobExecutionAlreadyRunningException`.

This commit fixes the loop by continuously
checking the status of the Job execution
in the job repository until it reaches one
of the end statuses.

Issue #1121
This commit is contained in:
Mahmoud Ben Hassine
2020-11-17 15:03:05 +01:00
parent 1090731302
commit cf2642223d

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,18 +18,22 @@ package org.springframework.batch.core.repository.dao;
import static org.junit.Assert.assertTrue;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.JobOperator;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.item.ItemWriter;
@@ -39,6 +43,10 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.lang.Nullable;
public class OptimisticLockingFailureTests {
private static final Set<BatchStatus> END_STATUSES =
EnumSet.of(BatchStatus.COMPLETED, BatchStatus.FAILED, BatchStatus.STOPPED);
@Test
public void testAsyncStopOfStartingJob() throws Exception {
ApplicationContext applicationContext =
@@ -46,17 +54,20 @@ public class OptimisticLockingFailureTests {
Job job = applicationContext.getBean(Job.class);
JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class);
JobOperator jobOperator = applicationContext.getBean(JobOperator.class);
JobRepository jobRepository = applicationContext.getBean(JobRepository.class);
JobExecution jobExecution = jobLauncher.run(job, new JobParametersBuilder()
JobParameters jobParameters = new JobParametersBuilder()
.addLong("test", 1L)
.toJobParameters());
.toJobParameters();
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
Thread.sleep(1000);
jobOperator.stop(jobExecution.getId());
while(jobExecution.isRunning()) {
// wait for async launched job to complete execution
JobExecution lastJobExecution = jobRepository.getLastJobExecution("locking", jobParameters);
while (lastJobExecution != null && !END_STATUSES.contains(lastJobExecution.getStatus())) {
lastJobExecution = jobRepository.getLastJobExecution("locking", jobParameters);
}
int numStepExecutions = jobExecution.getStepExecutions().size();
@@ -70,14 +81,13 @@ public class OptimisticLockingFailureTests {
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));
JobExecution restartJobExecution = jobLauncher.run(job, new JobParametersBuilder()
.addLong("test", 1L)
.toJobParameters());
JobExecution restartJobExecution = jobLauncher.run(job, jobParameters);
Thread.sleep(1000);
while(restartJobExecution.isRunning()) {
// wait for async launched job to complete execution
lastJobExecution = jobRepository.getLastJobExecution("locking", jobParameters);
while (lastJobExecution != null && !END_STATUSES.contains(lastJobExecution.getStatus())) {
lastJobExecution = jobRepository.getLastJobExecution("locking", jobParameters);
}
int restartNumStepExecutions = restartJobExecution.getStepExecutions().size();