11/* 
2-  * Copyright 2012-2017  the original author or authors. 
2+  * Copyright 2012-2018  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. 
1919import  java .util .Arrays ;
2020import  java .util .Collection ;
2121import  java .util .Collections ;
22+ import  java .util .HashMap ;
23+ import  java .util .LinkedHashMap ;
24+ import  java .util .Map ;
2225import  java .util .Properties ;
2326
2427import  org .apache .commons .logging .Log ;
2528import  org .apache .commons .logging .LogFactory ;
2629
30+ import  org .springframework .batch .core .BatchStatus ;
2731import  org .springframework .batch .core .Job ;
2832import  org .springframework .batch .core .JobExecution ;
2933import  org .springframework .batch .core .JobExecutionException ;
34+ import  org .springframework .batch .core .JobParameter ;
3035import  org .springframework .batch .core .JobParameters ;
3136import  org .springframework .batch .core .JobParametersBuilder ;
3237import  org .springframework .batch .core .JobParametersInvalidException ;
3944import  org .springframework .batch .core .launch .NoSuchJobException ;
4045import  org .springframework .batch .core .repository .JobExecutionAlreadyRunningException ;
4146import  org .springframework .batch .core .repository .JobInstanceAlreadyCompleteException ;
47+ import  org .springframework .batch .core .repository .JobRepository ;
4248import  org .springframework .batch .core .repository .JobRestartException ;
4349import  org .springframework .beans .factory .annotation .Autowired ;
4450import  org .springframework .boot .CommandLineRunner ;
4551import  org .springframework .context .ApplicationEventPublisher ;
4652import  org .springframework .context .ApplicationEventPublisherAware ;
4753import  org .springframework .core .Ordered ;
54+ import  org .springframework .util .Assert ;
4855import  org .springframework .util .PatternMatchUtils ;
4956import  org .springframework .util .StringUtils ;
5057
5562 * 
5663 * @author Dave Syer 
5764 * @author Jean-Pierre Bergamin 
65+  * @author Mahmoud Ben Hassine 
5866 */ 
5967public  class  JobLauncherCommandLineRunner 
6068		implements  CommandLineRunner , Ordered , ApplicationEventPublisherAware  {
@@ -69,11 +77,13 @@ public class JobLauncherCommandLineRunner
6977
7078	private  JobParametersConverter  converter  = new  DefaultJobParametersConverter ();
7179
72- 	private  JobLauncher  jobLauncher ;
80+ 	private  final   JobLauncher  jobLauncher ;
7381
74- 	private  JobRegistry  jobRegistry ;
82+ 	private  final  JobExplorer  jobExplorer ;
83+ 
84+ 	private  final  JobRepository  jobRepository ;
7585
76- 	private  JobExplorer   jobExplorer ;
86+ 	private  JobRegistry   jobRegistry ;
7787
7888	private  String  jobNames ;
7989
@@ -83,10 +93,38 @@ public class JobLauncherCommandLineRunner
8393
8494	private  ApplicationEventPublisher  publisher ;
8595
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 
86106	public  JobLauncherCommandLineRunner (JobLauncher  jobLauncher ,
87107			JobExplorer  jobExplorer ) {
88108		this .jobLauncher  = jobLauncher ;
89109		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 ;
90128	}
91129
92130	public  void  setOrder (int  order ) {
@@ -135,6 +173,20 @@ protected void launchJobFromProperties(Properties properties)
135173		executeRegisteredJobs (jobParameters );
136174	}
137175
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+ 
138190	private  void  executeRegisteredJobs (JobParameters  jobParameters )
139191			throws  JobExecutionException  {
140192		if  (this .jobRegistry  != null  && StringUtils .hasText (this .jobNames )) {
@@ -158,26 +210,59 @@ protected void execute(Job job, JobParameters jobParameters)
158210			throws  JobExecutionAlreadyRunningException , JobRestartException ,
159211			JobInstanceAlreadyCompleteException , JobParametersInvalidException ,
160212			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 );
164215		if  (this .publisher  != null ) {
165216			this .publisher .publishEvent (new  JobExecutionEvent (execution ));
166217		}
167218	}
168219
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 ;
180227		}
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 );
181266	}
182267
183268}
0 commit comments