BATCH-1744, BATCH-1739: fix inheritance problems with retry and skip exceptions, revert skip-limit and retry-limit late binding

This commit is contained in:
Dave Syer
2011-05-04 12:02:44 +01:00
parent 422974800d
commit 8efa4f4189
6 changed files with 59 additions and 78 deletions

View File

@@ -19,9 +19,7 @@ import java.util.List;
import org.springframework.batch.core.listener.StepListenerMetaData;
import org.springframework.batch.core.step.item.ForceRollbackForWriteSkipException;
import org.springframework.batch.core.step.skip.LimitCheckingItemSkipPolicy;
import org.springframework.batch.repeat.policy.SimpleCompletionPolicy;
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
@@ -122,70 +120,32 @@ public class ChunkElementParser {
String skipLimit = element.getAttribute("skip-limit");
ManagedMap skippableExceptions = handleExceptionElement(element, parserContext, "skippable-exception-classes");
boolean hasSkipPolicy = false;
if (StringUtils.hasText(skipLimit)) {
if (skipLimit.startsWith("#")) {
if (skippableExceptions == null) {
parserContext.getReaderContext().error(
"The <chunk/> element must have skippable-exceptions if a skip-limit is specified.", element);
}
// It's a late binding expression, so we need step scope...
BeanDefinitionBuilder skipPolicy = BeanDefinitionBuilder
.genericBeanDefinition(LimitCheckingItemSkipPolicy.class);
skipPolicy.setScope("step");
skipPolicy.addPropertyValue("skippableExceptionMap", skippableExceptions);
skipPolicy.addPropertyValue("skipLimit", skipLimit);
propertyValues.addPropertyValue("skipPolicy", skipPolicy.getBeanDefinition());
hasSkipPolicy = true;
}
else {
if (skippableExceptions == null) {
skippableExceptions = new ManagedMap();
skippableExceptions.setMergeEnabled(true);
}
propertyValues.addPropertyValue("skipLimit", skipLimit);
if (skippableExceptions == null) {
skippableExceptions = new ManagedMap();
skippableExceptions.setMergeEnabled(true);
}
propertyValues.addPropertyValue("skipLimit", skipLimit);
}
if (!hasSkipPolicy) {
// Even if there is no retryLimit, we can still accept exception
// classes for an abstract parent bean definition
propertyValues.addPropertyValue("skippableExceptionClasses", skippableExceptions);
}
// Even if there is no retryLimit, we can still accept exception
// classes for an abstract parent bean definition
propertyValues.addPropertyValue("skippableExceptionClasses", skippableExceptions);
handleItemHandler("skip-policy", "skipPolicy", null, false, element, parserContext, propertyValues,
underspecified);
String retryLimit = element.getAttribute("retry-limit");
ManagedMap retryableExceptions = handleExceptionElement(element, parserContext, "retryable-exception-classes");
boolean hasRetryPolicy = false;
if (StringUtils.hasText(retryLimit)) {
if (retryLimit.startsWith("#")) {
if (retryableExceptions == null) {
parserContext.getReaderContext().error(
"The <chunk/> element must have retryable-exceptions if a retry-limit is specified.", element);
}
// It's a late binding expression, so we need step scope...
BeanDefinitionBuilder retryPolicy = BeanDefinitionBuilder
.genericBeanDefinition(SimpleRetryPolicy.class);
retryPolicy.setScope("step");
retryPolicy.addPropertyValue("maxAttempts", retryLimit);
retryPolicy.addPropertyValue("retryableExceptions", retryableExceptions);
propertyValues.addPropertyValue("retryPolicy", retryPolicy.getBeanDefinition());
hasRetryPolicy = true;
}
else {
if (retryableExceptions == null) {
retryableExceptions = new ManagedMap();
retryableExceptions.setMergeEnabled(true);
}
propertyValues.addPropertyValue("retryLimit", retryLimit);
if (retryableExceptions == null) {
retryableExceptions = new ManagedMap();
retryableExceptions.setMergeEnabled(true);
}
propertyValues.addPropertyValue("retryLimit", retryLimit);
}
if (!hasRetryPolicy) {
// Even if there is no retryLimit, we can still accept exception
// classes for an abstract parent bean definition
propertyValues.addPropertyValue("retryableExceptionClasses", retryableExceptions);
}
// Even if there is no retryLimit, we can still accept exception
// classes for an abstract parent bean definition
propertyValues.addPropertyValue("retryableExceptionClasses", retryableExceptions);
handleItemHandler("retry-policy", "retryPolicy", null, false, element, parserContext, propertyValues,
underspecified);

View File

@@ -18,7 +18,6 @@ package org.springframework.batch.core.configuration.xml;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.step.item.FaultTolerantChunkProcessor;
@@ -40,7 +39,7 @@ public class ParentStepFactoryBeanParserTests {
assertNotNull("Step not parsed", step);
Object tasklet = ReflectionTestUtils.getField(step, "tasklet");
Object chunkProcessor = ReflectionTestUtils.getField(tasklet, "chunkProcessor");
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?,?>);
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?, ?>);
}
@Test
@@ -51,7 +50,7 @@ public class ParentStepFactoryBeanParserTests {
assertNotNull("Step not parsed", step);
Object tasklet = ReflectionTestUtils.getField(step, "tasklet");
Object chunkProcessor = ReflectionTestUtils.getField(tasklet, "chunkProcessor");
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?,?>);
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?, ?>);
}
@Test
@@ -62,11 +61,11 @@ public class ParentStepFactoryBeanParserTests {
assertNotNull("Step not parsed", step);
Object tasklet = ReflectionTestUtils.getField(step, "tasklet");
Object chunkProcessor = ReflectionTestUtils.getField(tasklet, "chunkProcessor");
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?,?>);
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?, ?>);
}
// BATCH-1396
@Test
@Ignore // Fix this BATCH-1739
public void testRetryableLateBindingAttributes() throws Exception {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/ParentRetryableLateBindingStepFactoryBeanParserTests-context.xml");
@@ -74,11 +73,11 @@ public class ParentStepFactoryBeanParserTests {
assertNotNull("Step not parsed", step);
Object tasklet = ReflectionTestUtils.getField(step, "tasklet");
Object chunkProcessor = ReflectionTestUtils.getField(tasklet, "chunkProcessor");
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?,?>);
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?, ?>);
}
// BATCH-1396
@Test
@Ignore // Fix this BATCH-1739
public void testSkippableLateBindingAttributes() throws Exception {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/ParentSkippableLateBindingStepFactoryBeanParserTests-context.xml");
@@ -86,7 +85,7 @@ public class ParentStepFactoryBeanParserTests {
assertNotNull("Step not parsed", step);
Object tasklet = ReflectionTestUtils.getField(step, "tasklet");
Object chunkProcessor = ReflectionTestUtils.getField(tasklet, "chunkProcessor");
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?,?>);
assertTrue("Wrong processor type", chunkProcessor instanceof FaultTolerantChunkProcessor<?, ?>);
}
}

View File

@@ -14,14 +14,19 @@
</step>
<step id="s2">
<tasklet>
<chunk reader="reader" writer="writer" processor="processor" commit-interval="1"
retry-limit="#{jobParameters['retry.interval']}">
<retryable-exception-classes>
<include class="java.lang.Exception" />
</retryable-exception-classes>
</chunk>
<chunk reader="reader" writer="writer" processor="processor" commit-interval="1" retry-policy="retryPolicy"/>
</tasklet>
</step>
</job>
<bean id="retryPolicy" class="org.springframework.batch.retry.policy.SimpleRetryPolicy" xmlns="http://www.springframework.org/schema/beans"
scope="step">
<property name="maxAttempts" value="#{jobParameters['retry.interval']}" />
<property name="retryableExceptions">
<map key-type="java.lang.Class">
<entry key="java.lang.Exception" value="true" />
</map>
</property>
</bean>
</beans:beans>

View File

@@ -8,11 +8,7 @@
<step id="stepParent" abstract="true" xmlns="http://www.springframework.org/schema/batch">
<tasklet>
<chunk>
<retryable-exception-classes>
<include class="java.lang.Exception" />
</retryable-exception-classes>
</chunk>
<chunk/>
</tasklet>
</step>
@@ -20,9 +16,19 @@
<step id="s1" parent="stepParent">
<tasklet>
<chunk reader="reader" writer="writer" processor="processor" commit-interval="1"
retry-limit="#{jobParameters['retry.interval']}"/>
retry-policy="retryPolicy"/>
</tasklet>
</step>
</job>
<bean id="retryPolicy" class="org.springframework.batch.retry.policy.SimpleRetryPolicy" xmlns="http://www.springframework.org/schema/beans"
scope="step">
<property name="maxAttempts" value="#{jobParameters['retry.interval']}" />
<property name="retryableExceptions">
<map key-type="java.lang.Class">
<entry key="java.lang.Exception" value="true" />
</map>
</property>
</bean>
</beans:beans>

View File

@@ -20,9 +20,19 @@
<step id="s1" parent="stepParent">
<tasklet>
<chunk reader="reader" writer="writer" processor="processor" commit-interval="1"
skip-limit="#{jobParameters['skip.limit']}"/>
skip-policy="skipPolicy"/>
</tasklet>
</step>
</job>
<bean id="skipPolicy" class="org.springframework.batch.core.step.skip.LimitCheckingItemSkipPolicy" xmlns="http://www.springframework.org/schema/beans"
scope="step">
<property name="skipLimit" value="#{jobParameters['skip.limit']}" />
<property name="skippableExceptionMap">
<map key-type="java.lang.Class">
<entry key="java.lang.Exception" value="true" />
</map>
</property>
</bean>
</beans:beans>