BATCH-1131:

*Move "transaction-attribute" attribute from <tasklet/> to <step/> as <transaction-attributes/>
BATCH-1152:
 *Allow comma and newline as delimiters in exception lists in namespace
This commit is contained in:
dhgarrette
2009-03-13 20:18:26 +00:00
parent 90a845edbc
commit e493bd5ceb
8 changed files with 99 additions and 43 deletions

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.batch.core.configuration.xml;
import java.util.Arrays;
import java.util.List;
import org.springframework.batch.core.step.tasklet.TaskletStep;
@@ -76,7 +77,7 @@ public abstract class AbstractStepParser {
setUpBeanDefinition(element, bd, parserContext, jobRepositoryRef);
}
return bd;
}
/**
@@ -84,8 +85,8 @@ public abstract class AbstractStepParser {
* @param taskletRef
* @param parserContext
*/
private AbstractBeanDefinition parseTaskletRef(Element stepElement, String taskletRef,
ParserContext parserContext, String jobRepositoryRef) {
private AbstractBeanDefinition parseTaskletRef(Element stepElement, String taskletRef, ParserContext parserContext,
String jobRepositoryRef) {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setBeanClass(TaskletStep.class);
@@ -99,6 +100,7 @@ public abstract class AbstractStepParser {
}
@SuppressWarnings("unchecked")
protected void setUpBeanDefinition(Element stepElement, AbstractBeanDefinition bd, ParserContext parserContext,
String jobRepositoryRef) {
checkStepAttributes(stepElement, bd);
@@ -110,6 +112,20 @@ public abstract class AbstractStepParser {
RuntimeBeanReference transactionManagerBeanRef = new RuntimeBeanReference(transactionManagerRef);
bd.getPropertyValues().addPropertyValue("transactionManager", transactionManagerBeanRef);
Element child = DomUtils.getChildElementByTagName(stepElement, "transaction-attributes");
if (child != null) {
String attributes = DomUtils.getTextValue(child);
if (StringUtils.hasLength(attributes)) {
String[] attributesArray = StringUtils.tokenizeToStringArray(attributes, ",\n");
if (attributesArray.length > 0) {
ManagedList managedList = new ManagedList();
managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute("merge")));
managedList.addAll(Arrays.asList(attributesArray));
bd.getPropertyValues().addPropertyValue("transactionAttributeList", managedList);
}
}
}
handleListenersElement(stepElement, bd, parserContext);
bd.setRole(BeanDefinition.ROLE_SUPPORT);

View File

@@ -146,11 +146,6 @@ public class TaskletElementParser {
propertyValues.addPropertyValue("cacheCapacity", cacheCapacity);
}
String transactionAttribute = element.getAttribute("transaction-attribute");
if (StringUtils.hasText(transactionAttribute)) {
propertyValues.addPropertyValue("transactionAttribute", transactionAttribute);
}
if (StringUtils.hasText(isReaderTransactionalQueue)) {
if (isFaultTolerant) {
propertyValues.addPropertyValue("isReaderTransactionalQueue", isReaderTransactionalQueue);
@@ -198,19 +193,21 @@ public class TaskletElementParser {
Element child = DomUtils.getChildElementByTagName(element, subElementName);
if (child != null) {
String exceptions = DomUtils.getTextValue(child);
if (StringUtils.hasLength(exceptions) && (isFaultTolerant || isAbstract)) {
String[] exceptionArray = StringUtils.tokenizeToStringArray(StringUtils.delete(exceptions, ","), "\n");
if (exceptionArray.length > 0) {
ManagedList managedList = new ManagedList();
managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute("merge")));
managedList.addAll(Arrays.asList(exceptionArray));
bd.getPropertyValues().addPropertyValue(propertyName, managedList);
if (StringUtils.hasLength(exceptions)) {
if (isFaultTolerant || isAbstract) {
String[] exceptionArray = StringUtils.tokenizeToStringArray(exceptions, ",\n");
if (exceptionArray.length > 0) {
ManagedList managedList = new ManagedList();
managedList.setMergeEnabled(Boolean.valueOf(child.getAttribute("merge")));
managedList.addAll(Arrays.asList(exceptionArray));
bd.getPropertyValues().addPropertyValue(propertyName, managedList);
}
}
else {
parserContext.getReaderContext().error(
subElementName + " can only be specified for fault-tolerant "
+ "configurations providing skip-limit, retry-limit or cache-capacity", element);
}
}
else {
parserContext.getReaderContext().error(
subElementName + " can only be specified for fault-tolerant "
+ "configurations providing skip-limit, retry-limit or cache-capacity", element);
}
}
}

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.batch.core.step.item;
import java.beans.PropertyEditor;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.core.ChunkListener;
@@ -45,7 +48,9 @@ import org.springframework.core.task.TaskExecutor;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttributeEditor;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Most common configuration options for simple steps should be found here. Use
@@ -269,6 +274,20 @@ public class SimpleStepFactoryBean<T, S> implements FactoryBean, BeanNameAware {
this.transactionManager = transactionManager;
}
/**
* Public setter for the {@link TransactionAttribute}.
*
* @param transactionAttributeList A list of all the transaction attributes
* to set
*/
public void setTransactionAttributeList(List<String> transactionAttributeList) {
String[] stringArray = transactionAttributeList.toArray(new String[0]);
String attributeString = StringUtils.arrayToCommaDelimitedString(stringArray);
PropertyEditor editor = new TransactionAttributeEditor();
editor.setAsText(attributeString);
this.setTransactionAttribute((TransactionAttribute) editor.getValue());
}
/**
* Public setter for the {@link TransactionAttribute}.
* @param transactionAttribute the {@link TransactionAttribute} to set

View File

@@ -181,8 +181,7 @@
<xsd:documentation>
Defines a stage in job processing backed by a
Step. The id attribute must be specified and
can
match the id of a bean definition
can match the id of a bean definition
for a Step. If it does not, then you must provide
a tasklet definition or a
reference to a Step defined elsewhere.
@@ -255,8 +254,7 @@
<xsd:annotation>
<xsd:documentation>
The decider is a reference to a JobExecutionDecider that can produce a status to base
the
next transition on.
the next transition on.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
@@ -295,6 +293,7 @@
<xsd:complexType name="stepType">
<xsd:sequence>
<xsd:element name="tasklet" type="taskletType" minOccurs="0" maxOccurs="1" />
<xsd:element name="transaction-attributes" type="transaction-attributesType" minOccurs="0" maxOccurs="1"/>
<xsd:group ref="stepListeners" />
</xsd:sequence>
<xsd:attributeGroup ref="transactionManagerAttribute" />
@@ -305,6 +304,7 @@
<xsd:extension base="nextType">
<xsd:sequence>
<xsd:element name="tasklet" type="taskletType" minOccurs="0" maxOccurs="1" />
<xsd:element name="transaction-attributes" type="transaction-attributesType" minOccurs="0" maxOccurs="1"/>
<xsd:group ref="stepListeners" />
<xsd:group ref="transitions" />
</xsd:sequence>
@@ -361,7 +361,8 @@
<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
List of exception classes that are skippable.
Separate each attribute with a comma or a newline.
]]>
</xsd:documentation>
</xsd:annotation>
@@ -376,7 +377,8 @@
<xsd:element name="retryable-exception-classes" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The newline-separated, list of exception classes that are retryable
List of exception classes that are retryable.
Separate each attribute with a newline or a comma.
]]>
</xsd:documentation>
</xsd:annotation>
@@ -391,7 +393,8 @@
<xsd:element name="fatal-exception-classes" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation><![CDATA[
The newline-separated, list of exception classes that are fatal
List of exception classes that are fatal.
Separate each attribute with a newline or a comma.
]]>
</xsd:documentation>
</xsd:annotation>
@@ -466,14 +469,6 @@
]]></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[
@@ -511,13 +506,28 @@
<xsd:attributeGroup ref="parentAttribute" />
</xsd:complexType>
<xsd:complexType name="transaction-attributesType">
<xsd:annotation>
<xsd:documentation><![CDATA[
The transaction attributes to be used for the transaction used
during the execution of the task within the step. Separate
each attribute with a comma or a newline.
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attributeGroup ref="mergeAttribute" />
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:complexType name="nextType">
<xsd:attribute name="next" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
A shortcut for specifying the next step to execute after this one, if there is only one choice. The next
attribute is a synonym for &lt;next on="*"/&gt; plus &lt;fail on="FAILED"/&gt; in a transition.
If this attribute is specified, then there should be no other transition with a nested &lt;next .../&gt;]]>
If this attribute is specified, then there should be no nested transition elements]]>
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>

View File

@@ -11,7 +11,6 @@
<tasklet reader="reader" processor="processor" writer="writer"
commit-interval="10" skip-limit="20"
retry-limit="3" cache-capacity="100"
transaction-attribute="PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_10,-org.springframework.dao.DataIntegrityViolationException"
is-reader-transactional-queue="true"
task-executor="taskExecutor">
<retry-listeners>
@@ -24,6 +23,10 @@
org.springframework.dao.DataIntegrityViolationException,
</skippable-exception-classes>
</tasklet>
<transaction-attributes>
PROPAGATION_REQUIRED, ISOLATION_DEFAULT, timeout_10,
-org.springframework.dao.DataIntegrityViolationException
</transaction-attributes>
<listeners>
<listener ref="listener"/>
</listeners>

View File

@@ -9,7 +9,6 @@
<tasklet reader="reader" processor="processor" writer="writer"
commit-interval="10" skip-limit="20"
retry-limit="3" cache-capacity="100"
transaction-attribute="PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_10,-org.springframework.dao.DataIntegrityViolationException"
is-reader-transactional-queue="true"
task-executor="taskExecutor">
<retry-listeners>
@@ -25,6 +24,10 @@
org.springframework.dao.DataIntegrityViolationException
</skippable-exception-classes>
</tasklet>
<transaction-attributes>
PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_10
-org.springframework.dao.DataIntegrityViolationException
</transaction-attributes>
<listeners>
<listener ref="listener"/>
</listeners>

View File

@@ -11,7 +11,6 @@
<tasklet reader="reader" processor="processor" writer="writer"
commit-interval="10" skip-limit="20"
retry-limit="3" cache-capacity="100"
transaction-attribute="PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_10,-org.springframework.dao.DataIntegrityViolationException"
is-reader-transactional-queue="true"
task-executor="taskExecutor">
<retry-listeners>
@@ -22,9 +21,15 @@
<stream ref="reader"/>
</streams>
<skippable-exception-classes>
org.springframework.dao.DataIntegrityViolationException,
org.springframework.dao.DataIntegrityViolationException
</skippable-exception-classes>
</tasklet>
<transaction-attributes>
PROPAGATION_REQUIRED
ISOLATION_DEFAULT
timeout_10
-org.springframework.dao.DataIntegrityViolationException
</transaction-attributes>
<listeners>
<listener class="org.springframework.batch.core.configuration.xml.TestListener"/>
<listener ref="listener"/>

View File

@@ -17,12 +17,15 @@
<tasklet reader="fileItemReader"
processor="validatingProcessor"
writer="tradeWriter"
commit-interval="1"
transaction-attribute="PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED">
commit-interval="1">
<streams>
<stream ref="fileItemReader"/>
</streams>
</tasklet>
</tasklet>
<transaction-attributes>
PROPAGATION_REQUIRED
ISOLATION_READ_COMMITTED
</transaction-attributes>
</step>
<step id="step2" next="step3">
<tasklet reader="tradeSqlItemReader" writer="customerWriter" commit-interval="1"/>