diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java index 7e16bc686..5b99c18a6 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractStepParser.java @@ -52,7 +52,7 @@ public abstract class AbstractStepParser { * @param taskletRef * @param parserContext */ - protected AbstractBeanDefinition handleTaskletRef(Element stepElement, String taskletRef, ParserContext parserContext) { + protected AbstractBeanDefinition parseTaskletRef(Element stepElement, String taskletRef, ParserContext parserContext, String jobRepositoryRef) { RootBeanDefinition bd = new RootBeanDefinition("org.springframework.batch.core.step.tasklet.TaskletStep", null, null); @@ -61,7 +61,6 @@ public abstract class AbstractStepParser { bd.getPropertyValues().addPropertyValue("tasklet", taskletBeanRef); } - String jobRepositoryRef = stepElement.getAttribute("job-repository"); RuntimeBeanReference jobRepositoryBeanRef = new RuntimeBeanReference(jobRepositoryRef); bd.getPropertyValues().addPropertyValue("jobRepository", jobRepositoryBeanRef); @@ -83,7 +82,7 @@ public abstract class AbstractStepParser { * @param element * @param parserContext */ - protected AbstractBeanDefinition handleTaskletElement(Element stepElement, Element element, ParserContext parserContext) { + protected AbstractBeanDefinition parseTaskletElement(Element stepElement, Element element, ParserContext parserContext, String jobRepositoryRef) { RootBeanDefinition bd; @@ -152,12 +151,11 @@ public abstract class AbstractStepParser { bd.getPropertyValues().addPropertyValue("taskExecutor", taskExecutorRef); } - String jobRepository = stepElement.getAttribute("job-repository"); - RuntimeBeanReference jobRepositoryRef = new RuntimeBeanReference(jobRepository); - bd.getPropertyValues().addPropertyValue("jobRepository", jobRepositoryRef); + RuntimeBeanReference jobRepositoryBeanRef = new RuntimeBeanReference(jobRepositoryRef); + bd.getPropertyValues().addPropertyValue("jobRepository", jobRepositoryBeanRef); - String transactionManager = stepElement.getAttribute("transaction-manager"); - RuntimeBeanReference tx = new RuntimeBeanReference(transactionManager); + String transactionManagerRef = stepElement.getAttribute("transaction-manager"); + RuntimeBeanReference tx = new RuntimeBeanReference(transactionManagerRef); bd.getPropertyValues().addPropertyValue("transactionManager", tx); String commitInterval = element.getAttribute("commit-interval"); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowParser.java index 9edd9b72b..3bb223b01 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/FlowParser.java @@ -1,299 +1,302 @@ -/* - * Copyright 2006-2008 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.batch.core.configuration.xml; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.springframework.batch.core.BatchStatus; -import org.springframework.batch.core.ExitStatus; -import org.springframework.batch.core.job.flow.support.SimpleFlow; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.parsing.CompositeComponentDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.ManagedList; -import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; -import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.util.StringUtils; -import org.springframework.util.xml.DomUtils; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; - -/** - * @author Dave Syer - * - */ -public class FlowParser extends AbstractSingleBeanDefinitionParser { - - private static final String NEXT = "next"; - private static final String END = "end"; - private static final String FAIL = "fail"; - private static final String PAUSE = "pause"; - - // For generating unique state names for end transitions - private static int endCounter = 0; - - private final String flowName; - - /** - * Construct a {@link FlowParser} with the specified name. - * @param flowName the name of the flow - */ - public FlowParser(String flowName) { - this.flowName = flowName; - - } - - /* - * (non-Javadoc) - * - * @see AbstractSingleBeanDefinitionParser#getBeanClass(Element) - */ - @Override - protected Class getBeanClass(Element element) { - return SimpleFlow.class; - } - - /** - * @param element the top level element containing a flow definition - * @param parserContext the {@link ParserContext} - */ - @Override - protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - List stateTransitions = new ArrayList(); - - InlineStepParser stepParser = new InlineStepParser(); - DecisionParser decisionParser = new DecisionParser(); - SplitParser splitParser = new SplitParser(); - CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), - parserContext.extractSource(element)); - parserContext.pushContainingComponent(compositeDef); - - NodeList children = element.getChildNodes(); - for (int i = 0; i < children.getLength(); i++) { - Node node = children.item(i); - if (node instanceof Element) { - String nodeName = node.getLocalName(); - if (nodeName.equals("step")) { - stateTransitions.addAll(stepParser.parse((Element) node, parserContext)); - } - else if (nodeName.equals("decision")) { - stateTransitions.addAll(decisionParser.parse((Element) node, parserContext)); - } - else if (nodeName.equals("split")) { - stateTransitions.addAll(splitParser.parse((Element) node, new ParserContext(parserContext - .getReaderContext(), parserContext.getDelegate(), builder.getBeanDefinition()))); - } - } - } - - builder.addConstructorArgValue(flowName); - ManagedList managedList = new ManagedList(); - @SuppressWarnings( { "unchecked", "unused" }) - boolean dummy = managedList.addAll(stateTransitions); - builder.addPropertyValue("stateTransitions", managedList); - - builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); - - parserContext.popAndRegisterContainingComponent(); - - } - - /** - * @param parserContext the parser context for the bean factory - * @param stateDef The bean definition for the current state - * @param element the <step/gt; element to parse - * @return a collection of - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * references - */ - protected static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef, - Element element) { - - Collection list = new ArrayList(); - - String shortNextAttribute = element.getAttribute(NEXT); - boolean hasNextAttribute = StringUtils.hasText(shortNextAttribute); - if (hasNextAttribute) { - list.add(getStateTransitionReference(parserContext, stateDef, null, shortNextAttribute)); - } - - boolean transitionElementExists = false; - List patterns = new ArrayList(); - for (String transitionName : new String[] { NEXT, PAUSE, END, FAIL }) { - @SuppressWarnings("unchecked") - List transitionElements = (List) DomUtils.getChildElementsByTagName(element, - transitionName); - for (Element transitionElement : transitionElements) { - verifyUniquePattern(transitionElement, patterns, element, parserContext); - list.addAll(parseTransitionElement(transitionElement, stateDef, parserContext)); - transitionElementExists = true; - } - } - - if (!transitionElementExists) { - list.addAll(createTransition(BatchStatus.FAILED, ExitStatus.FAILED.getExitCode(), null, null, stateDef, - parserContext)); - if (!hasNextAttribute) { - list.addAll(createTransition(BatchStatus.COMPLETED, null, null, null, stateDef, parserContext)); - } - } - else if (hasNextAttribute) { - parserContext.getReaderContext().error("Step may not contain a 'next' attribute and a transition element", - element); - } - - return list; - } - - /** - * @param transitionElement The element to parse - * @param patterns a list of patterns on state transitions for this element - * @param element - * @param parserContext the parser context for the bean factory - */ - private static void verifyUniquePattern(Element transitionElement, List patterns, Element element, - ParserContext parserContext) { - String onAttribute = transitionElement.getAttribute("on"); - if (patterns.contains(onAttribute)) { - parserContext.getReaderContext().error("Duplicate transition pattern found for '" + onAttribute + "'", - element); - } - patterns.add(onAttribute); - } - - /** - * @param transitionElement The element to parse - * @param stateDef The bean definition for the current state - * @param parserContext the parser context for the bean factory - * @param a collection of - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * references - */ - private static Collection parseTransitionElement(Element transitionElement, - BeanDefinition stateDef, ParserContext parserContext) { - - BatchStatus batchStatus = getBatchStatusFromEndTransitionName(transitionElement.getNodeName()); - String onAttribute = transitionElement.getAttribute("on"); - String nextAttribute = transitionElement.getAttribute("to"); - String statusAttribute = transitionElement.getAttribute("status"); - - return createTransition(batchStatus, onAttribute, nextAttribute, statusAttribute, stateDef, parserContext); - } - - /** - * @param batchStatus The batch status that this transition will set. Use - * BatchStatus.UNKNOWN if not applicable. - * @param on The pattern that this transition should match. Use null for - * "no restriction" (same as "*"). - * @param next The state to which this transition should go. Use null if not - * applicable. - * @param exitCode The exit code that this transition will set. Use null to - * default to batchStatus. - * @param stateDef The bean definition for the current state - * @param parserContext the parser context for the bean factory - * @param a collection of - * {@link org.springframework.batch.core.job.flow.support.StateTransition} - * references - */ - private static Collection createTransition(BatchStatus batchStatus, String on, String next, - String exitCode, BeanDefinition stateDef, ParserContext parserContext) { - - BeanDefinition endState = null; - - if (batchStatus == BatchStatus.STOPPED || batchStatus == BatchStatus.COMPLETED - || batchStatus == BatchStatus.FAILED) { - - BeanDefinitionBuilder endBuilder = BeanDefinitionBuilder - .genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.EndState"); - endBuilder.addConstructorArgValue(batchStatus); - - boolean exitCodeExists = StringUtils.hasText(exitCode); - endBuilder.addConstructorArgValue(new ExitStatus(exitCodeExists ? exitCode : batchStatus.toString())); - - String endName = "end" + (endCounter++); - endBuilder.addConstructorArgValue(endName); - - String nextOnEnd = exitCodeExists ? null : next; - endState = getStateTransitionReference(parserContext, endBuilder.getBeanDefinition(), null, nextOnEnd); - next = endName; - - } - - Collection list = new ArrayList(); - list.add(getStateTransitionReference(parserContext, stateDef, on, next)); - if (endState != null) { - // - // Must be added after the state to ensure that the state is the - // first in the list - // - list.add(endState); - } - return list; - } - - /** - * @param elementName An end transition element name - * @return the BatchStatus corresponding to the transition name - */ - private static BatchStatus getBatchStatusFromEndTransitionName(String elementName) { - if (PAUSE.equals(elementName)) { - return BatchStatus.STOPPED; - } - else if (END.equals(elementName)) { - return BatchStatus.COMPLETED; - } - else if (FAIL.equals(elementName)) { - return BatchStatus.FAILED; - } - else { - return BatchStatus.UNKNOWN; - } - } - - /** - * @param parserContext the parser context - * @param stateDefinition a reference to the state implementation - * @param on the pattern value - * @param next the next step id - * @return a bean definition for a {@link org.springframework.batch.core.job.flow.support.StateTransition} - */ - public static BeanDefinition getStateTransitionReference(ParserContext parserContext, - BeanDefinition stateDefinition, String on, String next) { - - BeanDefinitionBuilder nextBuilder = - BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.job.flow.support.StateTransition"); - nextBuilder.addConstructorArgValue(stateDefinition); - - if (StringUtils.hasText(on)) { - nextBuilder.addConstructorArgValue(on); - } - - if (StringUtils.hasText(next)) { - nextBuilder.setFactoryMethod("createStateTransition"); - nextBuilder.addConstructorArgValue(next); - } - else { - nextBuilder.setFactoryMethod("createEndStateTransition"); - } - - return nextBuilder.getBeanDefinition(); - - } - -} +/* + * Copyright 2006-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.batch.core.configuration.xml; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.job.flow.support.SimpleFlow; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.parsing.CompositeComponentDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.ManagedList; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.util.StringUtils; +import org.springframework.util.xml.DomUtils; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @author Dave Syer + * + */ +public class FlowParser extends AbstractSingleBeanDefinitionParser { + + private static final String NEXT = "next"; + private static final String END = "end"; + private static final String FAIL = "fail"; + private static final String PAUSE = "pause"; + + // For generating unique state names for end transitions + private static int endCounter = 0; + + private final String flowName; + private final String jobRepositoryRef; + + /** + * Construct a {@link FlowParser} with the specified name and using the provided job repository ref. + * @param flowName the name of the flow + * @param jobRepositoryRef the reference to the jobRepository from the enclosing tag + */ + public FlowParser(String flowName, String jobRepositoryRef) { + this.flowName = flowName; + this.jobRepositoryRef = jobRepositoryRef; + + } + + /* + * (non-Javadoc) + * + * @see AbstractSingleBeanDefinitionParser#getBeanClass(Element) + */ + @Override + protected Class getBeanClass(Element element) { + return SimpleFlow.class; + } + + /** + * @param element the top level element containing a flow definition + * @param parserContext the {@link ParserContext} + */ + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + List stateTransitions = new ArrayList(); + + InlineStepParser stepParser = new InlineStepParser(); + DecisionParser decisionParser = new DecisionParser(); + SplitParser splitParser = new SplitParser(jobRepositoryRef); + CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), + parserContext.extractSource(element)); + parserContext.pushContainingComponent(compositeDef); + + NodeList children = element.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node node = children.item(i); + if (node instanceof Element) { + String nodeName = node.getLocalName(); + if (nodeName.equals("step")) { + stateTransitions.addAll(stepParser.parse((Element) node, parserContext, jobRepositoryRef)); + } + else if (nodeName.equals("decision")) { + stateTransitions.addAll(decisionParser.parse((Element) node, parserContext)); + } + else if (nodeName.equals("split")) { + stateTransitions.addAll(splitParser.parse((Element) node, new ParserContext(parserContext + .getReaderContext(), parserContext.getDelegate(), builder.getBeanDefinition()))); + } + } + } + + builder.addConstructorArgValue(flowName); + ManagedList managedList = new ManagedList(); + @SuppressWarnings( { "unchecked", "unused" }) + boolean dummy = managedList.addAll(stateTransitions); + builder.addPropertyValue("stateTransitions", managedList); + + builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); + + parserContext.popAndRegisterContainingComponent(); + + } + + /** + * @param parserContext the parser context for the bean factory + * @param stateDef The bean definition for the current state + * @param element the <step/gt; element to parse + * @return a collection of + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references + */ + protected static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef, + Element element) { + + Collection list = new ArrayList(); + + String shortNextAttribute = element.getAttribute(NEXT); + boolean hasNextAttribute = StringUtils.hasText(shortNextAttribute); + if (hasNextAttribute) { + list.add(getStateTransitionReference(parserContext, stateDef, null, shortNextAttribute)); + } + + boolean transitionElementExists = false; + List patterns = new ArrayList(); + for (String transitionName : new String[] { NEXT, PAUSE, END, FAIL }) { + @SuppressWarnings("unchecked") + List transitionElements = (List) DomUtils.getChildElementsByTagName(element, + transitionName); + for (Element transitionElement : transitionElements) { + verifyUniquePattern(transitionElement, patterns, element, parserContext); + list.addAll(parseTransitionElement(transitionElement, stateDef, parserContext)); + transitionElementExists = true; + } + } + + if (!transitionElementExists) { + list.addAll(createTransition(BatchStatus.FAILED, ExitStatus.FAILED.getExitCode(), null, null, stateDef, + parserContext)); + if (!hasNextAttribute) { + list.addAll(createTransition(BatchStatus.COMPLETED, null, null, null, stateDef, parserContext)); + } + } + else if (hasNextAttribute) { + parserContext.getReaderContext().error("Step may not contain a 'next' attribute and a transition element", + element); + } + + return list; + } + + /** + * @param transitionElement The element to parse + * @param patterns a list of patterns on state transitions for this element + * @param element + * @param parserContext the parser context for the bean factory + */ + private static void verifyUniquePattern(Element transitionElement, List patterns, Element element, + ParserContext parserContext) { + String onAttribute = transitionElement.getAttribute("on"); + if (patterns.contains(onAttribute)) { + parserContext.getReaderContext().error("Duplicate transition pattern found for '" + onAttribute + "'", + element); + } + patterns.add(onAttribute); + } + + /** + * @param transitionElement The element to parse + * @param stateDef The bean definition for the current state + * @param parserContext the parser context for the bean factory + * @param a collection of + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references + */ + private static Collection parseTransitionElement(Element transitionElement, + BeanDefinition stateDef, ParserContext parserContext) { + + BatchStatus batchStatus = getBatchStatusFromEndTransitionName(transitionElement.getNodeName()); + String onAttribute = transitionElement.getAttribute("on"); + String nextAttribute = transitionElement.getAttribute("to"); + String statusAttribute = transitionElement.getAttribute("status"); + + return createTransition(batchStatus, onAttribute, nextAttribute, statusAttribute, stateDef, parserContext); + } + + /** + * @param batchStatus The batch status that this transition will set. Use + * BatchStatus.UNKNOWN if not applicable. + * @param on The pattern that this transition should match. Use null for + * "no restriction" (same as "*"). + * @param next The state to which this transition should go. Use null if not + * applicable. + * @param exitCode The exit code that this transition will set. Use null to + * default to batchStatus. + * @param stateDef The bean definition for the current state + * @param parserContext the parser context for the bean factory + * @param a collection of + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references + */ + private static Collection createTransition(BatchStatus batchStatus, String on, String next, + String exitCode, BeanDefinition stateDef, ParserContext parserContext) { + + BeanDefinition endState = null; + + if (batchStatus == BatchStatus.STOPPED || batchStatus == BatchStatus.COMPLETED + || batchStatus == BatchStatus.FAILED) { + + BeanDefinitionBuilder endBuilder = BeanDefinitionBuilder + .genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.EndState"); + endBuilder.addConstructorArgValue(batchStatus); + + boolean exitCodeExists = StringUtils.hasText(exitCode); + endBuilder.addConstructorArgValue(new ExitStatus(exitCodeExists ? exitCode : batchStatus.toString())); + + String endName = "end" + (endCounter++); + endBuilder.addConstructorArgValue(endName); + + String nextOnEnd = exitCodeExists ? null : next; + endState = getStateTransitionReference(parserContext, endBuilder.getBeanDefinition(), null, nextOnEnd); + next = endName; + + } + + Collection list = new ArrayList(); + list.add(getStateTransitionReference(parserContext, stateDef, on, next)); + if (endState != null) { + // + // Must be added after the state to ensure that the state is the + // first in the list + // + list.add(endState); + } + return list; + } + + /** + * @param elementName An end transition element name + * @return the BatchStatus corresponding to the transition name + */ + private static BatchStatus getBatchStatusFromEndTransitionName(String elementName) { + if (PAUSE.equals(elementName)) { + return BatchStatus.STOPPED; + } + else if (END.equals(elementName)) { + return BatchStatus.COMPLETED; + } + else if (FAIL.equals(elementName)) { + return BatchStatus.FAILED; + } + else { + return BatchStatus.UNKNOWN; + } + } + + /** + * @param parserContext the parser context + * @param stateDefinition a reference to the state implementation + * @param on the pattern value + * @param next the next step id + * @return a bean definition for a {@link org.springframework.batch.core.job.flow.support.StateTransition} + */ + public static BeanDefinition getStateTransitionReference(ParserContext parserContext, + BeanDefinition stateDefinition, String on, String next) { + + BeanDefinitionBuilder nextBuilder = + BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.job.flow.support.StateTransition"); + nextBuilder.addConstructorArgValue(stateDefinition); + + if (StringUtils.hasText(on)) { + nextBuilder.addConstructorArgValue(on); + } + + if (StringUtils.hasText(next)) { + nextBuilder.setFactoryMethod("createStateTransition"); + nextBuilder.addConstructorArgValue(next); + } + else { + nextBuilder.setFactoryMethod("createEndStateTransition"); + } + + return nextBuilder.getBeanDefinition(); + + } + +} diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java index 785e4827f..4ada422a8 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/InlineStepParser.java @@ -46,10 +46,11 @@ public class InlineStepParser extends AbstractStepParser { * * @param element the <step/gt; element to parse * @param parserContext the parser context for the bean factory + * @param jobRepositoryRef the reference to the jobRepository from the enclosing tag * @return a collection of bean definitions for {@link org.springframework.batch.core.job.flow.support.StateTransition} * instances objects */ - public Collection parse(Element element, ParserContext parserContext) { + public Collection parse(Element element, ParserContext parserContext, String jobRepositoryRef) { BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder.genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.StepState"); @@ -63,13 +64,13 @@ public class InlineStepParser extends AbstractStepParser { @SuppressWarnings("unchecked") List processTaskElements = (List) DomUtils.getChildElementsByTagName(element, "tasklet"); if (StringUtils.hasText(taskletRef)) { - AbstractBeanDefinition bd = handleTaskletRef(element, taskletRef, parserContext); + AbstractBeanDefinition bd = parseTaskletRef(element, taskletRef, parserContext, jobRepositoryRef); parserContext.registerBeanComponent(new BeanComponentDefinition(bd, stepRef)); stateBuilder.addConstructorArgReference(stepRef); } else if (processTaskElements.size() > 0) { Element taskElement = processTaskElements.get(0); - AbstractBeanDefinition bd = handleTaskletElement(element, taskElement, parserContext); + AbstractBeanDefinition bd = parseTaskletElement(element, taskElement, parserContext, jobRepositoryRef); parserContext.registerBeanComponent(new BeanComponentDefinition(bd, stepRef)); stateBuilder.addConstructorArgReference(stepRef); } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java index 3023eb2e3..e726af659 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParser.java @@ -70,7 +70,7 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { builder.addPropertyReference("jobParametersIncrementer", incrementer); } - FlowParser flowParser = new FlowParser(jobName); + FlowParser flowParser = new FlowParser(jobName, repositoryAttribute); BeanDefinition flowDef = flowParser.parse(element, parserContext); builder.addPropertyValue("flow", flowDef); diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java index 46ef874d7..33b1967db 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/SplitParser.java @@ -40,6 +40,17 @@ import org.w3c.dom.Element; */ public class SplitParser { + private final String jobRepositoryRef; + + /** + * Construct a {@link FlowParser} using the provided job repository ref. + * @param jobRepositoryRef the reference to the jobRepository from the enclosing tag + */ + public SplitParser(String jobRepositoryRef) { + this.jobRepositoryRef = jobRepositoryRef; + } + + /** * Parse the split and turn it into a list of transitions. * @@ -62,7 +73,7 @@ public class SplitParser { Collection flows = new ArrayList(); int i = 0; for (Element nextElement : flowElements) { - FlowParser flowParser = new FlowParser(idAttribute+"#"+i); + FlowParser flowParser = new FlowParser(idAttribute+"#"+i, jobRepositoryRef); flows.add(flowParser.parse(nextElement, parserContext)); i++; } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java index 2d920af5a..64ef79b68 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/StandaloneStepParser.java @@ -45,23 +45,18 @@ public class StandaloneStepParser extends AbstractStepParser { */ public AbstractBeanDefinition parse(Element element, ParserContext parserContext) { -// String stepId = element.getAttribute("id"); String taskletRef = element.getAttribute("tasklet"); + String jobRepositoryRef = element.getAttribute("job-repository"); -// TODO: this should be required in xsd -// if (!StringUtils.hasText(stepId)) { -// parserContext.getReaderContext().error("The id attribute can't be empty for <" + element.getNodeName() + ">", element); -// } - @SuppressWarnings("unchecked") List processTaskElements = (List) DomUtils.getChildElementsByTagName(element, "tasklet"); AbstractBeanDefinition bd = null; if (StringUtils.hasText(taskletRef)) { - bd = handleTaskletRef(element, taskletRef, parserContext); + bd = parseTaskletRef(element, taskletRef, parserContext, jobRepositoryRef); } else if (processTaskElements.size() > 0) { Element taskElement = processTaskElements.get(0); - bd = handleTaskletElement(element, taskElement, parserContext); + bd = parseTaskletElement(element, taskElement, parserContext, jobRepositoryRef); } return bd; diff --git a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd index 6c59a5d14..30bfd842f 100644 --- a/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd +++ b/spring-batch-core/src/main/resources/org/springframework/batch/core/configuration/xml/spring-batch-2.0.xsd @@ -64,6 +64,7 @@ + @@ -285,7 +286,6 @@ -