Skip to content

Commit 0b1d920

Browse files
committed
Introduce ListableStepLocator
Resolves #5015
1 parent 74a21f9 commit 0b1d920

File tree

13 files changed

+63
-56
lines changed

13 files changed

+63
-56
lines changed

spring-batch-core/src/main/java/org/springframework/batch/core/configuration/support/DefaultJobLoader.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import org.jspecify.annotations.NullUnmarked;
2727

2828
import org.springframework.batch.core.job.Job;
29+
import org.springframework.batch.core.step.ListableStepLocator;
2930
import org.springframework.batch.core.step.Step;
3031
import org.springframework.batch.core.configuration.DuplicateJobException;
3132
import org.springframework.batch.core.configuration.JobRegistry;
@@ -220,7 +221,8 @@ private Collection<Job> doLoad(ApplicationContextFactory factory, boolean unregi
220221
* @return all the {@link Step} defined by the given step locator and context
221222
* @see StepLocator
222223
*/
223-
private Collection<Step> getSteps(final StepLocator stepLocator, final ApplicationContext jobApplicationContext) {
224+
private Collection<Step> getSteps(final ListableStepLocator stepLocator,
225+
final ApplicationContext jobApplicationContext) {
224226
final Collection<String> stepNames = stepLocator.getStepNames();
225227
final Collection<Step> result = new ArrayList<>();
226228
for (String stepName : stepNames) {
@@ -253,7 +255,7 @@ private void doRegister(ConfigurableApplicationContext context, Job job) throws
253255
jobRegistry.register(job);
254256

255257
if (stepRegistry != null) {
256-
if (!(job instanceof StepLocator stepLocator)) {
258+
if (!(job instanceof ListableStepLocator stepLocator)) {
257259
throw new UnsupportedOperationException("Cannot locate steps from a Job that is not a StepLocator: job="
258260
+ job.getName() + " does not implement StepLocator");
259261
}

spring-batch-core/src/main/java/org/springframework/batch/core/job/AbstractJob.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.batch.core.observability.BatchMetrics;
3838
import org.springframework.batch.core.observability.jfr.events.job.JobExecutionEvent;
3939
import org.springframework.batch.core.observability.micrometer.MicrometerMetrics;
40+
import org.springframework.batch.core.step.ListableStepLocator;
4041
import org.springframework.batch.core.step.Step;
4142
import org.springframework.batch.core.step.StepExecution;
4243
import org.springframework.batch.core.listener.CompositeJobExecutionListener;
@@ -62,7 +63,7 @@
6263
*/
6364
@NullUnmarked // FIXME to remove once default constructors (required by the batch XML
6465
// namespace) are removed
65-
public abstract class AbstractJob implements Job, StepLocator, BeanNameAware, InitializingBean {
66+
public abstract class AbstractJob implements Job, ListableStepLocator, BeanNameAware, InitializingBean {
6667

6768
protected static final Log logger = LogFactory.getLog(AbstractJob.class);
6869

spring-batch-core/src/main/java/org/springframework/batch/core/job/SimpleJob.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import org.springframework.batch.core.BatchStatus;
2626

27+
import org.springframework.batch.core.step.ListableStepLocator;
2728
import org.springframework.batch.core.step.Step;
2829
import org.springframework.batch.core.step.StepExecution;
2930
import org.springframework.batch.core.launch.JobRestartException;
@@ -80,7 +81,7 @@ public Collection<String> getStepNames() {
8081
for (Step step : steps) {
8182
names.add(step.getName());
8283

83-
if (step instanceof StepLocator stepLocator) {
84+
if (step instanceof ListableStepLocator stepLocator) {
8485
names.addAll(stepLocator.getStepNames());
8586
}
8687
}

spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/FlowJob.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2023 the original author or authors.
2+
* Copyright 2006-2025 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.
@@ -24,6 +24,7 @@
2424
import org.jspecify.annotations.Nullable;
2525
import org.springframework.batch.core.job.JobExecution;
2626
import org.springframework.batch.core.job.JobExecutionException;
27+
import org.springframework.batch.core.step.ListableStepLocator;
2728
import org.springframework.batch.core.step.Step;
2829
import org.springframework.batch.core.job.AbstractJob;
2930
import org.springframework.batch.core.job.SimpleStepHandler;
@@ -93,7 +94,7 @@ private void init() {
9394
private void findSteps(Flow flow, Map<String, Step> map) {
9495

9596
for (State state : flow.getStates()) {
96-
if (state instanceof StepLocator locator) {
97+
if (state instanceof ListableStepLocator locator) {
9798
for (String name : locator.getStepNames()) {
9899
map.put(name, locator.getStep(name));
99100
}

spring-batch-core/src/main/java/org/springframework/batch/core/job/flow/support/state/StepState.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2023 the original author or authors.
2+
* Copyright 2006-2025 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.
@@ -20,6 +20,7 @@
2020
import java.util.Collection;
2121
import java.util.List;
2222

23+
import org.springframework.batch.core.step.ListableStepLocator;
2324
import org.springframework.batch.core.step.Step;
2425
import org.springframework.batch.core.job.flow.FlowExecutionStatus;
2526
import org.springframework.batch.core.job.flow.FlowExecutor;
@@ -36,7 +37,7 @@
3637
* @author Mahmoud Ben Hassine
3738
* @since 2.0
3839
*/
39-
public class StepState extends AbstractState implements StepLocator, StepHolder {
40+
public class StepState extends AbstractState implements ListableStepLocator, StepHolder {
4041

4142
private final Step step;
4243

@@ -83,7 +84,7 @@ public Collection<String> getStepNames() {
8384

8485
names.add(step.getName());
8586

86-
if (step instanceof StepLocator stepLocator) {
87+
if (step instanceof ListableStepLocator stepLocator) {
8788
names.addAll(stepLocator.getStepNames());
8889
}
8990

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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.step;
17+
18+
import java.util.Collection;
19+
20+
/**
21+
* Interface for listing {@link Step}s by name.
22+
*
23+
* @author Mahmoud Ben Hassine
24+
* @since 6.0
25+
* @see org.springframework.batch.core.step.StepLocator
26+
*/
27+
public interface ListableStepLocator extends StepLocator {
28+
29+
Collection<String> getStepNames();
30+
31+
}

spring-batch-core/src/main/java/org/springframework/batch/core/step/StepLocator.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009 the original author or authors.
2+
* Copyright 2009-2025 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.
@@ -15,20 +15,17 @@
1515
*/
1616
package org.springframework.batch.core.step;
1717

18-
import java.util.Collection;
19-
2018
import org.jspecify.annotations.Nullable;
2119

2220
/**
2321
* Interface for locating a {@link Step} instance by name.
2422
*
2523
* @author Dave Syer
24+
* @author Mahmoud Ben Hassine
2625
*
2726
*/
2827
public interface StepLocator {
2928

30-
Collection<String> getStepNames();
31-
3229
@Nullable Step getStep(String stepName);
3330

3431
}

spring-batch-core/src/test/java/org/springframework/batch/core/configuration/support/DefaultJobLoaderTests.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2022 the original author or authors.
2+
* Copyright 2006-2025 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.
@@ -25,12 +25,11 @@
2525
import org.springframework.batch.core.job.JobExecution;
2626
import org.springframework.batch.core.job.parameters.JobParametersIncrementer;
2727
import org.springframework.batch.core.job.parameters.JobParametersValidator;
28+
import org.springframework.batch.core.step.ListableStepLocator;
2829
import org.springframework.batch.core.step.Step;
2930
import org.springframework.batch.core.configuration.DuplicateJobException;
3031
import org.springframework.batch.core.configuration.JobRegistry;
3132
import org.springframework.batch.core.configuration.StepRegistry;
32-
import org.springframework.batch.core.step.NoSuchStepException;
33-
import org.springframework.batch.core.step.StepLocator;
3433
import org.springframework.core.io.ByteArrayResource;
3534
import org.springframework.core.io.ClassPathResource;
3635
import org.springframework.test.util.ReflectionTestUtils;
@@ -231,7 +230,7 @@ public boolean isRestartable() {
231230

232231
}
233232

234-
public static class StubJob extends BasicStubJob implements StepLocator {
233+
public static class StubJob extends BasicStubJob implements ListableStepLocator {
235234

236235
@Override
237236
public Collection<String> getStepNames() {

spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/SplitJobParserTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2006-2022 the original author or authors.
2+
* Copyright 2006-2025 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.
@@ -28,7 +28,7 @@
2828
import org.springframework.batch.core.job.JobInstance;
2929
import org.springframework.batch.core.job.parameters.JobParameters;
3030
import org.springframework.batch.core.repository.JobRepository;
31-
import org.springframework.batch.core.step.StepLocator;
31+
import org.springframework.batch.core.step.ListableStepLocator;
3232
import org.springframework.batch.infrastructure.item.ExecutionContext;
3333
import org.springframework.beans.factory.annotation.Autowired;
3434
import org.springframework.beans.factory.annotation.Qualifier;
@@ -58,7 +58,7 @@ void testSplitJob() throws Exception {
5858
job.execute(jobExecution);
5959
assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
6060
assertEquals(4, jobExecution.getStepExecutions().size());
61-
ArrayList<String> names = new ArrayList<>(((StepLocator) job).getStepNames());
61+
ArrayList<String> names = new ArrayList<>(((ListableStepLocator) job).getStepNames());
6262
Collections.sort(names);
6363
assertEquals("[s1, s2, s3, s4]", names.toString());
6464
}

spring-batch-core/src/test/java/org/springframework/batch/core/configuration/xml/StepNameTests.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import org.junit.jupiter.params.provider.Arguments;
3030
import org.junit.jupiter.params.provider.MethodSource;
3131
import org.springframework.batch.core.job.Job;
32-
import org.springframework.batch.core.step.StepLocator;
32+
import org.springframework.batch.core.step.ListableStepLocator;
3333
import org.springframework.beans.factory.BeanCreationException;
3434
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
3535
import org.springframework.context.ApplicationContext;
@@ -56,9 +56,9 @@ void testStepNames(Resource resource) throws Exception {
5656
if (context == null) {
5757
return;
5858
}
59-
Map<String, StepLocator> stepLocators = context.getBeansOfType(StepLocator.class);
59+
Map<String, ListableStepLocator> stepLocators = context.getBeansOfType(ListableStepLocator.class);
6060
for (String name : stepLocators.keySet()) {
61-
StepLocator stepLocator = stepLocators.get(name);
61+
ListableStepLocator stepLocator = stepLocators.get(name);
6262
Collection<String> stepNames = stepLocator.getStepNames();
6363
Job job = context.getBean(name, Job.class);
6464
String jobName = job.getName();

0 commit comments

Comments
 (0)