Skip to content

Commit a5595bf

Browse files
committed
Fix job execution validation in SimpleJobRepository
Before this commit, the logic that validates if a job instance is complete or not was based only on the size of previous parameters, without checking if they are identifying or not. This commit introduces a change that uses only identifying job parameters to identify a job instance and validate its previous executions. Issue #1221
1 parent c3b2e26 commit a5595bf

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/repository/support/SimpleJobRepository.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2020 the original author or authors.
2+
* Copyright 2006-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
2121
import org.springframework.batch.core.BatchStatus;
2222
import org.springframework.batch.core.JobExecution;
2323
import org.springframework.batch.core.JobInstance;
24+
import org.springframework.batch.core.JobParameter;
2425
import org.springframework.batch.core.JobParameters;
2526
import org.springframework.batch.core.StepExecution;
2627
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
@@ -132,7 +133,9 @@ public JobExecution createJobExecution(String jobName, JobParameters jobParamete
132133
+ "The last execution ended with a failure that could not be rolled back, "
133134
+ "so it may be dangerous to proceed. Manual intervention is probably necessary.");
134135
}
135-
if (execution.getJobParameters().getParameters().size() > 0 && (status == BatchStatus.COMPLETED || status == BatchStatus.ABANDONED)) {
136+
Collection<JobParameter> allJobParameters = execution.getJobParameters().getParameters().values();
137+
long identifyingJobParametersCount = allJobParameters.stream().filter(JobParameter::isIdentifying).count();
138+
if (identifyingJobParametersCount > 0 && (status == BatchStatus.COMPLETED || status == BatchStatus.ABANDONED)) {
136139
throw new JobInstanceAlreadyCompleteException(
137140
"A job instance already exists and is complete for parameters=" + jobParameters
138141
+ ". If you want to run this job again, change the parameters.");

spring-batch-core/src/test/java/org/springframework/batch/core/repository/support/SimpleJobRepositoryIntegrationTests.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2018 the original author or authors.
2+
* Copyright 2008-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -44,6 +44,7 @@
4444
*
4545
* @author Robert Kasanicky
4646
* @author Dimitrios Liapis
47+
* @author Mahmoud Ben Hassine
4748
*/
4849
@RunWith(SpringJUnit4ClassRunner.class)
4950
@ContextConfiguration(locations = "/org/springframework/batch/core/repository/dao/sql-dao-test.xml")
@@ -212,4 +213,23 @@ public void testGetLastJobExecution() throws Exception {
212213
assertEquals(stepExecution, jobExecution.getStepExecutions().iterator().next());
213214
}
214215

216+
/*
217+
* Create two job executions for the same job+parameters tuple. Should ignore
218+
* non-identifying job parameters when identifying the job instance.
219+
*/
220+
@Transactional
221+
@Test
222+
public void testReExecuteWithSameJobParameters() throws Exception {
223+
JobParameters jobParameters = new JobParametersBuilder()
224+
.addString("name", "foo", false)
225+
.toJobParameters();
226+
JobExecution jobExecution1 = jobRepository.createJobExecution(job.getName(), jobParameters);
227+
jobExecution1.setStatus(BatchStatus.COMPLETED);
228+
jobExecution1.setEndTime(new Date());
229+
jobRepository.update(jobExecution1);
230+
JobExecution jobExecution2 = jobRepository.createJobExecution(job.getName(), jobParameters);
231+
assertNotNull(jobExecution1);
232+
assertNotNull(jobExecution2);
233+
}
234+
215235
}

0 commit comments

Comments
 (0)