Skip to content

Commit 74e9564

Browse files
committed
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 spring-projects#1121
1 parent 05b782c commit 74e9564

File tree

1 file changed

+19
-9
lines changed

1 file changed

+19
-9
lines changed

spring-batch-core/src/test/java/org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests.java

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,22 @@
1818

1919
import static org.junit.Assert.assertTrue;
2020

21+
import java.util.EnumSet;
2122
import java.util.List;
23+
import java.util.Set;
2224

2325
import org.junit.Test;
2426

2527
import org.springframework.batch.core.BatchStatus;
2628
import org.springframework.batch.core.Job;
2729
import org.springframework.batch.core.JobExecution;
30+
import org.springframework.batch.core.JobParameters;
2831
import org.springframework.batch.core.JobParametersBuilder;
2932
import org.springframework.batch.core.StepContribution;
3033
import org.springframework.batch.core.StepExecution;
3134
import org.springframework.batch.core.launch.JobLauncher;
3235
import org.springframework.batch.core.launch.JobOperator;
36+
import org.springframework.batch.core.repository.JobRepository;
3337
import org.springframework.batch.core.scope.context.ChunkContext;
3438
import org.springframework.batch.core.step.tasklet.Tasklet;
3539
import org.springframework.batch.item.ItemWriter;
@@ -39,24 +43,31 @@
3943
import org.springframework.lang.Nullable;
4044

4145
public class OptimisticLockingFailureTests {
46+
47+
private static final Set<BatchStatus> END_STATUSES =
48+
EnumSet.of(BatchStatus.COMPLETED, BatchStatus.FAILED, BatchStatus.STOPPED);
49+
4250
@Test
4351
public void testAsyncStopOfStartingJob() throws Exception {
4452
ApplicationContext applicationContext =
4553
new ClassPathXmlApplicationContext("org/springframework/batch/core/repository/dao/OptimisticLockingFailureTests-context.xml");
4654
Job job = applicationContext.getBean(Job.class);
4755
JobLauncher jobLauncher = applicationContext.getBean(JobLauncher.class);
4856
JobOperator jobOperator = applicationContext.getBean(JobOperator.class);
57+
JobRepository jobRepository = applicationContext.getBean(JobRepository.class);
4958

50-
JobExecution jobExecution = jobLauncher.run(job, new JobParametersBuilder()
59+
JobParameters jobParameters = new JobParametersBuilder()
5160
.addLong("test", 1L)
52-
.toJobParameters());
61+
.toJobParameters();
62+
JobExecution jobExecution = jobLauncher.run(job, jobParameters);
5363

5464
Thread.sleep(1000);
5565

5666
jobOperator.stop(jobExecution.getId());
5767

58-
while(jobExecution.isRunning()) {
59-
// wait for async launched job to complete execution
68+
JobExecution lastJobExecution = jobRepository.getLastJobExecution("locking", jobParameters);
69+
while (lastJobExecution != null && !END_STATUSES.contains(lastJobExecution.getStatus())) {
70+
lastJobExecution = jobRepository.getLastJobExecution("locking", jobParameters);
6071
}
6172

6273
int numStepExecutions = jobExecution.getStepExecutions().size();
@@ -70,14 +81,13 @@ public void testAsyncStopOfStartingJob() throws Exception {
7081
assertTrue("Step execution status should be STOPPED but got: " + stepExecutionStatus, stepExecutionStatus.equals(BatchStatus.STOPPED));
7182
assertTrue("Job execution status should be STOPPED but got:" + jobExecutionStatus, jobExecutionStatus.equals(BatchStatus.STOPPED));
7283

73-
JobExecution restartJobExecution = jobLauncher.run(job, new JobParametersBuilder()
74-
.addLong("test", 1L)
75-
.toJobParameters());
84+
JobExecution restartJobExecution = jobLauncher.run(job, jobParameters);
7685

7786
Thread.sleep(1000);
7887

79-
while(restartJobExecution.isRunning()) {
80-
// wait for async launched job to complete execution
88+
lastJobExecution = jobRepository.getLastJobExecution("locking", jobParameters);
89+
while (lastJobExecution != null && !END_STATUSES.contains(lastJobExecution.getStatus())) {
90+
lastJobExecution = jobRepository.getLastJobExecution("locking", jobParameters);
8191
}
8292

8393
int restartNumStepExecutions = restartJobExecution.getStepExecutions().size();

0 commit comments

Comments
 (0)