BATCH-1080: refactored the tasklet element parsing and removed the id attribute from <tasklet>

This commit is contained in:
trisberg
2009-02-16 01:52:21 +00:00
parent e40aab476a
commit 2e95ee22c9
4 changed files with 454 additions and 387 deletions

View File

@@ -19,7 +19,6 @@ import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
@@ -46,6 +45,8 @@ import org.w3c.dom.NamedNodeMap;
* @since 2.0
*/
public abstract class AbstractStepParser {
TaskletElementParser taskletElementParser = new TaskletElementParser();
/**
* @param stepElement
@@ -86,113 +87,20 @@ public abstract class AbstractStepParser {
*/
protected AbstractBeanDefinition parseTaskletElement(Element stepElement, Element element, ParserContext parserContext, String jobRepositoryRef) {
RootBeanDefinition bd;
boolean isFaultTolerant = false;
String skipLimit = element.getAttribute("skip-limit");
if (!isFaultTolerant) {
isFaultTolerant = checkIntValueForFaultToleranceNeeded(skipLimit);
}
String retryLimit = element.getAttribute("retry-limit");
if (!isFaultTolerant) {
isFaultTolerant = checkIntValueForFaultToleranceNeeded(retryLimit);
}
String cacheCapacity = element.getAttribute("cache-capacity");
if (!isFaultTolerant) {
isFaultTolerant = checkIntValueForFaultToleranceNeeded(cacheCapacity);
}
String isReaderTransactionalQueue = element.getAttribute("is-reader-transactional-queue");
if (!isFaultTolerant && StringUtils.hasText(isReaderTransactionalQueue)) {
if ("true".equals(isReaderTransactionalQueue)) {
isFaultTolerant = true;
}
}
checkExceptionElementForFaultToleranceNeeded(element, "skippable-exception-classes");
checkExceptionElementForFaultToleranceNeeded(element, "retryable-exception-classes");
checkExceptionElementForFaultToleranceNeeded(element, "fatal-exception-classes");
if (isFaultTolerant) {
bd = new RootBeanDefinition("org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean", null, null);
}
else {
bd = new RootBeanDefinition("org.springframework.batch.core.step.item.SimpleStepFactoryBean", null, null);
}
AbstractBeanDefinition bd = taskletElementParser.parseTaskletElement(element, parserContext);
// now, set the properties on the new bean
checkStepAttributes(stepElement, bd);
String readerBeanId = element.getAttribute("reader");
if (StringUtils.hasText(readerBeanId)) {
RuntimeBeanReference readerRef = new RuntimeBeanReference(readerBeanId);
bd.getPropertyValues().addPropertyValue("itemReader", readerRef);
}
String processorBeanId = element.getAttribute("processor");
if (StringUtils.hasText(processorBeanId)) {
RuntimeBeanReference processorRef = new RuntimeBeanReference(processorBeanId);
bd.getPropertyValues().addPropertyValue("itemProcessor", processorRef);
}
String writerBeanId = element.getAttribute("writer");
if (StringUtils.hasText(writerBeanId)) {
RuntimeBeanReference writerRef = new RuntimeBeanReference(writerBeanId);
bd.getPropertyValues().addPropertyValue("itemWriter", writerRef);
}
String taskExecutorBeanId = element.getAttribute("task-executor");
if (StringUtils.hasText(taskExecutorBeanId)) {
RuntimeBeanReference taskExecutorRef = new RuntimeBeanReference(taskExecutorBeanId);
bd.getPropertyValues().addPropertyValue("taskExecutor", taskExecutorRef);
}
RuntimeBeanReference jobRepositoryBeanRef = new RuntimeBeanReference(jobRepositoryRef);
bd.getPropertyValues().addPropertyValue("jobRepository", jobRepositoryBeanRef);
String transactionManagerRef = stepElement.getAttribute("transaction-manager");
RuntimeBeanReference tx = new RuntimeBeanReference(transactionManagerRef);
bd.getPropertyValues().addPropertyValue("transactionManager", tx);
String commitInterval = element.getAttribute("commit-interval");
if (StringUtils.hasText(commitInterval)) {
bd.getPropertyValues().addPropertyValue("commitInterval", commitInterval);
}
if (StringUtils.hasText(skipLimit)) {
bd.getPropertyValues().addPropertyValue("skipLimit", skipLimit);
}
if (StringUtils.hasText(retryLimit)) {
bd.getPropertyValues().addPropertyValue("retryLimit", retryLimit);
}
if (StringUtils.hasText(cacheCapacity)) {
bd.getPropertyValues().addPropertyValue("cacheCapacity", cacheCapacity);
}
String transactionAttribute = element.getAttribute("transaction-attribute");
if (StringUtils.hasText(transactionAttribute)) {
bd.getPropertyValues().addPropertyValue("transactionAttribute", transactionAttribute);
}
if (StringUtils.hasText(isReaderTransactionalQueue)) {
if (isFaultTolerant) {
bd.getPropertyValues().addPropertyValue("isReaderTransactionalQueue", isReaderTransactionalQueue);
}
}
handleExceptionElement(element, parserContext, bd, "skippable-exception-classes", "skippableExceptionClasses", isFaultTolerant);
handleExceptionElement(element, parserContext, bd, "retryable-exception-classes", "retryableExceptionClasses", isFaultTolerant);
handleExceptionElement(element, parserContext, bd, "fatal-exception-classes", "fatalExceptionClasses", isFaultTolerant);
handleListenersElement(stepElement, bd, parserContext, "listeners");
handleRetryListenersElement(element, bd, parserContext);
handleStreamsElement(element, bd, parserContext);
bd.setRole(BeanDefinition.ROLE_SUPPORT);
bd.setSource(parserContext.extractSource(stepElement));
@@ -201,7 +109,7 @@ public abstract class AbstractStepParser {
}
private void checkStepAttributes(Element stepElement, RootBeanDefinition bd) {
private void checkStepAttributes(Element stepElement, AbstractBeanDefinition bd) {
String startLimit = stepElement.getAttribute("start-limit");
if (StringUtils.hasText(startLimit)) {
bd.getPropertyValues().addPropertyValue("startLimit", startLimit);
@@ -212,44 +120,6 @@ public abstract class AbstractStepParser {
}
}
private boolean checkIntValueForFaultToleranceNeeded(String stringValue) {
if (StringUtils.hasText(stringValue)) {
int value = Integer.valueOf(stringValue);
if (value > 0) {
return true;
}
}
return false;
}
private boolean checkExceptionElementForFaultToleranceNeeded(Element element, String subElementName) {
String exceptions =
DomUtils.getChildElementValueByTagName(element, subElementName);
if (StringUtils.hasLength(exceptions)) {
return true;
}
return false;
}
private void handleExceptionElement(Element element, ParserContext parserContext, BeanDefinition bd,
String subElementName, String propertyName, boolean isFaultTolerant) {
String exceptions =
DomUtils.getChildElementValueByTagName(element, subElementName);
if (StringUtils.hasLength(exceptions)) {
if (isFaultTolerant) {
String[] exceptionArray = StringUtils.tokenizeToStringArray(
StringUtils.delete(exceptions, ","), "\n");
if (exceptionArray.length > 0) {
bd.getPropertyValues().addPropertyValue(propertyName, exceptionArray);
}
}
else {
parserContext.getReaderContext().error(subElementName + " can only be specified for fault-tolerant " +
"configurations providing skip-limit, retry-limit or cache-capacity", element);
}
}
}
@SuppressWarnings("unchecked")
private void handleListenersElement(Element element, BeanDefinition bd, ParserContext parserContext, String property) {
Element listenersElement =
@@ -268,54 +138,6 @@ public abstract class AbstractStepParser {
}
}
@SuppressWarnings("unchecked")
private void handleRetryListenersElement(Element element, BeanDefinition bd, ParserContext parserContext) {
Element listenersElement =
DomUtils.getChildElementByTagName(element, "retry-listeners");
if (listenersElement != null) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(listenersElement.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
List<Object> retryListenerBeans = new ArrayList<Object>();
handleRetryListenerElements(parserContext, listenersElement,
retryListenerBeans);
ManagedList arguments = new ManagedList();
arguments.addAll(retryListenerBeans);
bd.getPropertyValues().addPropertyValue("retryListeners", arguments);
parserContext.popAndRegisterContainingComponent();
}
}
@SuppressWarnings("unchecked")
private void handleRetryListenerElements(ParserContext parserContext,
Element element, List<Object> beans) {
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");
checkListenerElementAttributes(parserContext, element,
listenerElement, id, listenerRef, className);
if (StringUtils.hasText(listenerRef)) {
BeanReference bean = new RuntimeBeanReference(listenerRef);
beans.add(bean);
}
else if (StringUtils.hasText(className)) {
RootBeanDefinition beanDef = new RootBeanDefinition(className, null, null);
if (!StringUtils.hasText(id)) {
id = parserContext.getReaderContext().generateBeanName(beanDef);
}
beans.add(beanDef);
}
else {
parserContext.getReaderContext().error("Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element", element);
}
}
}
}
@SuppressWarnings("unchecked")
private void handleStepListenerElements(ParserContext parserContext,
Element element, List<Object> beans) {
@@ -397,30 +219,4 @@ public abstract class AbstractStepParser {
}
}
@SuppressWarnings("unchecked")
private void handleStreamsElement(Element element, BeanDefinition bd, ParserContext parserContext) {
Element streamsElement =
DomUtils.getChildElementByTagName(element, "streams");
if (streamsElement != null) {
List<BeanReference> streamBeans = new ArrayList<BeanReference>();
List<Element> streamElements =
DomUtils.getChildElementsByTagName(streamsElement, "stream");
if (streamElements != null) {
for (Element streamElement : streamElements) {
String streamRef = streamElement.getAttribute("ref");
if (StringUtils.hasText(streamRef)) {
BeanReference bean = new RuntimeBeanReference(streamRef);
streamBeans.add(bean);
}
else {
parserContext.getReaderContext().error("ref not specified for <" + streamElement.getTagName() + "> element", element);
}
}
}
ManagedList arguments = new ManagedList();
arguments.addAll(streamBeans);
bd.getPropertyValues().addPropertyValue("streams", arguments);
}
}
}

View File

@@ -24,12 +24,8 @@ import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Internal parser for the &lt;step/&gt; elements inside a job. A step element
* references a bean definition for a {@link org.springframework.batch.core.Step} and goes on to (optionally)
* list a set of transitions from that step to others with &lt;next on="pattern"
* to="stepName"/&gt;. Used by the {@link JobParser}.
*
* @see JobParser
* Internal parser for the &lt;step/&gt; elements for a job. A step element
* references a bean definition for a {@link org.springframework.batch.core.Step}.
*
* @author Dave Syer
* @author Thomas Risberg

View File

@@ -0,0 +1,279 @@
/*
* Copyright 2006-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.batch.core.configuration.xml;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
/**
* Internal parser for the &lt;tasklet/&gt; element either inside a job or as a standalone tasklet definition.
*
* @author Thomas Risberg
* @since 2.0
*/
public class TaskletElementParser {
/**
* @param element
* @param parserContext
*/
protected AbstractBeanDefinition parseTaskletElement(Element element, ParserContext parserContext) {
RootBeanDefinition bd;
boolean isFaultTolerant = false;
String skipLimit = element.getAttribute("skip-limit");
if (!isFaultTolerant) {
isFaultTolerant = checkIntValueForFaultToleranceNeeded(skipLimit);
}
String retryLimit = element.getAttribute("retry-limit");
if (!isFaultTolerant) {
isFaultTolerant = checkIntValueForFaultToleranceNeeded(retryLimit);
}
String cacheCapacity = element.getAttribute("cache-capacity");
if (!isFaultTolerant) {
isFaultTolerant = checkIntValueForFaultToleranceNeeded(cacheCapacity);
}
String isReaderTransactionalQueue = element.getAttribute("is-reader-transactional-queue");
if (!isFaultTolerant && StringUtils.hasText(isReaderTransactionalQueue)) {
if ("true".equals(isReaderTransactionalQueue)) {
isFaultTolerant = true;
}
}
checkExceptionElementForFaultToleranceNeeded(element, "skippable-exception-classes");
checkExceptionElementForFaultToleranceNeeded(element, "retryable-exception-classes");
checkExceptionElementForFaultToleranceNeeded(element, "fatal-exception-classes");
if (isFaultTolerant) {
bd = new RootBeanDefinition("org.springframework.batch.core.step.item.FaultTolerantStepFactoryBean", null, null);
}
else {
bd = new RootBeanDefinition("org.springframework.batch.core.step.item.SimpleStepFactoryBean", null, null);
}
String readerBeanId = element.getAttribute("reader");
if (StringUtils.hasText(readerBeanId)) {
RuntimeBeanReference readerRef = new RuntimeBeanReference(readerBeanId);
bd.getPropertyValues().addPropertyValue("itemReader", readerRef);
}
String processorBeanId = element.getAttribute("processor");
if (StringUtils.hasText(processorBeanId)) {
RuntimeBeanReference processorRef = new RuntimeBeanReference(processorBeanId);
bd.getPropertyValues().addPropertyValue("itemProcessor", processorRef);
}
String writerBeanId = element.getAttribute("writer");
if (StringUtils.hasText(writerBeanId)) {
RuntimeBeanReference writerRef = new RuntimeBeanReference(writerBeanId);
bd.getPropertyValues().addPropertyValue("itemWriter", writerRef);
}
String taskExecutorBeanId = element.getAttribute("task-executor");
if (StringUtils.hasText(taskExecutorBeanId)) {
RuntimeBeanReference taskExecutorRef = new RuntimeBeanReference(taskExecutorBeanId);
bd.getPropertyValues().addPropertyValue("taskExecutor", taskExecutorRef);
}
String commitInterval = element.getAttribute("commit-interval");
if (StringUtils.hasText(commitInterval)) {
bd.getPropertyValues().addPropertyValue("commitInterval", commitInterval);
}
if (StringUtils.hasText(skipLimit)) {
bd.getPropertyValues().addPropertyValue("skipLimit", skipLimit);
}
if (StringUtils.hasText(retryLimit)) {
bd.getPropertyValues().addPropertyValue("retryLimit", retryLimit);
}
if (StringUtils.hasText(cacheCapacity)) {
bd.getPropertyValues().addPropertyValue("cacheCapacity", cacheCapacity);
}
String transactionAttribute = element.getAttribute("transaction-attribute");
if (StringUtils.hasText(transactionAttribute)) {
bd.getPropertyValues().addPropertyValue("transactionAttribute", transactionAttribute);
}
if (StringUtils.hasText(isReaderTransactionalQueue)) {
if (isFaultTolerant) {
bd.getPropertyValues().addPropertyValue("isReaderTransactionalQueue", isReaderTransactionalQueue);
}
}
handleExceptionElement(element, parserContext, bd, "skippable-exception-classes", "skippableExceptionClasses", isFaultTolerant);
handleExceptionElement(element, parserContext, bd, "retryable-exception-classes", "retryableExceptionClasses", isFaultTolerant);
handleExceptionElement(element, parserContext, bd, "fatal-exception-classes", "fatalExceptionClasses", isFaultTolerant);
handleRetryListenersElement(element, bd, parserContext);
handleStreamsElement(element, bd, parserContext);
return bd;
}
private boolean checkIntValueForFaultToleranceNeeded(String stringValue) {
if (StringUtils.hasText(stringValue)) {
int value = Integer.valueOf(stringValue);
if (value > 0) {
return true;
}
}
return false;
}
private boolean checkExceptionElementForFaultToleranceNeeded(Element element, String subElementName) {
String exceptions =
DomUtils.getChildElementValueByTagName(element, subElementName);
if (StringUtils.hasLength(exceptions)) {
return true;
}
return false;
}
private void handleExceptionElement(Element element, ParserContext parserContext, BeanDefinition bd,
String subElementName, String propertyName, boolean isFaultTolerant) {
String exceptions =
DomUtils.getChildElementValueByTagName(element, subElementName);
if (StringUtils.hasLength(exceptions)) {
if (isFaultTolerant) {
String[] exceptionArray = StringUtils.tokenizeToStringArray(
StringUtils.delete(exceptions, ","), "\n");
if (exceptionArray.length > 0) {
bd.getPropertyValues().addPropertyValue(propertyName, exceptionArray);
}
}
else {
parserContext.getReaderContext().error(subElementName + " can only be specified for fault-tolerant " +
"configurations providing skip-limit, retry-limit or cache-capacity", element);
}
}
}
@SuppressWarnings("unchecked")
private void handleRetryListenersElement(Element element, BeanDefinition bd, ParserContext parserContext) {
Element listenersElement =
DomUtils.getChildElementByTagName(element, "retry-listeners");
if (listenersElement != null) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(listenersElement.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
List<Object> retryListenerBeans = new ArrayList<Object>();
handleRetryListenerElements(parserContext, listenersElement,
retryListenerBeans);
ManagedList arguments = new ManagedList();
arguments.addAll(retryListenerBeans);
bd.getPropertyValues().addPropertyValue("retryListeners", arguments);
parserContext.popAndRegisterContainingComponent();
}
}
@SuppressWarnings("unchecked")
private void handleRetryListenerElements(ParserContext parserContext,
Element element, List<Object> beans) {
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");
checkListenerElementAttributes(parserContext, element,
listenerElement, id, listenerRef, className);
if (StringUtils.hasText(listenerRef)) {
BeanReference bean = new RuntimeBeanReference(listenerRef);
beans.add(bean);
}
else if (StringUtils.hasText(className)) {
RootBeanDefinition beanDef = new RootBeanDefinition(className, null, null);
if (!StringUtils.hasText(id)) {
id = parserContext.getReaderContext().generateBeanName(beanDef);
}
beans.add(beanDef);
}
else {
parserContext.getReaderContext().error("Neither 'ref' or 'class' specified for <" + listenerElement.getTagName() + "> element", element);
}
}
}
}
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)) {
NamedNodeMap attributeNodes = listenerElement.getAttributes();
StringBuilder attributes = new StringBuilder();
for (int i = 0; i < attributeNodes.getLength(); i++) {
if (i > 0) {
attributes.append(" ");
}
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 <" +
listenerElement.getTagName() + "> element specified with attributes: " + attributes, element);
}
}
@SuppressWarnings("unchecked")
private void handleStreamsElement(Element element, BeanDefinition bd, ParserContext parserContext) {
Element streamsElement =
DomUtils.getChildElementByTagName(element, "streams");
if (streamsElement != null) {
List<BeanReference> streamBeans = new ArrayList<BeanReference>();
List<Element> streamElements =
DomUtils.getChildElementsByTagName(streamsElement, "stream");
if (streamElements != null) {
for (Element streamElement : streamElements) {
String streamRef = streamElement.getAttribute("ref");
if (StringUtils.hasText(streamRef)) {
BeanReference bean = new RuntimeBeanReference(streamRef);
streamBeans.add(bean);
}
else {
parserContext.getReaderContext().error("ref not specified for <" + streamElement.getTagName() + "> element", element);
}
}
}
ManagedList arguments = new ManagedList();
arguments.addAll(streamBeans);
bd.getPropertyValues().addPropertyValue("streams", arguments);
}
}
}

View File

@@ -258,7 +258,7 @@
<xsd:sequence>
<xsd:element name="tasklet" type="taskletType" minOccurs="0" maxOccurs="1"/>
<xsd:group ref="stepListeners"/>
<xsd:group ref="transitions"/>
<xsd:group ref="transitions"/>
</xsd:sequence>
<xsd:attributeGroup ref="transactionManagerAttribute"/>
</xsd:extension>
@@ -266,177 +266,173 @@
</xsd:complexType>
<xsd:complexType name="taskletType">
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:all>
<xsd:element name="retry-listeners" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
List of all listeners for the step definition
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="listener" type="listenerType" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="streams" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
List of all streams to be included for the step definition
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="stream" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to an ItemStream bean definition
]]>
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref" />
<tool:expected-type type="org.springframework.batch.item.ItemStream" />
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="skippable-exception-classes" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The newline-separated, list of exception classes that are skippable
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="retryable-exception-classes" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The newline-separated, list of exception classes that are skippable
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="fatal-exception-classes" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The newline-separated, list of exception classes that are skippable
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:element>
</xsd:all>
<xsd:attribute name="commit-interval" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The number of items that will be processed before commit is called for the transaction.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reader" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name of the item reader that is to be used for the process.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref" />
<tool:expected-type type="org.springframework.batch.item.ItemReader" />
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="processor" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name of the item processor that is to be used for the process.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref" />
<tool:expected-type type="org.springframework.batch.item.ItemProcessor" />
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="writer" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name of the item writer that is to be used for the process.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref" />
<tool:expected-type type="org.springframework.batch.item.ItemWriter" />
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="skip-limit" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The maximum number of items that will be allowed to be skipped.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="retry-limit" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The maximum number of times the processing of an item will be retried.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cache-capacity" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The capacity of the cache in the retry policy.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="transaction-attribute" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The transaction attributes to be used for the transaction used during the execution
of the task within the step.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="is-reader-transactional-queue" type="xsd:string" default="false" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether the reader is a transactional queue. If it is then items read should not be cached
in the event of a rollback since they will be returned to the queue.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="task-executor" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation
source="java:org.springframework.core.task.TaskExecutor"><![CDATA[
The task executor responsible for executing the task..
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.core.task.TaskExecutor" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
<xsd:all>
<xsd:element name="retry-listeners" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
List of all listeners for the step definition
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="listener" type="listenerType" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="streams" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
List of all streams to be included for the step definition
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="stream" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="ref" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to an ItemStream bean definition
]]>
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref" />
<tool:expected-type type="org.springframework.batch.item.ItemStream" />
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="skippable-exception-classes" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The newline-separated, list of exception classes that are skippable
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="retryable-exception-classes" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The newline-separated, list of exception classes that are skippable
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:element>
<xsd:element name="fatal-exception-classes" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The newline-separated, list of exception classes that are skippable
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:restriction base="xsd:string"/>
</xsd:simpleType>
</xsd:element>
</xsd:all>
<xsd:attribute name="commit-interval" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The number of items that will be processed before commit is called for the transaction.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="reader" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name of the item reader that is to be used for the process.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref" />
<tool:expected-type type="org.springframework.batch.item.ItemReader" />
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="processor" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name of the item processor that is to be used for the process.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref" />
<tool:expected-type type="org.springframework.batch.item.ItemProcessor" />
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="writer" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
The bean name of the item writer that is to be used for the process.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref" />
<tool:expected-type type="org.springframework.batch.item.ItemWriter" />
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="skip-limit" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The maximum number of items that will be allowed to be skipped.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="retry-limit" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The maximum number of times the processing of an item will be retried.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="cache-capacity" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The capacity of the cache in the retry policy.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="transaction-attribute" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
The transaction attributes to be used for the transaction used during the execution
of the task within the step.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="is-reader-transactional-queue" type="xsd:string" default="false" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Whether the reader is a transactional queue. If it is then items read should not be cached
in the event of a rollback since they will be returned to the queue.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="task-executor" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation
source="java:org.springframework.core.task.TaskExecutor"><![CDATA[
The task executor responsible for executing the task..
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type
type="org.springframework.core.task.TaskExecutor" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="nextType">
@@ -684,7 +680,7 @@
<xsd:attribute name="tasklet" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation>
The tasklet is a reference to another bean definition that defines implements the Tasklet interface.
The tasklet is a reference to another bean definition that implements the Tasklet interface.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">