1515 */
1616package org .springframework .batch .test ;
1717
18+ import java .util .ArrayList ;
19+ import java .util .List ;
20+ import java .util .Map ;
21+
1822import org .springframework .batch .core .job .AbstractJob ;
1923import org .springframework .batch .core .job .Job ;
2024import org .springframework .batch .core .job .JobExecution ;
2125import org .springframework .batch .core .job .SimpleJob ;
26+ import org .springframework .batch .core .job .UnexpectedJobExecutionException ;
2227import org .springframework .batch .core .job .flow .FlowJob ;
2328import org .springframework .batch .core .job .parameters .JobParameters ;
2429import org .springframework .batch .core .job .parameters .JobParametersBuilder ;
30+ import org .springframework .batch .core .job .parameters .JobParametersInvalidException ;
2531import org .springframework .batch .core .launch .JobOperator ;
32+ import org .springframework .batch .core .launch .NoSuchJobException ;
33+ import org .springframework .batch .core .listener .JobExecutionListener ;
34+ import org .springframework .batch .core .repository .JobExecutionAlreadyRunningException ;
35+ import org .springframework .batch .core .repository .JobInstanceAlreadyCompleteException ;
2636import org .springframework .batch .core .repository .JobRepository ;
37+ import org .springframework .batch .core .repository .JobRestartException ;
2738import org .springframework .batch .core .step .Step ;
2839import org .springframework .batch .core .step .StepLocator ;
2940import org .springframework .batch .item .ExecutionContext ;
6273@ SuppressWarnings ("removal" )
6374public class JobOperatorTestUtils extends JobLauncherTestUtils {
6475
76+ /**
77+ * Name of the single-step job surrounding steps when tested individually
78+ */
79+ public static final String JOB_NAME = "TestJob" ;
80+
6581 protected JobOperator jobOperator ;
6682
6783 /**
@@ -123,9 +139,9 @@ public JobExecution startJob(JobParameters jobParameters) throws Exception {
123139
124140 /**
125141 * Start just the specified step in a surrounding single-step job of type
126- * {@link SimpleJob} named {@link StepRunner #JOB_NAME}. A unique set of JobParameters
127- * will automatically be generated. An IllegalStateException is thrown if there is no
128- * Step with the given name.
142+ * {@link SimpleJob} named {@link #JOB_NAME}. A unique set of JobParameters will
143+ * automatically be generated. An IllegalStateException is thrown if there is no Step
144+ * with the given name.
129145 * @param stepName The name of the step to launch
130146 * @return JobExecution
131147 */
@@ -134,13 +150,13 @@ public JobExecution startStep(String stepName) {
134150 }
135151
136152 /**
137- * Launch just the specified step in a surrounding single-step job of type
138- * {@link SimpleJob} named {@link StepRunner #JOB_NAME}. An IllegalStateException is
153+ * Extract the step from the injected job and start it in a surrounding single-step
154+ * job of type {@link SimpleJob} named {@link #JOB_NAME}. An IllegalStateException is
139155 * thrown if there is no Step with the given name.
140- * @param stepName The name of the step to launch
141- * @param jobParameters The JobParameters to use during the launch
156+ * @param stepName The name of the step to start
157+ * @param jobParameters The JobParameters to use during the start
142158 * @param jobExecutionContext An ExecutionContext whose values will be loaded into the
143- * Job ExecutionContext prior to launching the step.
159+ * Job ExecutionContext before starting the step.
144160 * @return JobExecution
145161 */
146162 public JobExecution startStep (String stepName , JobParameters jobParameters , ExecutionContext jobExecutionContext ) {
@@ -156,7 +172,62 @@ public JobExecution startStep(String stepName, JobParameters jobParameters, Exec
156172 if (step == null ) {
157173 throw new IllegalStateException ("No Step found with name: [" + stepName + "]" );
158174 }
159- return getStepRunner ().launchStep (step , jobParameters , jobExecutionContext );
175+
176+ return startStep (step , jobParameters , jobExecutionContext );
177+ }
178+
179+ /**
180+ * Start just the specified step with a unique set of job parameters in a surrounding
181+ * single-step job of type {@link SimpleJob} named {@link StepRunner#JOB_NAME}. An
182+ * IllegalStateException is thrown if there is no Step with the given name.
183+ * @param step The step to start
184+ * @return JobExecution
185+ */
186+ public JobExecution startStep (Step step ) {
187+ return startStep (step , getUniqueJobParameters (), new ExecutionContext ());
188+ }
189+
190+ /**
191+ * Start just the specified step in a surrounding single-step job of type
192+ * {@link SimpleJob} named {@link StepRunner#JOB_NAME}. An IllegalStateException is
193+ * thrown if there is no Step with the given name.
194+ * @param step The step to start
195+ * @param jobParameters The JobParameters to use during the start
196+ * @param jobExecutionContext An ExecutionContext whose values will be loaded into the
197+ * Job ExecutionContext before starting the step.
198+ * @return JobExecution
199+ */
200+ public JobExecution startStep (Step step , JobParameters jobParameters , ExecutionContext jobExecutionContext ) {
201+ // Create a fake job
202+ SimpleJob job = new SimpleJob ();
203+ job .setName (JOB_NAME );
204+ job .setJobRepository (this .jobRepository );
205+
206+ List <Step > stepsToExecute = new ArrayList <>();
207+ stepsToExecute .add (step );
208+ job .setSteps (stepsToExecute );
209+
210+ // Dump the given Job ExecutionContext using a listener
211+ if (jobExecutionContext != null && !jobExecutionContext .isEmpty ()) {
212+ job .setJobExecutionListeners (new JobExecutionListener [] { new JobExecutionListener () {
213+ @ Override
214+ public void beforeJob (JobExecution jobExecution ) {
215+ ExecutionContext jobContext = jobExecution .getExecutionContext ();
216+ for (Map .Entry <String , Object > entry : jobExecutionContext .entrySet ()) {
217+ jobContext .put (entry .getKey (), entry .getValue ());
218+ }
219+ }
220+ } });
221+ }
222+
223+ // Launch the job
224+ try {
225+ return this .jobOperator .start (job , jobParameters );
226+ }
227+ catch (NoSuchJobException | JobExecutionAlreadyRunningException | JobRestartException
228+ | JobInstanceAlreadyCompleteException | JobParametersInvalidException e ) {
229+ throw new UnexpectedJobExecutionException ("Step runner encountered exception." , e );
230+ }
160231 }
161232
162233 /**
0 commit comments