1
1
/*
2
- * Copyright 2012-2017 the original author or authors.
2
+ * Copyright 2012-2018 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
19
19
import java .util .Arrays ;
20
20
import java .util .Collection ;
21
21
import java .util .Collections ;
22
+ import java .util .HashMap ;
23
+ import java .util .LinkedHashMap ;
24
+ import java .util .Map ;
22
25
import java .util .Properties ;
23
26
24
27
import org .apache .commons .logging .Log ;
25
28
import org .apache .commons .logging .LogFactory ;
26
29
30
+ import org .springframework .batch .core .BatchStatus ;
27
31
import org .springframework .batch .core .Job ;
28
32
import org .springframework .batch .core .JobExecution ;
29
33
import org .springframework .batch .core .JobExecutionException ;
34
+ import org .springframework .batch .core .JobParameter ;
30
35
import org .springframework .batch .core .JobParameters ;
31
36
import org .springframework .batch .core .JobParametersBuilder ;
32
37
import org .springframework .batch .core .JobParametersInvalidException ;
39
44
import org .springframework .batch .core .launch .NoSuchJobException ;
40
45
import org .springframework .batch .core .repository .JobExecutionAlreadyRunningException ;
41
46
import org .springframework .batch .core .repository .JobInstanceAlreadyCompleteException ;
47
+ import org .springframework .batch .core .repository .JobRepository ;
42
48
import org .springframework .batch .core .repository .JobRestartException ;
43
49
import org .springframework .beans .factory .annotation .Autowired ;
44
50
import org .springframework .boot .CommandLineRunner ;
45
51
import org .springframework .context .ApplicationEventPublisher ;
46
52
import org .springframework .context .ApplicationEventPublisherAware ;
47
53
import org .springframework .core .Ordered ;
54
+ import org .springframework .util .Assert ;
48
55
import org .springframework .util .PatternMatchUtils ;
49
56
import org .springframework .util .StringUtils ;
50
57
55
62
*
56
63
* @author Dave Syer
57
64
* @author Jean-Pierre Bergamin
65
+ * @author Mahmoud Ben Hassine
58
66
*/
59
67
public class JobLauncherCommandLineRunner
60
68
implements CommandLineRunner , Ordered , ApplicationEventPublisherAware {
@@ -69,11 +77,13 @@ public class JobLauncherCommandLineRunner
69
77
70
78
private JobParametersConverter converter = new DefaultJobParametersConverter ();
71
79
72
- private JobLauncher jobLauncher ;
80
+ private final JobLauncher jobLauncher ;
73
81
74
- private JobRegistry jobRegistry ;
82
+ private final JobExplorer jobExplorer ;
83
+
84
+ private final JobRepository jobRepository ;
75
85
76
- private JobExplorer jobExplorer ;
86
+ private JobRegistry jobRegistry ;
77
87
78
88
private String jobNames ;
79
89
@@ -83,10 +93,38 @@ public class JobLauncherCommandLineRunner
83
93
84
94
private ApplicationEventPublisher publisher ;
85
95
96
+ /**
97
+ * Create a new {@link JobLauncherCommandLineRunner}.
98
+ * @param jobLauncher to launch jobs
99
+ * @param jobExplorer to check the job repository for previous executions
100
+ * @deprecated since 2.0.7 in favor of
101
+ * {@link #JobLauncherCommandLineRunner(JobLauncher, JobExplorer, JobRepository)}. A
102
+ * job repository is required to check if a job instance exists with the given
103
+ * parameters when running a job (which is not possible with the job explorer).
104
+ */
105
+ @ Deprecated
86
106
public JobLauncherCommandLineRunner (JobLauncher jobLauncher ,
87
107
JobExplorer jobExplorer ) {
88
108
this .jobLauncher = jobLauncher ;
89
109
this .jobExplorer = jobExplorer ;
110
+ this .jobRepository = null ;
111
+ }
112
+
113
+ /**
114
+ * Create a new {@link JobLauncherCommandLineRunner}.
115
+ * @param jobLauncher to launch jobs
116
+ * @param jobExplorer to check the job repository for previous executions
117
+ * @param jobRepository to check if a job instance exists with the given parameters
118
+ * when running a job
119
+ */
120
+ public JobLauncherCommandLineRunner (JobLauncher jobLauncher , JobExplorer jobExplorer ,
121
+ JobRepository jobRepository ) {
122
+ Assert .notNull (jobLauncher , "JobLauncher must not be null" );
123
+ Assert .notNull (jobExplorer , "JobExplorer must not be null" );
124
+ Assert .notNull (jobRepository , "JobRepository must not be null" );
125
+ this .jobLauncher = jobLauncher ;
126
+ this .jobExplorer = jobExplorer ;
127
+ this .jobRepository = jobRepository ;
90
128
}
91
129
92
130
public void setOrder (int order ) {
@@ -135,6 +173,20 @@ protected void launchJobFromProperties(Properties properties)
135
173
executeRegisteredJobs (jobParameters );
136
174
}
137
175
176
+ private void executeLocalJobs (JobParameters jobParameters )
177
+ throws JobExecutionException {
178
+ for (Job job : this .jobs ) {
179
+ if (StringUtils .hasText (this .jobNames )) {
180
+ String [] jobsToRun = this .jobNames .split ("," );
181
+ if (!PatternMatchUtils .simpleMatch (jobsToRun , job .getName ())) {
182
+ logger .debug ("Skipped job: " + job .getName ());
183
+ continue ;
184
+ }
185
+ }
186
+ execute (job , jobParameters );
187
+ }
188
+ }
189
+
138
190
private void executeRegisteredJobs (JobParameters jobParameters )
139
191
throws JobExecutionException {
140
192
if (this .jobRegistry != null && StringUtils .hasText (this .jobNames )) {
@@ -158,26 +210,59 @@ protected void execute(Job job, JobParameters jobParameters)
158
210
throws JobExecutionAlreadyRunningException , JobRestartException ,
159
211
JobInstanceAlreadyCompleteException , JobParametersInvalidException ,
160
212
JobParametersNotFoundException {
161
- JobParameters nextParameters = new JobParametersBuilder (jobParameters ,
162
- this .jobExplorer ).getNextJobParameters (job ).toJobParameters ();
163
- JobExecution execution = this .jobLauncher .run (job , nextParameters );
213
+ JobParameters parameters = getNextJobParameters (job , jobParameters );
214
+ JobExecution execution = this .jobLauncher .run (job , parameters );
164
215
if (this .publisher != null ) {
165
216
this .publisher .publishEvent (new JobExecutionEvent (execution ));
166
217
}
167
218
}
168
219
169
- private void executeLocalJobs (JobParameters jobParameters )
170
- throws JobExecutionException {
171
- for (Job job : this .jobs ) {
172
- if (StringUtils .hasText (this .jobNames )) {
173
- String [] jobsToRun = this .jobNames .split ("," );
174
- if (!PatternMatchUtils .simpleMatch (jobsToRun , job .getName ())) {
175
- logger .debug ("Skipped job: " + job .getName ());
176
- continue ;
177
- }
178
- }
179
- execute (job , jobParameters );
220
+ private JobParameters getNextJobParameters (Job job , JobParameters jobParameters ) {
221
+ if (this .jobRepository != null
222
+ && this .jobRepository .isJobInstanceExists (job .getName (), jobParameters )) {
223
+ return getNextJobParametersForExisting (job , jobParameters );
224
+ }
225
+ if (job .getJobParametersIncrementer () == null ) {
226
+ return jobParameters ;
180
227
}
228
+ JobParameters nextParameters = new JobParametersBuilder (jobParameters ,
229
+ this .jobExplorer ).getNextJobParameters (job ).toJobParameters ();
230
+ return merge (nextParameters , jobParameters );
231
+ }
232
+
233
+ private JobParameters getNextJobParametersForExisting (Job job ,
234
+ JobParameters jobParameters ) {
235
+ JobExecution lastExecution = this .jobRepository .getLastJobExecution (job .getName (),
236
+ jobParameters );
237
+ if (isStoppedOrFailed (lastExecution ) && job .isRestartable ()) {
238
+ JobParameters previousIdentifyingParameters = getGetIdentifying (
239
+ lastExecution .getJobParameters ());
240
+ return merge (previousIdentifyingParameters , jobParameters );
241
+ }
242
+ return jobParameters ;
243
+ }
244
+
245
+ private boolean isStoppedOrFailed (JobExecution execution ) {
246
+ BatchStatus status = (execution != null ) ? execution .getStatus () : null ;
247
+ return (status == BatchStatus .STOPPED || status == BatchStatus .FAILED );
248
+ }
249
+
250
+ private JobParameters getGetIdentifying (JobParameters parameters ) {
251
+ HashMap <String , JobParameter > nonIdentifying = new LinkedHashMap <>(
252
+ parameters .getParameters ().size ());
253
+ parameters .getParameters ().forEach ((key , value ) -> {
254
+ if (value .isIdentifying ()) {
255
+ nonIdentifying .put (key , value );
256
+ }
257
+ });
258
+ return new JobParameters (nonIdentifying );
259
+ }
260
+
261
+ private JobParameters merge (JobParameters parameters , JobParameters additionals ) {
262
+ Map <String , JobParameter > merged = new LinkedHashMap <>();
263
+ merged .putAll (parameters .getParameters ());
264
+ merged .putAll (additionals .getParameters ());
265
+ return new JobParameters (merged );
181
266
}
182
267
183
268
}
0 commit comments