RESOLVED - issue BATCH-486: Users must choose between skip and retry

Tweak the retry policy to account for fatal exceptions as well (they should not be retryable).
This commit is contained in:
dsyer
2008-03-28 12:14:45 +00:00
parent bfa98e3bdb
commit 0ada1fcaaa
4 changed files with 47 additions and 5 deletions

View File

@@ -68,6 +68,14 @@ public class SkipLimitStepFactoryBean extends SimpleStepFactoryBean {
this.fatalExceptionClasses = fatalExceptionClasses;
}
/**
* Protected getter for the fatal exceptions.
* @return the fatalExceptionClasses
*/
protected Class[] getFatalExceptionClasses() {
return fatalExceptionClasses;
}
/**
* Public setter for the {@link ItemKeyGenerator}. This is used to identify
* failed items so they can be skipped if encountered again, generally in

View File

@@ -119,6 +119,7 @@ public class StatefulRetryStepFactoryBean extends SkipLimitStepFactoryBean {
SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(retryLimit);
if (retryableExceptionClasses != null) {
retryPolicy.setRetryableExceptionClasses(retryableExceptionClasses);
retryPolicy.setFatalExceptionClasses(getFatalExceptionClasses());
}
// Co-ordinate the retry policy with the exception handler:

View File

@@ -48,7 +48,9 @@ public class SimpleRetryPolicy extends AbstractStatelessRetryPolicy {
private volatile int maxAttempts;
private BinaryExceptionClassifier classifier = new BinaryExceptionClassifier();
private BinaryExceptionClassifier retryableClassifier = new BinaryExceptionClassifier();
private BinaryExceptionClassifier fatalClassifier = new BinaryExceptionClassifier();
/**
* Create a {@link SimpleRetryPolicy} with the default number of retry
@@ -67,6 +69,7 @@ public class SimpleRetryPolicy extends AbstractStatelessRetryPolicy {
public SimpleRetryPolicy(int maxAttempts) {
super();
setRetryableExceptionClasses(new Class[] { Exception.class });
setFatalExceptionClasses(new Class[] { Error.class });
this.maxAttempts = maxAttempts;
}
@@ -97,12 +100,23 @@ public class SimpleRetryPolicy extends AbstractStatelessRetryPolicy {
/**
* Set the retryable exceptions. Any exception on the list, or subclasses
* thereof, will be retryable. Others will be rethrown without retry.
* thereof, will be retryable. Others will be re-thrown without retry.
*
* @param retryableExceptionClasses defaults to {@link Exception}.
*/
public final void setRetryableExceptionClasses(Class[] retryableExceptionClasses) {
classifier.setExceptionClasses(retryableExceptionClasses);
retryableClassifier.setExceptionClasses(retryableExceptionClasses);
}
/**
* Set the fatal exceptions. Any exception on the list, or subclasses
* thereof, will be re-thrown without retry. This list takes precedence over
* the retryable list.
*
* @param retryableExceptionClasses defaults to {@link Exception}.
*/
public final void setFatalExceptionClasses(Class[] fatalExceptionClasses) {
fatalClassifier.setExceptionClasses(fatalExceptionClasses);
}
/**
@@ -126,7 +140,8 @@ public class SimpleRetryPolicy extends AbstractStatelessRetryPolicy {
* Get a status object that can be used to track the current operation
* according to this policy. Has to be aware of the latest exception and the
* number of attempts.
* @see org.springframework.batch.retry.RetryPolicy#open(org.springframework.batch.retry.RetryCallback, RetryContext)
* @see org.springframework.batch.retry.RetryPolicy#open(org.springframework.batch.retry.RetryCallback,
* RetryContext)
*/
public RetryContext open(RetryCallback callback, RetryContext parent) {
return new SimpleRetryContext(parent);
@@ -146,6 +161,6 @@ public class SimpleRetryPolicy extends AbstractStatelessRetryPolicy {
* retryable.
*/
private boolean retryForException(Throwable ex) {
return !classifier.isDefault(ex);
return fatalClassifier.isDefault(ex) && !retryableClassifier.isDefault(ex);
}
}

View File

@@ -82,6 +82,24 @@ public class SimpleRetryPolicyTests extends TestCase {
assertEquals("foo", context.getLastThrowable().getMessage());
}
public void testDefaultFatal() throws Exception {
SimpleRetryPolicy policy = new SimpleRetryPolicy();
RetryContext context = policy.open(null, null);
assertNotNull(context);
policy.registerThrowable(context, new Error("foo"));
assertFalse(policy.canRetry(context));
}
public void testFatalOverridesRetryable() throws Exception {
SimpleRetryPolicy policy = new SimpleRetryPolicy();
policy.setFatalExceptionClasses(new Class[] {Exception.class});
policy.setRetryableExceptionClasses(new Class[] {RuntimeException.class});
RetryContext context = policy.open(null, null);
assertNotNull(context);
policy.registerThrowable(context, new RuntimeException("foo"));
assertFalse(policy.canRetry(context));
}
public void testParent() throws Exception {
SimpleRetryPolicy policy = new SimpleRetryPolicy();
RetryContext context = policy.open(null, null);