BATCH-1167: Create constants for element and attribute names in the namespace
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Element> taskletElements = (List<Element>) DomUtils.getChildElementsByTagName(stepElement, "tasklet");
|
||||
List<Element> taskletElements = (List<Element>) 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 <step/>.", 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 <tasklet/> 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<Element> txAttrElements = DomUtils.getChildElementsByTagName(stepElement, "transaction-attributes");
|
||||
List<Element> 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 <step/>.",
|
||||
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<Element> listenersElements = DomUtils.getChildElementsByTagName(stepElement, "listeners");
|
||||
List<Element> 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<Element> 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 <step/>.",
|
||||
stepElement);
|
||||
parserContext.getReaderContext().error(
|
||||
"The '" + LISTENERS_ELE + "' element may not appear more than once in a single <"
|
||||
+ stepElement.getNodeName() + "/>.", stepElement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<BeanDefinition> 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<BeanDefinition> getNextElements(ParserContext parserContext, String stepId,
|
||||
BeanDefinition stateDef, Element element) {
|
||||
|
||||
Collection<BeanDefinition> list = new ArrayList<BeanDefinition>();
|
||||
|
||||
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<String> patterns = new ArrayList<String>();
|
||||
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<Element> transitionElements = (List<Element>) 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<String> 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<BeanDefinition> 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<BeanDefinition> 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) {
|
||||
|
||||
@@ -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<Element> listOfTaskElements = (List<Element>) DomUtils.getChildElementsByTagName(element, "tasklet");
|
||||
List<Element> listOfTaskElements = (List<Element>) DomUtils.getChildElementsByTagName(element, TASKLET_ELE);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Element> listOfListenersElements = (List<Element>) DomUtils
|
||||
.getChildElementsByTagName(element, "listeners");
|
||||
List<Element> listOfListenersElements = (List<Element>) 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ import org.w3c.dom.Element;
|
||||
*/
|
||||
public class JobParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
private JobExecutionListenerParser jobListenerParser = new JobExecutionListenerParser();
|
||||
|
||||
@Override
|
||||
protected Class<FlowJob> 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<Element> listenersElements = DomUtils.getChildElementsByTagName(element, "listeners");
|
||||
if (listenersElements.size() == 1) {
|
||||
Element listenersElement = listenersElements.get(0);
|
||||
@@ -101,7 +102,7 @@ public class JobParser extends AbstractSingleBeanDefinitionParser {
|
||||
List<Element> listenerElements = (List<Element>) 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 <job/>.", element);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Element> 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<Element> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user