diff --git a/spring-batch-core/pom.xml b/spring-batch-core/pom.xml
index cd9ed54c7..4c3269365 100644
--- a/spring-batch-core/pom.xml
+++ b/spring-batch-core/pom.xml
@@ -18,6 +18,11 @@
spring-batch-infrastructure
${project.version}
+
+ javax.batch
+ javax.batch-api
+ 1.0-b29
+
org.hsqldb
hsqldb
@@ -38,10 +43,6 @@
true
test
-
-
-
-
junit
junit
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java
index aaf15b2dc..ad0331476 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/EnableBatchProcessing.java
@@ -21,6 +21,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import javax.sql.DataSource;
+
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.configuration.support.ApplicationContextFactory;
import org.springframework.batch.core.configuration.support.AutomaticJobRegistrar;
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java
index 9f91af2f1..0d6d3827c 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/AbstractFlowParser.java
@@ -211,7 +211,7 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar
* @param reachableElementMap
* @param accumulator a collection of reachable element names
*/
- private void findAllReachableElements(String startElement, Map> reachableElementMap,
+ protected void findAllReachableElements(String startElement, Map> reachableElementMap,
Set accumulator) {
Set reachableIds = reachableElementMap.get(startElement);
accumulator.add(startElement);
@@ -233,7 +233,7 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
- protected static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef,
+ public static Collection getNextElements(ParserContext parserContext, BeanDefinition stateDef,
Element element) {
return getNextElements(parserContext, null, stateDef, element);
}
@@ -248,7 +248,7 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar
* {@link org.springframework.batch.core.job.flow.support.StateTransition}
* references
*/
- protected static Collection getNextElements(ParserContext parserContext, String stepId,
+ public static Collection getNextElements(ParserContext parserContext, String stepId,
BeanDefinition stateDef, Element element) {
Collection list = new ArrayList();
@@ -283,7 +283,7 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar
else if (hasNextAttribute) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> may not contain a '" + NEXT_ATTR
- + "' attribute and a transition element", element);
+ + "' attribute and a transition element", element);
}
return list;
@@ -390,7 +390,7 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar
* @return the BatchStatus corresponding to the transition name
*/
private static FlowExecutionStatus getBatchStatusFromEndTransitionName(String elementName) {
- elementName = stripNamespace(elementName);
+ elementName = stripNamespace(elementName);
if (STOP_ELE.equals(elementName)) {
return FlowExecutionStatus.STOPPED;
}
@@ -405,17 +405,17 @@ public abstract class AbstractFlowParser extends AbstractSingleBeanDefinitionPar
}
}
- /**
- * Strip the namespace from the element name if it exists.
- */
- private static String stripNamespace(String elementName){
- if(elementName.startsWith("batch:")){
- return elementName.substring(6);
- }
- else{
- return elementName;
- }
- }
+ /**
+ * Strip the namespace from the element name if it exists.
+ */
+ private static String stripNamespace(String elementName){
+ if(elementName.startsWith("batch:")){
+ return elementName.substring(6);
+ }
+ else{
+ return elementName;
+ }
+ }
/**
* @param parserContext the parser context
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java
index f9b2ef44b..fa05bba2a 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ChunkElementParser.java
@@ -15,14 +15,14 @@
*/
package org.springframework.batch.core.configuration.xml;
+import java.util.List;
+
import org.springframework.batch.core.listener.StepListenerMetaData;
-import org.springframework.batch.core.step.item.ForceRollbackForWriteSkipException;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
-import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -30,12 +30,11 @@ import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
-import java.util.List;
-
/**
* Internal parser for the <chunk/> element inside a step.
*
@@ -108,18 +107,18 @@ public class ChunkElementParser {
if (propertyValues.contains("commitInterval")) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> element must contain either '" + COMMIT_INTERVAL_ATTR
- + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "', but not both.", element);
+ + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "', but not both.", element);
}
else {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> element must contain either '" + COMMIT_INTERVAL_ATTR
- + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "'.", element);
+ + "' " + "or '" + CHUNK_COMPLETION_POLICY_ATTR + "'.", element);
}
}
String skipLimit = element.getAttribute("skip-limit");
- ManagedMap skippableExceptions = handleExceptionElement(element, parserContext, "skippable-exception-classes");
+ ManagedMap skippableExceptions = new ExceptionElementParser().parse(element, parserContext, "skippable-exception-classes");
if (StringUtils.hasText(skipLimit)) {
if (skippableExceptions == null) {
skippableExceptions = new ManagedMap();
@@ -128,6 +127,12 @@ public class ChunkElementParser {
propertyValues.addPropertyValue("skipLimit", skipLimit);
}
if (skippableExceptions != null) {
+ List exceptionClassElements = DomUtils.getChildElementsByTagName(element, "skippable-exception-classes");
+
+ if(!CollectionUtils.isEmpty(exceptionClassElements)) {
+ skippableExceptions.setMergeEnabled(exceptionClassElements.get(0).hasAttribute(MERGE_ATTR)
+ && Boolean.valueOf(exceptionClassElements.get(0).getAttribute(MERGE_ATTR)));
+ }
// Even if there is no retryLimit, we can still accept exception
// classes for an abstract parent bean definition
propertyValues.addPropertyValue("skippableExceptionClasses", skippableExceptions);
@@ -137,7 +142,7 @@ public class ChunkElementParser {
underspecified);
String retryLimit = element.getAttribute("retry-limit");
- ManagedMap retryableExceptions = handleExceptionElement(element, parserContext, "retryable-exception-classes");
+ ManagedMap retryableExceptions = new ExceptionElementParser().parse(element, parserContext, "retryable-exception-classes");
if (StringUtils.hasText(retryLimit)) {
if (retryableExceptions == null) {
retryableExceptions = new ManagedMap();
@@ -146,6 +151,12 @@ public class ChunkElementParser {
propertyValues.addPropertyValue("retryLimit", retryLimit);
}
if (retryableExceptions != null) {
+ List exceptionClassElements = DomUtils.getChildElementsByTagName(element, "retryable-exception-classes");
+
+ if(!CollectionUtils.isEmpty(exceptionClassElements)) {
+ retryableExceptions.setMergeEnabled(exceptionClassElements.get(0).hasAttribute(MERGE_ATTR)
+ && Boolean.valueOf(exceptionClassElements.get(0).getAttribute(MERGE_ATTR)));
+ }
// Even if there is no retryLimit, we can still accept exception
// classes for an abstract parent bean definition
propertyValues.addPropertyValue("retryableExceptionClasses", retryableExceptions);
@@ -189,7 +200,7 @@ public class ChunkElementParser {
if (StringUtils.hasText(refName)) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> element may not have both a '" + handlerName
- + "' attribute and a <" + handlerName + "/> element.", element);
+ + "' attribute and a <" + handlerName + "/> element.", element);
}
handleItemHandlerElement(enclosing, propertyName, adapterClassName, propertyValues, children.get(0), parserContext);
}
@@ -204,7 +215,7 @@ public class ChunkElementParser {
else if (required && !underspecified) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> element has neither a '" + handlerName
- + "' attribute nor a <" + handlerName + "/> element.", element);
+ + "' attribute nor a <" + handlerName + "/> element.", element);
}
}
@@ -220,7 +231,7 @@ public class ChunkElementParser {
if (beanElements.size() + refElements.size() != 1) {
parserContext.getReaderContext().error(
"The <" + element.getNodeName() + "/> must have exactly one of either a <" + BEAN_ELE
- + "/> element or a <" + REF_ELE + "/> element.", element);
+ + "/> element or a <" + REF_ELE + "/> element.", element);
}
else if (beanElements.size() == 1) {
Element beanElement = beanElements.get(0);
@@ -313,35 +324,35 @@ public class ChunkElementParser {
propertyValues.addPropertyValue("streams", streamBeans);
}
}
-
- @SuppressWarnings("unchecked")
- private ManagedMap handleExceptionElement(Element element, ParserContext parserContext, String exceptionListName) {
- List children = DomUtils.getChildElementsByTagName(element, exceptionListName);
- if (children.size() == 1) {
- ManagedMap map = new ManagedMap();
- Element exceptionClassesElement = children.get(0);
- map.setMergeEnabled(exceptionClassesElement.hasAttribute(MERGE_ATTR)
- && Boolean.valueOf(exceptionClassesElement.getAttribute(MERGE_ATTR)));
- addExceptionClasses("include", true, exceptionClassesElement, map, parserContext);
- addExceptionClasses("exclude", false, exceptionClassesElement, map, parserContext);
- map.put(ForceRollbackForWriteSkipException.class, true);
- return map;
- }
- else if (children.size() > 1) {
- parserContext.getReaderContext().error(
- "The <" + exceptionListName + "/> element may not appear more than once in a single <"
- + element.getNodeName() + "/>.", element);
- }
- return null;
- }
-
- @SuppressWarnings("unchecked")
- private void addExceptionClasses(String elementName, boolean include, Element exceptionClassesElement,
- ManagedMap map, ParserContext parserContext) {
- for (Element child : (List) DomUtils.getChildElementsByTagName(exceptionClassesElement, elementName)) {
- String className = child.getAttribute("class");
- map.put(new TypedStringValue(className, Class.class), include);
- }
- }
-
+ //
+ // @SuppressWarnings("unchecked")
+ // private ManagedMap handleExceptionElement(Element element, ParserContext parserContext, String exceptionListName) {
+ // List children = DomUtils.getChildElementsByTagName(element, exceptionListName);
+ // if (children.size() == 1) {
+ // ManagedMap map = new ManagedMap();
+ // Element exceptionClassesElement = children.get(0);
+ // map.setMergeEnabled(exceptionClassesElement.hasAttribute(MERGE_ATTR)
+ // && Boolean.valueOf(exceptionClassesElement.getAttribute(MERGE_ATTR)));
+ // addExceptionClasses("include", true, exceptionClassesElement, map, parserContext);
+ // addExceptionClasses("exclude", false, exceptionClassesElement, map, parserContext);
+ // map.put(ForceRollbackForWriteSkipException.class, true);
+ // return map;
+ // }
+ // else if (children.size() > 1) {
+ // parserContext.getReaderContext().error(
+ // "The <" + exceptionListName + "/> element may not appear more than once in a single <"
+ // + element.getNodeName() + "/>.", element);
+ // }
+ // return null;
+ // }
+ //
+ // @SuppressWarnings("unchecked")
+ // private void addExceptionClasses(String elementName, boolean include, Element exceptionClassesElement,
+ // ManagedMap map, ParserContext parserContext) {
+ // for (Element child : (List) DomUtils.getChildElementsByTagName(exceptionClassesElement, elementName)) {
+ // String className = child.getAttribute("class");
+ // map.put(new TypedStringValue(className, Class.class), include);
+ // }
+ // }
+ //
}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java
index 426b038ba..4963a5da1 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/CoreNamespaceUtils.java
@@ -47,7 +47,7 @@ public class CoreNamespaceUtils {
private static final String CORE_NAMESPACE_POST_PROCESSOR_CLASS_NAME = "org.springframework.batch.core.configuration.xml.CoreNamespacePostProcessor";
- protected static void autoregisterBeansForNamespace(ParserContext parserContext, Object source) {
+ public static void autoregisterBeansForNamespace(ParserContext parserContext, Object source) {
checkForStepScope(parserContext, source);
addRangePropertyEditor(parserContext);
addCoreNamespacePostProcessor(parserContext);
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java
new file mode 100644
index 000000000..a5bf3501b
--- /dev/null
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/ExceptionElementParser.java
@@ -0,0 +1,41 @@
+package org.springframework.batch.core.configuration.xml;
+
+import java.util.List;
+
+import org.springframework.batch.core.step.item.ForceRollbackForWriteSkipException;
+import org.springframework.beans.factory.config.TypedStringValue;
+import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.xml.DomUtils;
+import org.w3c.dom.Element;
+
+public class ExceptionElementParser {
+
+ @SuppressWarnings("unchecked")
+ public ManagedMap parse(Element element, ParserContext parserContext, String exceptionListName) {
+ List children = DomUtils.getChildElementsByTagName(element, exceptionListName);
+ if (children.size() == 1) {
+ ManagedMap map = new ManagedMap();
+ Element exceptionClassesElement = children.get(0);
+ addExceptionClasses("include", true, exceptionClassesElement, map, parserContext);
+ addExceptionClasses("exclude", false, exceptionClassesElement, map, parserContext);
+ map.put(ForceRollbackForWriteSkipException.class, true);
+ return map;
+ }
+ else if (children.size() > 1) {
+ parserContext.getReaderContext().error(
+ "The <" + exceptionListName + "/> element may not appear more than once in a single <"
+ + element.getNodeName() + "/>.", element);
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void addExceptionClasses(String elementName, boolean include, Element exceptionClassesElement,
+ ManagedMap map, ParserContext parserContext) {
+ for (Element child : DomUtils.getChildElementsByTagName(exceptionClassesElement, elementName)) {
+ String className = child.getAttribute("class");
+ map.put(new TypedStringValue(className, Class.class), include);
+ }
+ }
+}
diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java
index 202281f63..45abbadc6 100644
--- a/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java
+++ b/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/xml/JobParserJobFactoryBean.java
@@ -35,7 +35,7 @@ import org.springframework.util.StringUtils;
* @author Dave Syer
* @since 2.0.1
*/
-class JobParserJobFactoryBean implements SmartFactoryBean {
+public class JobParserJobFactoryBean implements SmartFactoryBean {
private String name;
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 5209dc22b..cd3c12477 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
@@ -84,14 +84,13 @@ public class SplitParser {
stateBuilder.addPropertyValue("taskExecutor", taskExecutorRef);
}
- @SuppressWarnings("unchecked")
List flowElements = DomUtils.getChildElementsByTagName(element, "flow");
if (flowElements.size() < 2) {
parserContext.getReaderContext().error("A must contain at least two 'flow' elements.", element);
}
- @SuppressWarnings("unchecked")
+ @SuppressWarnings({"rawtypes", "unchecked"})
Collection