diff --git a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleStepFactoryBean.java b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleStepFactoryBean.java index be3952347..dd5b8ee88 100644 --- a/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleStepFactoryBean.java +++ b/spring-batch-execution/src/main/java/org/springframework/batch/execution/step/support/SimpleStepFactoryBean.java @@ -16,17 +16,20 @@ package org.springframework.batch.execution.step.support; import org.springframework.batch.execution.step.ItemOrientedStep; +import org.springframework.batch.repeat.exception.handler.SimpleLimitExceptionHandler; import org.springframework.batch.repeat.policy.SimpleCompletionPolicy; import org.springframework.batch.repeat.support.RepeatTemplate; /** * @author Dave Syer - * + * */ public class SimpleStepFactoryBean extends AbstractStepFactoryBean { private int commitInterval = 0; + private boolean alwaysSkip = false; + /** * Set the commit interval. * @@ -36,19 +39,45 @@ public class SimpleStepFactoryBean extends AbstractStepFactoryBean { this.commitInterval = commitInterval; } + /** + * Public setter for the flag that determines skip policy. If this flag is + * true then an exception in chunk processing will cause the item to be + * skipped and no exceptions propagated. If it is false then all exceptions + * will be propagated from the chunk and cause the step to abort. + * + * @param alwaysSkip the value to set. Default is false. + */ + public void setAlwaysSkip(boolean alwaysSkip) { + this.alwaysSkip = alwaysSkip; + } + /** * @param step * */ protected void applyConfiguration(ItemOrientedStep step) { - + super.applyConfiguration(step); - + if (commitInterval > 0) { RepeatTemplate chunkOperations = new RepeatTemplate(); chunkOperations.setCompletionPolicy(new SimpleCompletionPolicy(commitInterval)); step.setChunkOperations(chunkOperations); } + if (alwaysSkip) { + // If we always skip (not the default) then we are prepared to + // absorb all exceptions at the step level because the failed items + // will never re-appear after a rollback. + step.setItemSkipPolicy(new AlwaysSkipItemSkipPolicy()); + RepeatTemplate stepOperations = new RepeatTemplate(); + stepOperations.setExceptionHandler(new SimpleLimitExceptionHandler(Integer.MAX_VALUE)); + step.setStepOperations(stepOperations); + } + else { + // This is the default in ItemOrientedStep anyway... + step.setItemSkipPolicy(new NeverSkipItemSkipPolicy()); + } + } } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/handler/SimpleLimitExceptionHandler.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/handler/SimpleLimitExceptionHandler.java index 4e9221487..d5c9e6f0d 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/handler/SimpleLimitExceptionHandler.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/repeat/exception/handler/SimpleLimitExceptionHandler.java @@ -45,14 +45,22 @@ public class SimpleLimitExceptionHandler implements ExceptionHandler { * Set this flag to true if you want to count exceptions for the whole * (outer) loop in a typical container. * - * @param useParent - * true if the parent context should be used to store the - * counters. + * @param useParent true if the parent context should be used to store the + * counters. */ public void setUseParent(boolean useParent) { delegate.setUseParent(useParent); } + /** + * Convenience constructor for the {@link SimpleLimitExceptionHandler} to + * set the limit. + */ + public SimpleLimitExceptionHandler(int limit) { + this(); + setLimit(limit); + } + /** * Default constructor for the {@link SimpleLimitExceptionHandler}. */ @@ -76,10 +84,9 @@ public class SimpleLimitExceptionHandler implements ExceptionHandler { * @see #setLimit(int) * * @see org.springframework.batch.repeat.exception.handler.ExceptionHandler#handleException(org.springframework.batch.repeat.RepeatContext, - * Throwable) + * Throwable) */ - public void handleException(RepeatContext context, Throwable throwable) - throws RuntimeException { + public void handleException(RepeatContext context, Throwable throwable) throws RuntimeException { delegate.handleException(context, throwable); } diff --git a/spring-batch-samples/src/main/resources/jobs/hibernateJob.xml b/spring-batch-samples/src/main/resources/jobs/hibernateJob.xml index 3250f0581..33690c6f3 100644 --- a/spring-batch-samples/src/main/resources/jobs/hibernateJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/hibernateJob.xml @@ -15,31 +15,17 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + diff --git a/spring-batch-samples/src/main/resources/jobs/rollbackJob.xml b/spring-batch-samples/src/main/resources/jobs/rollbackJob.xml index 759643060..d0636a1e9 100644 --- a/spring-batch-samples/src/main/resources/jobs/rollbackJob.xml +++ b/spring-batch-samples/src/main/resources/jobs/rollbackJob.xml @@ -14,15 +14,10 @@ - - - - - - + + + +