diff --git a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBean.java b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBean.java index 3437067e4..782bf6460 100755 --- a/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBean.java +++ b/spring-batch-core/src/main/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBean.java @@ -77,12 +77,6 @@ public class FaultTolerantStepFactoryBean extends SimpleStepFactoryBean> retryableExceptionClasses = new HashSet>(); - { - fatalExceptionClasses.add(Error.class); - skippableExceptionClasses.add(Exception.class); - retryableExceptionClasses.add(Exception.class); - } - private int cacheCapacity = 0; private int retryLimit = 0; diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRetryTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRetryTests.java index 27ebdf349..50c76f9f0 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRetryTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRetryTests.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.List; @@ -63,7 +64,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { protected final Log logger = LogFactory.getLog(getClass()); - private FaultTolerantStepFactoryBean factory = new FaultTolerantStepFactoryBean(); + private FaultTolerantStepFactoryBean factory; private List recovered = new ArrayList(); @@ -88,11 +89,6 @@ public class FaultTolerantStepFactoryBeanRetryTests { } }; - /* - * (non-Javadoc) - * - * @see junit.framework.TestCase#setUp() - */ @Before public void setUp() throws Exception { @@ -100,6 +96,7 @@ public class FaultTolerantStepFactoryBeanRetryTests { MapJobExecutionDao.clear(); MapStepExecutionDao.clear(); + factory = new FaultTolerantStepFactoryBean(); factory.setBeanName("step"); factory.setItemReader(new ListItemReader(new ArrayList())); @@ -113,6 +110,11 @@ public class FaultTolerantStepFactoryBeanRetryTests { }); factory.setCommitInterval(1); // trivial by default + @SuppressWarnings("unchecked") + Collection> skippableExceptions = Arrays + .> asList(Exception.class); + factory.setSkippableExceptionClasses(skippableExceptions); + JobParameters jobParameters = new JobParametersBuilder().addString("statefulTest", "make_this_unique") .toJobParameters(); jobExecution = repository.createJobExecution("job", jobParameters); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRollbackTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRollbackTests.java index 2592c5b4f..52c54c28b 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRollbackTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanRollbackTests.java @@ -42,7 +42,7 @@ public class FaultTolerantStepFactoryBeanRollbackTests { protected final Log logger = LogFactory.getLog(getClass()); - private FaultTolerantStepFactoryBean factory = new FaultTolerantStepFactoryBean(); + private FaultTolerantStepFactoryBean factory; private static Collection NO_FAILURES = Collections.emptyList(); @@ -60,12 +60,19 @@ public class FaultTolerantStepFactoryBeanRollbackTests { @Before public void setUp() throws Exception { + factory = new FaultTolerantStepFactoryBean(); + factory.setBeanName("stepName"); factory.setTransactionManager(new ResourcelessTransactionManager()); factory.setCommitInterval(2); factory.setItemReader(reader); factory.setItemWriter(writer); factory.setSkipLimit(2); + + @SuppressWarnings("unchecked") + Collection> skippableExceptions = Arrays + .> asList(Exception.class); + factory.setSkippableExceptionClasses(skippableExceptions); MapJobRepositoryFactoryBean.clear(); MapJobRepositoryFactoryBean repositoryFactory = new MapJobRepositoryFactoryBean(); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanTests.java index 4d55e874c..5cdc73f02 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/item/FaultTolerantStepFactoryBeanTests.java @@ -50,11 +50,7 @@ public class FaultTolerantStepFactoryBeanTests { protected final Log logger = LogFactory.getLog(getClass()); - private FaultTolerantStepFactoryBean factory = new FaultTolerantStepFactoryBean(); - - @SuppressWarnings("unchecked") - private Collection> skippableExceptions = Arrays.> asList( - SkippableException.class, SkippableRuntimeException.class); + private FaultTolerantStepFactoryBean factory; private SkipReaderStub reader = new SkipReaderStub(); @@ -78,14 +74,20 @@ public class FaultTolerantStepFactoryBeanTests { @Before public void setUp() throws Exception { + factory = new FaultTolerantStepFactoryBean(); + factory.setBeanName("stepName"); factory.setTransactionManager(new ResourcelessTransactionManager()); factory.setCommitInterval(2); factory.setItemReader(reader); factory.setItemWriter(writer); - factory.setSkippableExceptionClasses(skippableExceptions); factory.setSkipLimit(2); + @SuppressWarnings("unchecked") + Collection> skippableExceptions = Arrays.> asList( + SkippableException.class, SkippableRuntimeException.class); + factory.setSkippableExceptionClasses(skippableExceptions); + MapJobRepositoryFactoryBean.clear(); MapJobRepositoryFactoryBean repositoryFactory = new MapJobRepositoryFactoryBean(); repositoryFactory.setTransactionManager(new ResourcelessTransactionManager()); diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicyTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicyTests.java index 28095a867..c4b7dbf63 100644 --- a/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicyTests.java +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/skip/LimitCheckingItemSkipPolicyTests.java @@ -25,19 +25,20 @@ import java.util.List; import org.junit.Before; import org.junit.Test; -import org.springframework.batch.core.step.skip.LimitCheckingItemSkipPolicy; -import org.springframework.batch.core.step.skip.SkipLimitExceededException; +import org.springframework.batch.item.ItemWriterException; +import org.springframework.batch.item.WriteFailedException; +import org.springframework.batch.item.WriterNotOpenException; import org.springframework.batch.item.file.FlatFileParseException; /** * @author Lucas Ward * @author Dave Syer - * + * */ public class LimitCheckingItemSkipPolicyTests { private LimitCheckingItemSkipPolicy failurePolicy; - + @Before public void setUp() throws Exception { List> skippableExceptions = new ArrayList>(); @@ -45,26 +46,100 @@ public class LimitCheckingItemSkipPolicyTests { List> fatalExceptions = new ArrayList>(); failurePolicy = new LimitCheckingItemSkipPolicy(1, skippableExceptions, fatalExceptions); } - + @Test - public void testLimitExceed(){ - try{ + public void testLimitExceed() { + try { failurePolicy.shouldSkip(new FlatFileParseException("", ""), 2); fail(); + } catch (SkipLimitExceededException ex) { + // expected } - catch(SkipLimitExceededException ex){ - //expected - } - } - - @Test - public void testNonSkippableException(){ - assertFalse(failurePolicy.shouldSkip(new FileNotFoundException(), 2)); - } - - @Test - public void testSkip(){ - assertTrue(failurePolicy.shouldSkip(new FlatFileParseException("",""), 0)); } + @Test + public void testNonSkippableException() { + assertFalse(failurePolicy.shouldSkip(new FileNotFoundException(), 2)); + } + + @Test + public void testSkip() { + assertTrue(failurePolicy.shouldSkip(new FlatFileParseException("", ""), 0)); + } + + private LimitCheckingItemSkipPolicy getSkippableSubsetFailurePolicy() { + List> skippableExceptions = new ArrayList>(); + skippableExceptions.add(WriteFailedException.class); + List> fatalExceptions = new ArrayList>(); + fatalExceptions.add(ItemWriterException.class); + return new LimitCheckingItemSkipPolicy(1, skippableExceptions, fatalExceptions); + } + + /** + * condition: skippable < fatal; exception is unclassified + * + * expected: false; default classification + */ + @Test + public void testSkippableSubset_unclassified() { + assertFalse(getSkippableSubsetFailurePolicy().shouldSkip(new RuntimeException(), 0)); + } + + /** + * condition: skippable < fatal; exception is skippable + * + * expected: false; fatal overrides skippable + */ + @Test + public void testSkippableSubset_skippable() { + assertFalse(getSkippableSubsetFailurePolicy().shouldSkip(new WriteFailedException(""), 0)); + } + + /** + * condition: skippable < fatal; exception is fatal + * + * expected: false + */ + @Test + public void testSkippableSubset_fatal() { + assertFalse(getSkippableSubsetFailurePolicy().shouldSkip(new WriterNotOpenException(""), 0)); + } + + private LimitCheckingItemSkipPolicy getFatalSubsetFailurePolicy() { + List> skippableExceptions = new ArrayList>(); + skippableExceptions.add(ItemWriterException.class); + List> fatalExceptions = new ArrayList>(); + fatalExceptions.add(WriteFailedException.class); + return new LimitCheckingItemSkipPolicy(1, skippableExceptions, fatalExceptions); + } + + /** + * condition: fatal < skippable; exception is unclassified + * + * expected: false; default classification + */ + @Test + public void testFatalSubset_unclassified() { + assertFalse(getFatalSubsetFailurePolicy().shouldSkip(new RuntimeException(), 0)); + } + + /** + * condition: fatal < skippable; exception is skippable + * + * expected: true + */ + @Test + public void testFatalSubset_skippable() { + assertTrue(getFatalSubsetFailurePolicy().shouldSkip(new WriterNotOpenException(""), 0)); + } + + /** + * condition: fatal < skippable; exception is fatal + * + * expected: false + */ + @Test + public void testFatalSubset_fatal() { + assertFalse(getFatalSubsetFailurePolicy().shouldSkip(new WriteFailedException(""), 0)); + } } diff --git a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeWriter.java b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeWriter.java index da99dfa88..6f19dda94 100644 --- a/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeWriter.java +++ b/spring-batch-samples/src/main/java/org/springframework/batch/sample/domain/trade/internal/TradeWriter.java @@ -27,6 +27,7 @@ import org.springframework.batch.item.ExecutionContext; import org.springframework.batch.item.ItemStreamException; import org.springframework.batch.item.ItemStreamSupport; import org.springframework.batch.item.ItemWriter; +import org.springframework.batch.item.WriteFailedException; import org.springframework.batch.sample.domain.trade.Trade; import org.springframework.batch.sample.domain.trade.TradeDao; import org.springframework.util.Assert; @@ -58,7 +59,7 @@ public class TradeWriter extends ItemStreamSupport implements ItemWriter Assert.notNull(trade.getPrice()); // There must be a price to total if (this.failingCustomers.contains(trade.getCustomer())) { - throw new RuntimeException("Something unexpected happened!"); + throw new WriteFailedException("Something unexpected happened!"); } } diff --git a/spring-batch-samples/src/main/resources/jobs/hibernateJob.xml b/spring-batch-samples/src/main/resources/jobs/hibernateJob.xml index 7776e0b8b..9d83fa65a 100644 --- a/spring-batch-samples/src/main/resources/jobs/hibernateJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/hibernateJob.xml @@ -17,7 +17,11 @@ processor="creditIncreaseProcessor" writer="hibernateCreditWriter" skip-limit="5" - commit-interval="3"/> + commit-interval="3"> + + java.lang.RuntimeException + + diff --git a/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml b/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml index 291249174..41a15b08a 100644 --- a/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/skipSampleJob.xml @@ -17,6 +17,10 @@ + + org.springframework.batch.item.file.FlatFileParseException + org.springframework.batch.item.WriteFailedException + @@ -46,7 +50,7 @@ - java.lang.RuntimeException + org.springframework.batch.item.validator.ValidationException @@ -59,7 +63,7 @@ - org.springframework.batch.item.validator.ValidationException + java.lang.RuntimeException