BATCH-1396: added step scope to retry and fixed bugs

This commit is contained in:
Dave Syer
2011-03-21 09:35:20 +00:00
parent aeadf8b02e
commit 58ad6bd542
12 changed files with 239 additions and 57 deletions

View File

@@ -29,6 +29,7 @@ import org.junit.Test;
import org.springframework.batch.classify.SubclassClassifier;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.step.item.SimpleChunkProcessor;
import org.springframework.batch.core.step.skip.SkipPolicy;
import org.springframework.batch.core.step.tasklet.TaskletStep;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.support.CompositeItemStream;
@@ -37,11 +38,13 @@ import org.springframework.batch.retry.listener.RetryListenerSupport;
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
import org.springframework.beans.PropertyAccessorUtils;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.CannotAcquireLockException;
import org.springframework.dao.CannotSerializeTransactionException;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.dao.DeadlockLoserDataAccessException;
import org.springframework.dao.PessimisticLockingFailureException;
import org.springframework.test.util.ReflectionTestUtils;
@@ -68,11 +71,32 @@ public class ChunkElementParserTests {
@Test
public void testCommitIntervalLateBinding() throws Exception {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/ChunkElementCommitIntervalParserTests-context.xml");
"org/springframework/batch/core/configuration/xml/ChunkElementLateBindingParserTests-context.xml");
Step step = (Step) context.getBean("s1", Step.class);
assertNotNull("Step not parsed", step);
}
@Test
public void testSkipAndRetryAttributes() throws Exception {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/ChunkElementSkipAndRetryAttributeParserTests-context.xml");
Step step = (Step) context.getBean("s1", Step.class);
assertNotNull("Step not parsed", step);
}
@Test
public void testIllegalSkipAndRetryAttributes() throws Exception {
try {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/ChunkElementIllegalSkipAndRetryAttributeParserTests-context.xml");
Step step = (Step) context.getBean("s1", Step.class);
assertNotNull("Step not parsed", step);
fail("Expected BeanDefinitionParsingException");
} catch (BeanDefinitionParsingException e) {
// expected
}
}
@Test
public void testRetryPolicyAttribute() throws Exception {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
@@ -98,19 +122,18 @@ public class ChunkElementParserTests {
public void testSkipPolicyAttribute() throws Exception {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/ChunkElementSkipPolicyParserTests-context.xml");
Map<Class<? extends Throwable>, Boolean> skippable = getSkippableExceptionClasses("s1", context);
assertEquals(2, skippable.size());
containsClassified(skippable, NullPointerException.class, true);
containsClassified(skippable, ArithmeticException.class, true);
SkipPolicy policy = getSkipPolicy("s1", context);
assertTrue(policy.shouldSkip(new NullPointerException(), 0));
assertTrue(policy.shouldSkip(new ArithmeticException(), 0));
}
@Test
public void testSkipPolicyElement() throws Exception {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(
"org/springframework/batch/core/configuration/xml/ChunkElementSkipPolicyParserTests-context.xml");
Map<Class<? extends Throwable>, Boolean> skippable = getSkippableExceptionClasses("s2", context);
assertEquals(1, skippable.size());
containsClassified(skippable, ArithmeticException.class, true);
SkipPolicy policy = getSkipPolicy("s2", context);
assertFalse(policy.shouldSkip(new NullPointerException(), 0));
assertTrue(policy.shouldSkip(new ArithmeticException(), 0));
}
@Test
@@ -164,6 +187,7 @@ public class ChunkElementParserTests {
@Test
public void testInheritSkippable() throws Exception {
Map<Class<? extends Throwable>, Boolean> skippable = getSkippableExceptionClasses("s1", getContext());
System.err.println(skippable);
assertEquals(5, skippable.size());
containsClassified(skippable, NullPointerException.class, true);
containsClassified(skippable, ArithmeticException.class, true);
@@ -175,9 +199,9 @@ public class ChunkElementParserTests {
public void testInheritSkippableWithNoMerge() throws Exception {
Map<Class<? extends Throwable>, Boolean> skippable = getSkippableExceptionClasses("s2", getContext());
assertEquals(3, skippable.size());
containsClassified(skippable, NullPointerException.class, true);
containsClassified(skippable, IllegalArgumentException.class, true);
assertFalse(skippable.containsKey(ArithmeticException.class));
containsClassified(skippable, CannotAcquireLockException.class, false);
containsClassified(skippable, ConcurrencyFailureException.class, false);
assertFalse(skippable.containsKey(DeadlockLoserDataAccessException.class));
}
@@ -244,6 +268,11 @@ public class ChunkElementParserTests {
"skippableExceptionClassifier");
}
private SkipPolicy getSkipPolicy(String stepName,
ApplicationContext ctx) throws Exception {
return (SkipPolicy) getNestedPathInStep(stepName, ctx, "tasklet.chunkProvider.skipPolicy");
}
private Map<Class<? extends Throwable>, Boolean> getRetryableExceptionClasses(String stepName,
ApplicationContext ctx) throws Exception {
return getNestedExceptionMap(stepName, ctx,

View File

@@ -40,6 +40,7 @@ import org.springframework.batch.core.repository.support.SimpleJobRepository;
import org.springframework.batch.core.step.AbstractStep;
import org.springframework.batch.core.step.item.FatalSkippableException;
import org.springframework.batch.core.step.item.FatalRuntimeException;
import org.springframework.batch.core.step.item.ForceRollbackForWriteSkipException;
import org.springframework.batch.core.step.item.SkippableException;
import org.springframework.batch.core.step.item.SkippableRuntimeException;
import org.springframework.batch.core.step.tasklet.Tasklet;
@@ -428,9 +429,11 @@ public class StepParserTests {
skippable.put(SkippableException.class, true);
skippable.put(FatalRuntimeException.class, false);
skippable.put(FatalSkippableException.class, false);
skippable.put(ForceRollbackForWriteSkipException.class, true);
Map<Class<? extends Throwable>, Boolean> retryable = new HashMap<Class<? extends Throwable>, Boolean>();
retryable.put(DeadlockLoserDataAccessException.class, true);
retryable.put(FatalSkippableException.class, true);
retryable.put(ForceRollbackForWriteSkipException.class, true);
List<Class<? extends ItemStream>> streams = Arrays.asList(CompositeItemStream.class, TestReader.class);
List<Class<? extends RetryListener>> retryListeners = Arrays.asList(RetryListenerSupport.class,
DummyRetryListener.class);
@@ -464,8 +467,10 @@ public class StepParserTests {
Map<Class<? extends Throwable>, Boolean> skippable = new HashMap<Class<? extends Throwable>, Boolean>();
skippable.put(SkippableException.class, true);
skippable.put(FatalSkippableException.class, false);
skippable.put(ForceRollbackForWriteSkipException.class, true);
Map<Class<? extends Throwable>, Boolean> retryable = new HashMap<Class<? extends Throwable>, Boolean>();
retryable.put(FatalSkippableException.class, true);
retryable.put(ForceRollbackForWriteSkipException.class, true);
List<Class<CompositeItemStream>> streams = Arrays.asList(CompositeItemStream.class);
List<Class<DummyRetryListener>> retryListeners = Arrays.asList(DummyRetryListener.class);
List<Class<CompositeStepExecutionListener>> stepListeners = Arrays.asList(CompositeStepExecutionListener.class);
@@ -495,8 +500,8 @@ public class StepParserTests {
StepParserStepFactoryBean<?, ?> fb = (StepParserStepFactoryBean<?, ?>) ctx
.getBean("&stepWithListsOverrideWithEmpty");
assertEquals(0, getExceptionMap(fb, "skippableExceptionClasses").size());
assertEquals(0, getExceptionMap(fb, "retryableExceptionClasses").size());
assertEquals(1, getExceptionMap(fb, "skippableExceptionClasses").size());
assertEquals(1, getExceptionMap(fb, "retryableExceptionClasses").size());
assertEquals(0, ((ItemStream[]) ReflectionTestUtils.getField(fb, "streams")).length);
assertEquals(0, ((RetryListener[]) ReflectionTestUtils.getField(fb, "retryListeners")).length);
assertEquals(0, ((StepListener[]) ReflectionTestUtils.getField(fb, "listeners")).length);