Skip to content

Commit 5750492

Browse files
committed
Fix retrieval of running job executions
Resolves #5104
1 parent 69665d8 commit 5750492

File tree

2 files changed

+101
-3
lines changed

2 files changed

+101
-3
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/repository/dao/jdbc/JdbcJobExecutionDao.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,9 +343,15 @@ public Set<JobExecution> findRunningJobExecutions(String jobName) {
343343
final Set<JobExecution> result = new HashSet<>();
344344
List<Long> jobInstanceIds = this.jobInstanceDao.getJobInstanceIds(jobName);
345345
for (long jobInstanceId : jobInstanceIds) {
346-
long runningJobExecutionId = getJdbcTemplate().queryForObject(getQuery(GET_RUNNING_EXECUTION_FOR_INSTANCE),
347-
Long.class, jobInstanceId);
348-
JobExecution runningJobExecution = getJobExecution(runningJobExecutionId);
346+
List<Long> runningJobExecutionIds = getJdbcTemplate()
347+
.queryForList(getQuery(GET_RUNNING_EXECUTION_FOR_INSTANCE), Long.class, jobInstanceId);
348+
if (runningJobExecutionIds.isEmpty()) {
349+
continue;
350+
}
351+
// There should be only one running execution per job instance, enforced at
352+
// startup time
353+
Long jobExecutionId = runningJobExecutionIds.get(0);
354+
JobExecution runningJobExecution = getJobExecution(jobExecutionId);
349355
result.add(runningJobExecution);
350356
}
351357
return result;
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Copyright 2025-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.batch.core.repository;
17+
18+
import java.util.Set;
19+
20+
import javax.sql.DataSource;
21+
22+
import org.junit.jupiter.api.Assertions;
23+
import org.junit.jupiter.api.Test;
24+
import org.junit.jupiter.api.extension.ExtendWith;
25+
26+
import org.springframework.batch.core.ExitStatus;
27+
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
28+
import org.springframework.batch.core.configuration.annotation.EnableJdbcJobRepository;
29+
import org.springframework.batch.core.job.Job;
30+
import org.springframework.batch.core.job.JobExecution;
31+
import org.springframework.batch.core.job.builder.JobBuilder;
32+
import org.springframework.batch.core.job.parameters.JobParameters;
33+
import org.springframework.batch.core.launch.JobOperator;
34+
import org.springframework.batch.core.step.builder.StepBuilder;
35+
import org.springframework.batch.core.step.tasklet.Tasklet;
36+
import org.springframework.batch.core.step.tasklet.TaskletStep;
37+
import org.springframework.batch.infrastructure.repeat.RepeatStatus;
38+
import org.springframework.beans.factory.annotation.Autowired;
39+
import org.springframework.context.annotation.Bean;
40+
import org.springframework.context.annotation.Configuration;
41+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
42+
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
43+
import org.springframework.jdbc.support.JdbcTransactionManager;
44+
import org.springframework.test.context.junit.jupiter.SpringExtension;
45+
46+
@ExtendWith(SpringExtension.class)
47+
public class JobRepositoryIntegrationTests {
48+
49+
// Issue https://github.com/spring-projects/spring-batch/issues/5104
50+
@Test
51+
void testFindRunningJobExecutions(@Autowired JobOperator jobOperator, @Autowired JobRepository jobRepository,
52+
@Autowired Job job) throws Exception {
53+
// Start a job execution
54+
JobExecution jobExecution = jobOperator.start(job, new JobParameters());
55+
Assertions.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
56+
57+
// Find running job executions, none at this point
58+
Set<JobExecution> runningExecutions = jobRepository.findRunningJobExecutions(job.getName());
59+
60+
// then
61+
Assertions.assertTrue(runningExecutions.isEmpty());
62+
}
63+
64+
@Configuration
65+
@EnableBatchProcessing
66+
@EnableJdbcJobRepository
67+
static class JobConfiguration {
68+
69+
@Bean
70+
public Job job(JobRepository jobRepository) {
71+
Tasklet tasklet = (contribution, chunkContext) -> RepeatStatus.FINISHED;
72+
TaskletStep step = new StepBuilder("step", jobRepository).tasklet(tasklet).build();
73+
return new JobBuilder(jobRepository).start(step).build();
74+
}
75+
76+
@Bean
77+
public DataSource dataSource() {
78+
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2)
79+
.addScript("/org/springframework/batch/core/schema-drop-h2.sql")
80+
.addScript("/org/springframework/batch/core/schema-h2.sql")
81+
.generateUniqueName(true)
82+
.build();
83+
}
84+
85+
@Bean
86+
public JdbcTransactionManager transactionManager(DataSource dataSource) {
87+
return new JdbcTransactionManager(dataSource);
88+
}
89+
90+
}
91+
92+
}

0 commit comments

Comments
 (0)