1616
1717package org .springframework .batch .execution .configuration ;
1818
19+ import java .util .ArrayList ;
20+ import java .util .List ;
21+
22+ import org .springframework .batch .execution .job .SimpleJob ;
1923import org .springframework .batch .execution .repository .SimpleJobRepository ;
2024import org .springframework .batch .execution .repository .dao .JdbcJobExecutionDao ;
2125import org .springframework .batch .execution .repository .dao .JdbcJobInstanceDao ;
2226import org .springframework .batch .execution .repository .dao .JdbcStepExecutionDao ;
2327import org .springframework .batch .execution .step .ItemOrientedStep ;
2428import org .springframework .batch .execution .step .TaskletStep ;
29+ import org .springframework .batch .execution .step .support .LimitCheckingItemSkipPolicy ;
2530import org .springframework .beans .MutablePropertyValues ;
2631import org .springframework .beans .factory .config .BeanDefinition ;
2732import org .springframework .beans .factory .config .ConstructorArgumentValues ;
5055public class ConfigBeanDefinitionParser implements BeanDefinitionParser {
5156
5257 private static final String JOB_REPOSITORY_ELEMENT = "job-repository" ;
53-
58+
5459 private static final String JOB_REPOSITORY_BEAN_NAME = "_jobRepository" ;
5560
5661 private static final String DATA_SOURCE_ATT = "data-source" ;
@@ -70,33 +75,31 @@ public class ConfigBeanDefinitionParser implements BeanDefinitionParser {
7075 private static final String DB_TYPE_POSTGRES = "postgres" ;
7176
7277 private static final String JOB_ELEMENT = "job" ;
73-
78+
7479 private static final String ID_ATT = "id" ;
75-
80+
7681 private static final String RERUN_ATT = "rerun" ;
77-
82+
7883 private static final String RERUN_ALWAYS = "always" ;
79-
84+
8085 private static final String RERUN_NEVER = "never" ;
81-
86+
8287 private static final String RERUN_INCOMPLETE = "incomplete" ;
8388
8489 private static final String STEP_ELEMENT = "step" ;
85-
90+
8691 private static final String SIZE_ATT = "size" ;
87-
92+
8893 private static final String TRANSACTION_MANAGER_ATT = "transaction-manager" ;
89-
94+
9095 private static final String ITEM_READER_ATT = "item-reader" ;
91-
96+
9297 private static final String ITEM_WRITER_ATT = "item-writer" ;
93-
94- private static final String INPUT_SKIP_LIMIT_ATT = "input-skip-limit" ;
95-
96- private static final String OUTPUT_SKIP_LIMIT_ATT = "output-skip-limit" ;
98+
99+ private static final String SKIP_LIMIT_ATT = "skip-limit" ;
97100
98101 private static final String TASKLET_STEP_ELEMENT = "tasklet-step" ;
99-
102+
100103 private static final String TASKLET_ATT = "tasklet" ;
101104
102105 public BeanDefinition parse (Element element , ParserContext parserContext ) {
@@ -218,28 +221,43 @@ private void addTableIncrementer(String dataSourceId, String incrementerName,
218221 }
219222
220223 private void parseJob (Element jobEle , ParserContext parserContext ) {
224+ AbstractBeanDefinition jobDef = createJobBeanDefinition (jobEle , parserContext );
225+ List steps = new ArrayList ();
226+
221227 NodeList childNodes = jobEle .getChildNodes ();
222228 for (int i = 0 ; i < childNodes .getLength (); i ++) {
223229 Node child = childNodes .item (i );
224230 if (child .getNodeType () == Node .ELEMENT_NODE ) {
225231 String localName = child .getLocalName ();
226232 if (STEP_ELEMENT .equals (localName )) {
227- parseStep ((Element ) child , parserContext );
233+ String id = parseStep ((Element ) child , parserContext );
234+ steps .add (new RuntimeBeanReference (id ));
228235 } else if (TASKLET_STEP_ELEMENT .equals (localName )) {
229- parseTaskletStep ((Element ) child , parserContext );
236+ String id = parseTaskletStep ((Element ) child , parserContext );
237+ steps .add (new RuntimeBeanReference (id ));
230238 }
231239 }
232240 }
241+
242+ jobDef .getPropertyValues ().addPropertyValue ("steps" , steps );
233243 }
234-
235- private void parseStep (Element stepEle , ParserContext parserContext ) {
244+
245+ private AbstractBeanDefinition createJobBeanDefinition (Element jobEle , ParserContext parserContext ) {
246+ RootBeanDefinition jobDef = new RootBeanDefinition (SimpleJob .class );
247+ jobDef .setSource (parserContext .extractSource (jobEle ));
248+ jobDef .getPropertyValues ().addPropertyValue ("jobRepository" , JOB_REPOSITORY_BEAN_NAME );
249+ return jobDef ;
250+ }
251+
252+ private String parseStep (Element stepEle , ParserContext parserContext ) {
236253 AbstractBeanDefinition stepDef = createStepBeanDefinition (stepEle , parserContext );
237254 String id = stepEle .getAttribute (ID_ATT );
238255
239256 if (StringUtils .hasText (id )) {
240257 parserContext .getRegistry ().registerBeanDefinition (id , stepDef );
258+ return id ;
241259 } else {
242- parserContext .getReaderContext ().registerWithGeneratedName (stepDef );
260+ return parserContext .getReaderContext ().registerWithGeneratedName (stepDef );
243261 }
244262 }
245263
@@ -256,7 +274,7 @@ private AbstractBeanDefinition createStepBeanDefinition(Element stepElement, Par
256274 } else {
257275 propertyValues .addPropertyValue ("transactionManager" , new RuntimeBeanReference (transactionManager ));
258276 }
259-
277+
260278 String itemReader = stepElement .getAttribute (ITEM_READER_ATT );
261279 if (!StringUtils .hasText (itemReader )) {
262280 parserContext .getReaderContext ().error ("'item-reader' attribute contains empty value" , stepElement );
@@ -270,32 +288,33 @@ private AbstractBeanDefinition createStepBeanDefinition(Element stepElement, Par
270288 propertyValues .addPropertyValue ("itemWriter" , new RuntimeBeanReference (itemWriter ));
271289 }
272290
273- if (stepElement .hasAttribute (INPUT_SKIP_LIMIT_ATT )) {
274- String inputSkipLimit = stepElement .getAttribute (INPUT_SKIP_LIMIT_ATT );
275- propertyValues .addPropertyValue ("skipLimit" , Integer .valueOf (inputSkipLimit ));
291+ if (stepElement .hasAttribute (SKIP_LIMIT_ATT )) {
292+ String skipLimit = stepElement .getAttribute (SKIP_LIMIT_ATT );
293+ propertyValues .addPropertyValue ("skipLimit" , createSkipLimitBeanDefinition ( Integer .valueOf (skipLimit ) ));
276294 }
277295
278- // TODO: Create difference between input skip limit and output skip limit
279- // if (stepElement.hasAttribute(ATT_OUTPUT_SKIP_LIMIT)) {
280- // String outputSkipLimit = stepElement.getAttribute(ATT_OUTPUT_SKIP_LIMIT);
281- // propertyValues.addPropertyValue(PROP_OUTPUT_SKIP_LIMIT, Integer.valueOf(outputSkipLimit));
282- // }
283-
284296 String rerun = stepElement .getAttribute (RERUN_ATT );
285297 setPropertiesForRerun (rerun , propertyValues );
286298 propertyValues .addPropertyValue ("jobRepository" , new RuntimeBeanReference (JOB_REPOSITORY_BEAN_NAME ));
287299 return stepDef ;
288300 }
289301
290- private void parseTaskletStep (Element taskletStepEle , ParserContext parserContext ) {
302+ private AbstractBeanDefinition createSkipLimitBeanDefinition (Integer skipLimit ) {
303+ RootBeanDefinition skipLimitDef = new RootBeanDefinition (LimitCheckingItemSkipPolicy .class );
304+ skipLimitDef .getConstructorArgumentValues ().addGenericArgumentValue (skipLimit );
305+ return skipLimitDef ;
306+ }
307+
308+ private String parseTaskletStep (Element taskletStepEle , ParserContext parserContext ) {
291309 AbstractBeanDefinition stepDef = createTaskletStepBeanDefinition (taskletStepEle , parserContext );
292310
293311 String id = taskletStepEle .getAttribute (ID_ATT );
294312
295313 if (StringUtils .hasText (id )) {
296314 parserContext .getRegistry ().registerBeanDefinition (id , stepDef );
315+ return id ;
297316 } else {
298- parserContext .getReaderContext ().registerWithGeneratedName (stepDef );
317+ return parserContext .getReaderContext ().registerWithGeneratedName (stepDef );
299318 }
300319 }
301320
0 commit comments