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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <next on="*"/> plus <fail on="FAILED"/> in a transition.
|
||||
If this attribute is specified, then there should be no other transition with a nested <next .../>]]>
|
||||
If this attribute is specified, then there should be no nested transition elements]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
Reference in New Issue
Block a user