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 e9b3b84d2..e40e9322e 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 @@ -59,11 +59,10 @@ public abstract class AbstractStepParser { String taskletRef = stepElement.getAttribute("tasklet"); @SuppressWarnings("unchecked") List taskletElements = (List) DomUtils.getChildElementsByTagName(stepElement, "tasklet"); - boolean taskletElementExists = taskletElements.size() > 0; boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); AbstractBeanDefinition bd = null; if (StringUtils.hasText(taskletRef)) { - if (taskletElementExists) { + if (taskletElements.size() > 0) { parserContext.getReaderContext().error( "The <" + taskletElements.get(0).getNodeName() + "> element can't be combined with the 'tasklet=\"" + taskletRef @@ -71,10 +70,13 @@ public abstract class AbstractStepParser { } bd = parseTaskletRef(stepElement, taskletRef, parserContext, jobRepositoryRef); } - else if (taskletElementExists) { + else if (taskletElements.size() == 1) { Element taskElement = taskletElements.get(0); bd = taskletElementParser.parse(taskElement, parserContext, stepUnderspecified); } + else if (taskletElements.size() > 1) { + parserContext.getReaderContext().error("The 'tasklet' element may not appear more than once.", stepElement); + } if (bd != null) { setUpBeanDefinition(stepElement, bd, parserContext, jobRepositoryRef); @@ -123,19 +125,24 @@ public abstract class AbstractStepParser { RuntimeBeanReference transactionManagerBeanRef = new RuntimeBeanReference(transactionManagerRef); bd.getPropertyValues().addPropertyValue("transactionManager", transactionManagerBeanRef); - Element child = DomUtils.getChildElementByTagName(stepElement, "transaction-attributes"); - if (child != null) { - String attributes = DomUtils.getTextValue(child); + List txAttrElements = DomUtils.getChildElementsByTagName(stepElement, "transaction-attributes"); + if (txAttrElements.size() == 1) { + Element txAttrElement = txAttrElements.get(0); + String attributes = DomUtils.getTextValue(txAttrElement); if (StringUtils.hasLength(attributes)) { String[] attributesArray = StringUtils.tokenizeToStringArray(attributes, ",\n"); if (attributesArray.length > 0) { ManagedList managedList = new ManagedList(); - managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute("merge"))); + managedList.setMergeEnabled(Boolean.valueOf(txAttrElement.getAttribute("merge"))); managedList.addAll(Arrays.asList(attributesArray)); bd.getPropertyValues().addPropertyValue("transactionAttributeList", managedList); } } } + else if (txAttrElements.size() > 1) { + parserContext.getReaderContext().error( + "The 'transaction-attribute' element may not appear more than once.", stepElement); + } handleListenersElement(stepElement, bd, parserContext); @@ -161,11 +168,12 @@ public abstract class AbstractStepParser { } @SuppressWarnings("unchecked") - private void handleListenersElement(Element element, BeanDefinition bd, ParserContext parserContext) { - Element listenersElement = DomUtils.getChildElementByTagName(element, "listeners"); - if (listenersElement != null) { + private void handleListenersElement(Element stepElement, BeanDefinition bd, ParserContext parserContext) { + List listenersElements = DomUtils.getChildElementsByTagName(stepElement, "listeners"); + if (listenersElements.size() == 1) { + Element listenersElement = listenersElements.get(0); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(listenersElement.getTagName(), - parserContext.extractSource(element)); + parserContext.extractSource(stepElement)); parserContext.pushContainingComponent(compositeDef); ManagedList listenerBeans = new ManagedList(); listenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute("merge"))); @@ -178,6 +186,10 @@ public abstract class AbstractStepParser { bd.getPropertyValues().addPropertyValue("listeners", listenerBeans); parserContext.popAndRegisterContainingComponent(); } + else if (listenersElements.size() > 1) { + parserContext.getReaderContext().error("The 'listeners' element may not appear more than once.", + stepElement); + } } } 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 b0e8dd716..0b53e4cbd 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 @@ -276,11 +276,11 @@ - + - - + + @@ -288,16 +288,18 @@ - - - + + + + + - + diff --git a/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml b/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml index f18eca14c..d4776c5bb 100644 --- a/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml @@ -37,6 +37,7 @@ + java.lang.RuntimeException