Skip to content

Commit 72cd7bc

Browse files
committed
Add ability for Task to obtain next Job Params for job launch
Update tests so that they can handle that a JobIncrementer is fired on job launch if one exists and update tests. spring-projects/spring-batch#4910
1 parent 12eee35 commit 72cd7bc

File tree

2 files changed

+65
-10
lines changed

2 files changed

+65
-10
lines changed

spring-cloud-task-batch/src/main/java/org/springframework/cloud/task/batch/handler/TaskJobLauncherApplicationRunner.java

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
import org.springframework.batch.core.job.Job;
3131
import org.springframework.batch.core.job.JobExecution;
3232
import org.springframework.batch.core.job.JobExecutionException;
33+
import org.springframework.batch.core.job.JobInstance;
3334
import org.springframework.batch.core.job.parameters.JobParameter;
3435
import org.springframework.batch.core.job.parameters.JobParameters;
35-
import org.springframework.batch.core.job.parameters.JobParametersBuilder;
3636
import org.springframework.batch.core.job.parameters.JobParametersIncrementer;
3737
import org.springframework.batch.core.job.parameters.JobParametersInvalidException;
3838
import org.springframework.batch.core.launch.JobOperator;
@@ -50,6 +50,7 @@
5050
import org.springframework.cloud.task.listener.TaskException;
5151
import org.springframework.context.ApplicationEventPublisher;
5252
import org.springframework.core.task.TaskExecutor;
53+
import org.springframework.util.Assert;
5354
import org.springframework.util.StringUtils;
5455

5556
/**
@@ -90,7 +91,7 @@ public class TaskJobLauncherApplicationRunner extends JobLauncherApplicationRunn
9091
*/
9192
public TaskJobLauncherApplicationRunner(JobOperator jobOperator, JobRepository jobRepository,
9293
TaskBatchProperties taskBatchProperties) {
93-
super(jobOperator, jobRepository);
94+
super(jobOperator);
9495
this.taskJobOperator = jobOperator;
9596
this.taskJobRepository = jobRepository;
9697
this.taskBatchProperties = taskBatchProperties;
@@ -136,9 +137,12 @@ protected void execute(Job job, JobParameters jobParameters)
136137
else {
137138
JobParametersIncrementer incrementer = job.getJobParametersIncrementer();
138139
if (incrementer != null) {
139-
JobParameters nextParameters = new JobParametersBuilder(jobParameters, this.taskJobRepository)
140-
.getNextJobParameters(job)
141-
.toJobParameters();
140+
// JobParameters nextParameters = new JobParametersBuilder(jobParameters,
141+
// this.taskJobRepository)
142+
// .getNextJobParameters(job)
143+
// .toJobParameters();
144+
JobParameters nextParameters = getNextJobParameters(job, new HashMap<>(jobParameters.getParameters()),
145+
this.taskJobRepository);
142146
parameters = merge(nextParameters, jobParameters);
143147
}
144148
}
@@ -223,4 +227,51 @@ private JobParameters merge(JobParameters parameters, JobParameters additionals)
223227
return new JobParameters(merged);
224228
}
225229

230+
/**
231+
* Initializes the {@link JobParameters} based on the state of the {@link Job}. This
232+
* should be called after all parameters have been entered into the builder. All
233+
* parameters already set on this builder instance are appended to those retrieved
234+
* from the job incrementer, overriding any with the same key (this is the same
235+
* behavior as
236+
* {@link org.springframework.batch.core.launch.support.CommandLineJobRunner} with the
237+
* {@code -next} option and
238+
* {@link org.springframework.batch.core.launch.JobOperator#startNextInstance(String)}).
239+
* @param job The job for which the {@link JobParameters} are being constructed.
240+
* @return a reference to this object.
241+
*
242+
* @since 4.0
243+
*/
244+
public JobParameters getNextJobParameters(Job job, Map<String, JobParameter<?>> parameterMap,
245+
JobRepository taskJobRepository) {
246+
Assert.notNull(job, "Job must not be null");
247+
Assert.notNull(job.getJobParametersIncrementer(),
248+
"No job parameters incrementer found for job=" + job.getName());
249+
250+
String name = job.getName();
251+
JobParameters nextParameters;
252+
JobInstance lastInstance = taskJobRepository.getLastJobInstance(name);
253+
JobParametersIncrementer incrementer = job.getJobParametersIncrementer();
254+
if (lastInstance == null) {
255+
// Start from a completely clean sheet
256+
nextParameters = incrementer.getNext(new JobParameters());
257+
}
258+
else {
259+
JobExecution previousExecution = taskJobRepository.getLastJobExecution(lastInstance);
260+
if (previousExecution == null) {
261+
// Normally this will not happen - an instance exists with no executions
262+
nextParameters = incrementer.getNext(new JobParameters());
263+
}
264+
else {
265+
nextParameters = incrementer.getNext(previousExecution.getJobParameters());
266+
}
267+
}
268+
269+
// start with parameters from the incrementer
270+
Map<String, JobParameter<?>> nextParametersMap = new HashMap<>(nextParameters.getParameters());
271+
// append new parameters (overriding those with the same key)
272+
nextParametersMap.putAll(parameterMap);
273+
parameterMap = nextParametersMap;
274+
return new JobParameters(parameterMap);
275+
}
276+
226277
}

spring-cloud-task-batch/src/test/java/org/springframework/cloud/task/batch/handler/TaskJobLauncherApplicationRunnerCoreTests.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import org.springframework.batch.core.launch.JobOperator;
3636
import org.springframework.batch.core.launch.support.RunIdIncrementer;
3737
import org.springframework.batch.core.repository.JobRepository;
38-
import org.springframework.batch.core.repository.JobRestartException;
3938
import org.springframework.batch.core.step.Step;
4039
import org.springframework.batch.core.step.builder.StepBuilder;
4140
import org.springframework.batch.core.step.tasklet.Tasklet;
@@ -124,12 +123,15 @@ void retryFailedExecutionOnNonRestartableJob() {
124123
// A failed job that is not restartable does not re-use the job params of
125124
// the last execution, but creates a new job instance when running it again.
126125
assertThat(jobLauncherContext.jobInstances()).hasSize(2);
127-
assertThatExceptionOfType(JobRestartException.class).isThrownBy(() -> {
126+
assertThatExceptionOfType(TaskException.class).isThrownBy(() -> {
128127
// try to re-run a failed execution
128+
// In this case the change from the previous behavior is that a new job
129+
// instance is created
130+
// https://github.com/spring-projects/spring-batch/issues/4910
129131
jobLauncherContext.runner.execute(job,
130132
new JobParametersBuilder().addLong("run.id", 1L).toJobParameters());
131-
fail("expected JobRestartException");
132-
}).withMessageContaining("JobInstance already exists and is not restartable");
133+
fail("expected TaskException");
134+
}).withMessageContaining("Job job failed during execution for job instance id 3 with jobExecutionId of 3 ");
133135
});
134136
}
135137

@@ -148,9 +150,11 @@ void retryFailedExecutionWithNonIdentifyingParameters() {
148150
runFailedJob(jobLauncherContext, job, jobParameters);
149151
assertThat(jobLauncherContext.jobInstances()).hasSize(1);
150152
// try to re-run a failed execution with non identifying parameters
153+
// Updated to expect a new 2 instances are created because of this change
154+
// https://github.com/spring-projects/spring-batch/issues/4910
151155
runFailedJob(jobLauncherContext, job,
152156
new JobParametersBuilder(jobParameters).addLong("run.id", 1L).toJobParameters());
153-
assertThat(jobLauncherContext.jobInstances()).hasSize(1);
157+
assertThat(jobLauncherContext.jobInstances()).hasSize(2);
154158
});
155159
}
156160

0 commit comments

Comments
 (0)