From 6efcda99d6920a9b13489c7b8ad37f396329d9a9 Mon Sep 17 00:00:00 2001 From: dhgarrette Date: Fri, 20 Mar 2009 18:02:05 +0000 Subject: [PATCH] BATCH-1167: Create constants for element and attribute names in the namespace --- .../xml/AbstractListenerParser.java | 19 +++- .../configuration/xml/AbstractStepParser.java | 55 +++++---- .../core/configuration/xml/FlowParser.java | 106 ++++++++++-------- .../configuration/xml/InlineStepParser.java | 40 +++---- .../core/configuration/xml/JobParser.java | 7 +- .../xml/TaskletElementParser.java | 48 +++++--- 6 files changed, 164 insertions(+), 111 deletions(-) diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java index d2f0a7e96..7957c113d 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractListenerParser.java @@ -22,6 +22,12 @@ import org.w3c.dom.NamedNodeMap; */ public abstract class AbstractListenerParser { + private static final String ID_ATTR = "id"; + + private static final String REF_ATTR = "ref"; + + private static final String CLASS_ATTR = "class"; + public AbstractBeanDefinition parse(Element element, ParserContext parserContext) { BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(getBeanClass()); doParse(element, parserContext, builder); @@ -30,9 +36,9 @@ public abstract class AbstractListenerParser { @SuppressWarnings("unchecked") public void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { - String id = element.getAttribute("id"); - String listenerRef = element.getAttribute("ref"); - String className = element.getAttribute("class"); + String id = element.getAttribute(ID_ATTR); + String listenerRef = element.getAttribute(REF_ATTR); + String className = element.getAttribute(CLASS_ATTR); checkListenerElementAttributes(parserContext, element, id, listenerRef, className); if (StringUtils.hasText(listenerRef)) { @@ -44,7 +50,8 @@ public abstract class AbstractListenerParser { } else { parserContext.getReaderContext().error( - "Neither 'ref' or 'class' specified for <" + element.getTagName() + "> element", element); + "Neither '" + REF_ATTR + "' or '" + CLASS_ATTR + "' specified for <" + element.getTagName() + + "> element", element); } ManagedMap metaDataMap = new ManagedMap(); @@ -69,8 +76,8 @@ public abstract class AbstractListenerParser { attributes.append(attributeNodes.item(i)); } parserContext.getReaderContext().error( - "Either 'ref' or 'class' may be specified, but not both; <" + element.getTagName() - + "> element specified with attributes: " + attributes, element); + "Either '" + REF_ATTR + "' or '" + CLASS_ATTR + "' may be specified, but not both; <" + + element.getTagName() + "> element specified with attributes: " + attributes, element); } } 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 38b075b9d..ace7157e6 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 @@ -44,6 +44,20 @@ import org.w3c.dom.Element; */ public abstract class AbstractStepParser { + protected static final String ID_ATTR = "id"; + + protected static final String PARENT_ATTR = "parent"; + + protected static final String TASKLET_ATTR = "tasklet"; + + protected static final String TASKLET_ELE = "tasklet"; + + protected static final String LISTENERS_ELE = "listeners"; + + protected static final String MERGE_ATTR = "merge"; + + private static final String TX_ATTRIBUTES_ELE = "transaction-attributes"; + private TaskletElementParser taskletElementParser = new TaskletElementParser(); private StepListenerParser stepListenerParser = new StepListenerParser(); @@ -56,17 +70,17 @@ public abstract class AbstractStepParser { protected AbstractBeanDefinition parseTasklet(Element stepElement, ParserContext parserContext, String jobRepositoryRef) { - String taskletRef = stepElement.getAttribute("tasklet"); + String taskletRef = stepElement.getAttribute(TASKLET_ATTR); @SuppressWarnings("unchecked") - List taskletElements = (List) DomUtils.getChildElementsByTagName(stepElement, "tasklet"); + List taskletElements = (List) DomUtils.getChildElementsByTagName(stepElement, TASKLET_ELE); boolean stepUnderspecified = CoreNamespaceUtils.isUnderspecified(stepElement); AbstractBeanDefinition bd = null; if (StringUtils.hasText(taskletRef)) { if (taskletElements.size() > 0) { parserContext.getReaderContext().error( - "The <" + taskletElements.get(0).getNodeName() - + "> element can't be combined with the 'tasklet=\"" + taskletRef - + "\"' attribute specification for <" + stepElement.getNodeName() + ">", stepElement); + "The <" + TASKLET_ELE + "/> element can't be combined with the '" + TASKLET_ATTR + "=\"" + + taskletRef + "\"' attribute specification for <" + stepElement.getNodeName() + "/>", + stepElement); } bd = parseTaskletRef(stepElement, taskletRef, parserContext, jobRepositoryRef); } @@ -76,7 +90,8 @@ public abstract class AbstractStepParser { } else if (taskletElements.size() > 1) { parserContext.getReaderContext().error( - "The 'tasklet' element may not appear more than once in a single .", stepElement); + "The '<" + TASKLET_ELE + "/>' element may not appear more than once in a single <" + + stepElement.getNodeName() + "/>.", stepElement); } if (bd != null) { @@ -84,8 +99,8 @@ public abstract class AbstractStepParser { } else if (!stepUnderspecified) { parserContext.getReaderContext().error( - "Step [" + stepElement.getAttribute("id") - + "] has neither a element nor a 'tasklet' attribute.", stepElement); + "Step [" + stepElement.getAttribute(ID_ATTR) + "] has neither a <" + TASKLET_ELE + + "/> element nor a '" + TASKLET_ATTR + "' attribute.", stepElement); } return bd; @@ -126,7 +141,7 @@ public abstract class AbstractStepParser { RuntimeBeanReference transactionManagerBeanRef = new RuntimeBeanReference(transactionManagerRef); bd.getPropertyValues().addPropertyValue("transactionManager", transactionManagerBeanRef); - List txAttrElements = DomUtils.getChildElementsByTagName(stepElement, "transaction-attributes"); + List txAttrElements = DomUtils.getChildElementsByTagName(stepElement, TX_ATTRIBUTES_ELE); if (txAttrElements.size() == 1) { Element txAttrElement = txAttrElements.get(0); String propagation = txAttrElement.getAttribute("propagation"); @@ -144,13 +159,14 @@ public abstract class AbstractStepParser { } else if (txAttrElements.size() > 1) { parserContext.getReaderContext().error( - "The 'transaction-attributes' element may not appear more than once in a single .", - stepElement); + "The '" + TX_ATTRIBUTES_ELE + "' element may not appear more than once in a single <" + + stepElement.getNodeName() + "/>.", stepElement); } handleListenersElement(stepElement, bd, parserContext); - - handleExceptionElement(stepElement, parserContext, bd, "no-rollback-exception-classes", "noRollbackExceptionClasses"); + + handleExceptionElement(stepElement, parserContext, bd, "no-rollback-exception-classes", + "noRollbackExceptionClasses"); bd.setRole(BeanDefinition.ROLE_SUPPORT); @@ -168,7 +184,7 @@ public abstract class AbstractStepParser { String[] exceptionArray = StringUtils.tokenizeToStringArray(exceptions, ",\n"); if (exceptionArray.length > 0) { ManagedList managedList = new ManagedList(); - managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute("merge"))); + managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute(MERGE_ATTR))); managedList.addAll(Arrays.asList(exceptionArray)); bd.getPropertyValues().addPropertyValue(propertyName, managedList); } @@ -185,7 +201,7 @@ public abstract class AbstractStepParser { if (StringUtils.hasText(allowStartIfComplete)) { bd.getPropertyValues().addPropertyValue("allowStartIfComplete", allowStartIfComplete); } - String parentRef = stepElement.getAttribute("parent"); + String parentRef = stepElement.getAttribute(PARENT_ATTR); if (StringUtils.hasText(parentRef)) { bd.setParentName(parentRef); } @@ -193,14 +209,14 @@ public abstract class AbstractStepParser { @SuppressWarnings("unchecked") private void handleListenersElement(Element stepElement, BeanDefinition bd, ParserContext parserContext) { - List listenersElements = DomUtils.getChildElementsByTagName(stepElement, "listeners"); + List listenersElements = DomUtils.getChildElementsByTagName(stepElement, LISTENERS_ELE); if (listenersElements.size() == 1) { Element listenersElement = listenersElements.get(0); CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(listenersElement.getTagName(), parserContext.extractSource(stepElement)); parserContext.pushContainingComponent(compositeDef); ManagedList listenerBeans = new ManagedList(); - listenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute("merge"))); + listenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute(MERGE_ATTR))); List listenerElements = DomUtils.getChildElementsByTagName(listenersElement, "listener"); if (listenerElements != null) { for (Element listenerElement : listenerElements) { @@ -211,8 +227,9 @@ public abstract class AbstractStepParser { parserContext.popAndRegisterContainingComponent(); } else if (listenersElements.size() > 1) { - parserContext.getReaderContext().error("The 'listeners' element may not appear more than once in a single .", - stepElement); + parserContext.getReaderContext().error( + "The '" + LISTENERS_ELE + "' element may not appear more than once in a single <" + + stepElement.getNodeName() + "/>.", stepElement); } } 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 78f9688cb..4fb70ba93 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 @@ -39,13 +39,29 @@ import org.w3c.dom.NodeList; */ public class FlowParser extends AbstractSingleBeanDefinitionParser { - private static final String NEXT = "next"; + private static final String STEP_ELE = "step"; - private static final String END = "end"; + private static final String DECISION_ELE = "decision"; - private static final String FAIL = "fail"; + private static final String SPLIT_ELE = "split"; - private static final String STOP = "stop"; + private static final String NEXT_ATTR = "next"; + + private static final String NEXT_ELE = "next"; + + private static final String END_ELE = "end"; + + private static final String FAIL_ELE = "fail"; + + private static final String STOP_ELE = "stop"; + + private static final String ON_ATTR = "on"; + + private static final String TO_ATTR = "to"; + + private static final String RESTART_ATTR = "restart"; + + private static final String EXIT_CODE_ATTR = "exit-code"; // For generating unique state names for end transitions private static int endCounter = 0; @@ -60,7 +76,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { * * @param flowName the name of the flow * @param jobRepositoryRef the reference to the jobRepository from the - * enclosing tag + * enclosing tag */ public FlowParser(String flowName, String jobRepositoryRef) { this.flowName = flowName; @@ -99,14 +115,14 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { Node node = children.item(i); if (node instanceof Element) { String nodeName = node.getLocalName(); - if (nodeName.equals("step")) { + if (nodeName.equals(STEP_ELE)) { stateTransitions.addAll(stepParser.parse((Element) node, parserContext, jobRepositoryRef)); stepExists = true; } - else if (nodeName.equals("decision")) { + else if (nodeName.equals(DECISION_ELE)) { stateTransitions.addAll(decisionParser.parse((Element) node, parserContext)); } - else if (nodeName.equals("split")) { + else if (nodeName.equals(SPLIT_ELE)) { stateTransitions.addAll(splitParser.parse((Element) node, new ParserContext(parserContext .getReaderContext(), parserContext.getDelegate(), builder.getBeanDefinition()))); stepExists = true; @@ -117,7 +133,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { if (!stepExists && !CoreNamespaceUtils.isUnderspecified(element)) { parserContext.getReaderContext().error("A flow must contain at least one step", element); } - + builder.addConstructorArgValue(flowName); ManagedList managedList = new ManagedList(); @SuppressWarnings( { "unchecked", "unused" }) @@ -135,8 +151,8 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { * @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 + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references */ protected static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef, Element element) { @@ -146,19 +162,19 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { /** * @param parserContext the parser context for the bean factory * @param stepId the id of the current state if it is a step state, null - * otherwise + * otherwise * @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 + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references */ protected static Collection getNextElements(ParserContext parserContext, String stepId, BeanDefinition stateDef, Element element) { Collection list = new ArrayList(); - String shortNextAttribute = element.getAttribute(NEXT); + String shortNextAttribute = element.getAttribute(NEXT_ATTR); boolean hasNextAttribute = StringUtils.hasText(shortNextAttribute); if (hasNextAttribute) { list.add(getStateTransitionReference(parserContext, stateDef, null, shortNextAttribute)); @@ -166,7 +182,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { boolean transitionElementExists = false; List patterns = new ArrayList(); - for (String transitionName : new String[] { NEXT, STOP, END, FAIL }) { + for (String transitionName : new String[] { NEXT_ELE, STOP_ELE, END_ELE, FAIL_ELE }) { @SuppressWarnings("unchecked") List transitionElements = (List) DomUtils.getChildElementsByTagName(element, transitionName); @@ -178,15 +194,17 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { } if (!transitionElementExists) { - list.addAll(createTransition(FlowExecutionStatus.FAILED, FlowExecutionStatus.FAILED.getName(), null, null, stateDef, parserContext, false)); + list.addAll(createTransition(FlowExecutionStatus.FAILED, FlowExecutionStatus.FAILED.getName(), null, null, + stateDef, parserContext, false)); if (!hasNextAttribute) { list.addAll(createTransition(FlowExecutionStatus.COMPLETED, null, null, null, stateDef, parserContext, false)); } } else if (hasNextAttribute) { - parserContext.getReaderContext().error("Step may not contain a 'next' attribute and a transition element", - element); + parserContext.getReaderContext().error( + "The <" + element.getNodeName() + "/> may not contain a '" + NEXT_ATTR + + "' attribute and a transition element", element); } return list; @@ -200,7 +218,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { */ private static void verifyUniquePattern(Element transitionElement, List patterns, Element element, ParserContext parserContext) { - String onAttribute = transitionElement.getAttribute("on"); + String onAttribute = transitionElement.getAttribute(ON_ATTR); if (patterns.contains(onAttribute)) { parserContext.getReaderContext().error("Duplicate transition pattern found for '" + onAttribute + "'", element); @@ -213,41 +231,39 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { * @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 + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references */ private static Collection parseTransitionElement(Element transitionElement, String stateId, BeanDefinition stateDef, ParserContext parserContext) { FlowExecutionStatus status = getBatchStatusFromEndTransitionName(transitionElement.getNodeName()); - String onAttribute = transitionElement.getAttribute("on"); - String nextAttribute = transitionElement.getAttribute("to"); - String restartAttribute = transitionElement.getAttribute("restart"); - nextAttribute = StringUtils.hasText(nextAttribute) ? nextAttribute : restartAttribute; - boolean abandon = false; - if (stateId != null && StringUtils.hasText(restartAttribute) && !restartAttribute.equals(stateId)) { - abandon = true; + String onAttribute = transitionElement.getAttribute(ON_ATTR); + String restartAttribute = transitionElement.getAttribute(RESTART_ATTR); + String nextAttribute = transitionElement.getAttribute(TO_ATTR); + if (!StringUtils.hasText(nextAttribute)) { + nextAttribute = restartAttribute; } - String exitCodeAttribute = transitionElement.getAttribute("exit-code"); + boolean abandon = stateId != null && StringUtils.hasText(restartAttribute) && !restartAttribute.equals(stateId); + String exitCodeAttribute = transitionElement.getAttribute(EXIT_CODE_ATTR); - return createTransition(status, onAttribute, nextAttribute, exitCodeAttribute, stateDef, parserContext, - abandon); + return createTransition(status, onAttribute, nextAttribute, exitCodeAttribute, stateDef, parserContext, abandon); } /** * @param status The batch status that this transition will set. Use - * BatchStatus.UNKNOWN if not applicable. + * BatchStatus.UNKNOWN if not applicable. * @param on The pattern that this transition should match. Use null for - * "no restriction" (same as "*"). + * "no restriction" (same as "*"). * @param next The state to which this transition should go. Use null if not - * applicable. + * applicable. * @param exitCode The exit code that this transition will set. Use null to - * default to batchStatus. + * 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 + * {@link org.springframework.batch.core.job.flow.support.StateTransition} + * references */ private static Collection createTransition(FlowExecutionStatus status, String on, String next, String exitCode, BeanDefinition stateDef, ParserContext parserContext, boolean abandon) { @@ -266,9 +282,9 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { endBuilder.addConstructorArgValue(status); endBuilder.addConstructorArgValue(exitCodeExists ? exitCode : status.getName()); - - String endName = (status == FlowExecutionStatus.STOPPED ? STOP - : status == FlowExecutionStatus.FAILED ? FAIL : END) + + String endName = (status == FlowExecutionStatus.STOPPED ? STOP_ELE + : status == FlowExecutionStatus.FAILED ? FAIL_ELE : END_ELE) + (endCounter++); endBuilder.addConstructorArgValue(endName); @@ -297,13 +313,13 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { * @return the BatchStatus corresponding to the transition name */ private static FlowExecutionStatus getBatchStatusFromEndTransitionName(String elementName) { - if (STOP.equals(elementName)) { + if (STOP_ELE.equals(elementName)) { return FlowExecutionStatus.STOPPED; } - else if (END.equals(elementName)) { + else if (END_ELE.equals(elementName)) { return FlowExecutionStatus.COMPLETED; } - else if (FAIL.equals(elementName)) { + else if (FAIL_ELE.equals(elementName)) { return FlowExecutionStatus.FAILED; } else { @@ -317,7 +333,7 @@ public class FlowParser extends AbstractSingleBeanDefinitionParser { * @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} + * {@link org.springframework.batch.core.job.flow.support.StateTransition} */ public static BeanDefinition getStateTransitionReference(ParserContext parserContext, BeanDefinition stateDefinition, String on, String next) { 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 584e1ed2b..c30a2f6c0 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 @@ -42,6 +42,8 @@ import org.w3c.dom.Element; */ public class InlineStepParser extends AbstractStepParser { + private static final String REF_ATTR = "ref"; + /** * Parse the step and turn it into a list of transitions. * @@ -57,37 +59,28 @@ public class InlineStepParser extends AbstractStepParser { BeanDefinitionBuilder stateBuilder = BeanDefinitionBuilder .genericBeanDefinition("org.springframework.batch.core.job.flow.support.state.StepState"); - String stepId = element.getAttribute("id"); - String stepRef = element.getAttribute("ref"); - String taskletRef = element.getAttribute("tasklet"); + String stepId = element.getAttribute(ID_ATTR); + String stepRef = element.getAttribute(REF_ATTR); + String taskletRef = element.getAttribute(TASKLET_ATTR); @SuppressWarnings("unchecked") - List listOfTaskElements = (List) DomUtils.getChildElementsByTagName(element, "tasklet"); + List listOfTaskElements = (List) DomUtils.getChildElementsByTagName(element, TASKLET_ELE); @SuppressWarnings("unchecked") - List listOfListenersElements = (List) DomUtils - .getChildElementsByTagName(element, "listeners"); + List listOfListenersElements = (List) DomUtils.getChildElementsByTagName(element, + LISTENERS_ELE); if (StringUtils.hasText(stepRef)) { if (StringUtils.hasText(taskletRef)) { - parserContext.getReaderContext().error( - "The 'tasklet' attribute can't be combined with the 'ref=\"" + stepRef - + "\"' attribute specification for <" + element.getNodeName() + ">", element); + cantBeCombinedWithRef(TASKLET_ATTR, "attribute", element, parserContext); } if (listOfTaskElements.size() > 0) { - parserContext.getReaderContext().error( - "The <" + listOfTaskElements.get(0).getNodeName() - + "> element can't be combined with the 'ref=\"" + stepRef - + "\"' attribute specification for <" + element.getNodeName() + ">", element); + cantBeCombinedWithRef(TASKLET_ELE, "element", element, parserContext); } if (listOfListenersElements.size() > 0) { - parserContext.getReaderContext().error( - "The 'listeners' element can't be combined with the 'ref=\"" + stepRef - + "\"' attribute specification for <" + element.getNodeName() + ">", element); + cantBeCombinedWithRef(LISTENERS_ELE, "element", element, parserContext); } - if (StringUtils.hasText(element.getAttribute("parent"))) { - parserContext.getReaderContext().error( - "The 'parent' element can't be combined with the 'ref=\"" + stepRef - + "\"' attribute specification for <" + element.getNodeName() + ">", element); + if (StringUtils.hasText(element.getAttribute(PARENT_ATTR))) { + cantBeCombinedWithRef(PARENT_ATTR, "attribute", element, parserContext); } BeanDefinitionBuilder stepBuilder = BeanDefinitionBuilder .genericBeanDefinition("org.springframework.batch.core.configuration.xml.DelegatingStep"); @@ -109,4 +102,11 @@ public class InlineStepParser extends AbstractStepParser { } + private void cantBeCombinedWithRef(String itemName, String itemType, Element element, ParserContext parserContext) { + parserContext.getReaderContext().error( + "The '" + itemName + "' " + itemType + " can't be combined with the '" + REF_ATTR + "=\"" + + element.getAttribute(REF_ATTR) + "\"' attribute specification for <" + element.getNodeName() + + ">", element); + } + } 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 748eb689d..12b02d202 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 @@ -37,6 +37,8 @@ import org.w3c.dom.Element; */ public class JobParser extends AbstractSingleBeanDefinitionParser { + private JobExecutionListenerParser jobListenerParser = new JobExecutionListenerParser(); + @Override protected Class getBeanClass(Element element) { return FlowJob.class; @@ -89,7 +91,6 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { BeanDefinition flowDef = flowParser.parse(element, parserContext); builder.addPropertyValue("flow", flowDef); - JobExecutionListenerParser listenerParser = new JobExecutionListenerParser(); List listenersElements = DomUtils.getChildElementsByTagName(element, "listeners"); if (listenersElements.size() == 1) { Element listenersElement = listenersElements.get(0); @@ -101,7 +102,7 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { List listenerElements = (List) DomUtils.getChildElementsByTagName(listenersElement, "listener"); for (Element listenerElement : listenerElements) { - listeners.add(listenerParser.parse(listenerElement, parserContext)); + listeners.add(jobListenerParser.parse(listenerElement, parserContext)); } builder.addPropertyValue("jobExecutionListeners", listeners); parserContext.popAndRegisterContainingComponent(); @@ -110,7 +111,7 @@ public class JobParser extends AbstractSingleBeanDefinitionParser { parserContext.getReaderContext().error( "The 'listeners' element may not appear more than once in a single .", element); } - + } } diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletElementParser.java index 96ec46510..1d39528d2 100644 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletElementParser.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/TaskletElementParser.java @@ -42,6 +42,18 @@ import org.w3c.dom.NamedNodeMap; */ public class TaskletElementParser { + private static final String ID_ATTR = "id"; + + private static final String REF_ATTR = "ref"; + + private static final String CLASS_ATTR = "class"; + + private static final String MERGE_ATTR = "merge"; + + private static final String COMMIT_INTERVAL_ATTR = "commit-interval"; + + private static final String CHUNK_COMPLETION_POLICY_ATTR = "chunk-completion-policy"; + /** * @param element * @param parserContext @@ -54,7 +66,7 @@ public class TaskletElementParser { MutablePropertyValues propertyValues = bd.getPropertyValues(); propertyValues.addPropertyValue("hasTaskletElement", Boolean.TRUE); - + String readerBeanId = element.getAttribute("reader"); if (StringUtils.hasText(readerBeanId)) { RuntimeBeanReference readerRef = new RuntimeBeanReference(readerBeanId); @@ -79,12 +91,12 @@ public class TaskletElementParser { propertyValues.addPropertyValue("taskExecutor", taskExecutorRef); } - String commitInterval = element.getAttribute("commit-interval"); + String commitInterval = element.getAttribute(COMMIT_INTERVAL_ATTR); if (StringUtils.hasText(commitInterval)) { propertyValues.addPropertyValue("commitInterval", commitInterval); } - String completionPolicyRef = element.getAttribute("chunk-completion-policy"); + String completionPolicyRef = element.getAttribute(CHUNK_COMPLETION_POLICY_ATTR); if (StringUtils.hasText(completionPolicyRef)) { RuntimeBeanReference completionPolicy = new RuntimeBeanReference(completionPolicyRef); propertyValues.addPropertyValue("chunkCompletionPolicy", completionPolicy); @@ -93,8 +105,8 @@ public class TaskletElementParser { if (!underspecified && propertyValues.contains("commitInterval") == propertyValues.contains("chunkCompletionPolicy")) { parserContext.getReaderContext().error( - "The 'tasklet' element must contain either 'commit-interval' " - + "or 'chunk-completion-policy', but not both.", element); + "The '" + element.getNodeName() + "' element must contain either '" + COMMIT_INTERVAL_ATTR + "' " + + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "', but not both.", element); } String skipLimit = element.getAttribute("skip-limit"); @@ -141,7 +153,7 @@ public class TaskletElementParser { String[] exceptionArray = StringUtils.tokenizeToStringArray(exceptions, ",\n"); if (exceptionArray.length > 0) { ManagedList managedList = new ManagedList(); - managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute("merge"))); + managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute(MERGE_ATTR))); managedList.addAll(Arrays.asList(exceptionArray)); bd.getPropertyValues().addPropertyValue(propertyName, managedList); } @@ -156,7 +168,7 @@ public class TaskletElementParser { parserContext.extractSource(element)); parserContext.pushContainingComponent(compositeDef); ManagedList retryListenerBeans = new ManagedList(); - retryListenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute("merge"))); + retryListenerBeans.setMergeEnabled(Boolean.valueOf(listenersElement.getAttribute(MERGE_ATTR))); handleRetryListenerElements(parserContext, listenersElement, retryListenerBeans); bd.getPropertyValues().addPropertyValue("retryListeners", retryListenerBeans); parserContext.popAndRegisterContainingComponent(); @@ -168,9 +180,9 @@ public class TaskletElementParser { List listenerElements = DomUtils.getChildElementsByTagName(element, "listener"); if (listenerElements != null) { for (Element listenerElement : listenerElements) { - String id = listenerElement.getAttribute("id"); - String listenerRef = listenerElement.getAttribute("ref"); - String className = listenerElement.getAttribute("class"); + String id = listenerElement.getAttribute(ID_ATTR); + String listenerRef = listenerElement.getAttribute(REF_ATTR); + String className = listenerElement.getAttribute(CLASS_ATTR); checkListenerElementAttributes(parserContext, element, listenerElement, id, listenerRef, className); if (StringUtils.hasText(listenerRef)) { BeanReference bean = new RuntimeBeanReference(listenerRef); @@ -185,8 +197,8 @@ public class TaskletElementParser { } else { parserContext.getReaderContext().error( - "Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element", - element); + "Neither '" + REF_ATTR + "' or '" + CLASS_ATTR + "' specified for <" + + listenerElement.getTagName() + "> element", element); } } } @@ -194,7 +206,7 @@ public class TaskletElementParser { private void checkListenerElementAttributes(ParserContext parserContext, Element element, Element listenerElement, String id, String listenerRef, String className) { - if ((StringUtils.hasText(id) || StringUtils.hasText(className)) && StringUtils.hasText(listenerRef)) { + if (StringUtils.hasText(className) && StringUtils.hasText(listenerRef)) { NamedNodeMap attributeNodes = listenerElement.getAttributes(); StringBuilder attributes = new StringBuilder(); for (int i = 0; i < attributeNodes.getLength(); i++) { @@ -204,8 +216,8 @@ public class TaskletElementParser { attributes.append(attributeNodes.item(i)); } parserContext.getReaderContext().error( - "Both 'ref' and " + (StringUtils.hasText(id) ? "'id'" : "'class'") - + " specified; use 'class' with an optional 'id' or just 'ref' for <" + "Both '" + REF_ATTR + "' and '" + CLASS_ATTR + "' specified; use '" + CLASS_ATTR + + "' with an optional '" + ID_ATTR + "' or just '" + REF_ATTR + "' for <" + listenerElement.getTagName() + "> element specified with attributes: " + attributes, element); } @@ -216,18 +228,18 @@ public class TaskletElementParser { Element streamsElement = DomUtils.getChildElementByTagName(element, "streams"); if (streamsElement != null) { ManagedList streamBeans = new ManagedList(); - streamBeans.setMergeEnabled(Boolean.valueOf(streamsElement.getAttribute("merge"))); + streamBeans.setMergeEnabled(Boolean.valueOf(streamsElement.getAttribute(MERGE_ATTR))); List streamElements = DomUtils.getChildElementsByTagName(streamsElement, "stream"); if (streamElements != null) { for (Element streamElement : streamElements) { - String streamRef = streamElement.getAttribute("ref"); + String streamRef = streamElement.getAttribute(REF_ATTR); if (StringUtils.hasText(streamRef)) { BeanReference bean = new RuntimeBeanReference(streamRef); streamBeans.add(bean); } else { parserContext.getReaderContext().error( - "ref not specified for <" + streamElement.getTagName() + "> element", element); + REF_ATTR + " not specified for <" + streamElement.getTagName() + "> element", element); } } }