RESOLVED - issue BATCH-973: Switch RetryPolicy back to Throwable instead of Exception as in 1.x

http://jira.springframework.org/browse/BATCH-973
This commit is contained in:
dsyer
2009-09-24 08:24:47 +00:00
parent ab5ece862a
commit 6ef8865ce2
18 changed files with 64 additions and 43 deletions

View File

@@ -123,7 +123,7 @@ public class BatchRetryTemplate implements RetryOperations {
}
@Override
protected void registerThrowable(RetryPolicy retryPolicy, RetryState state, RetryContext context, Exception e) {
protected void registerThrowable(RetryPolicy retryPolicy, RetryState state, RetryContext context, Throwable e) {
BatchRetryState batchState = (BatchRetryState) state;
BatchRetryContext batchContext = (BatchRetryContext) context;

View File

@@ -222,7 +222,7 @@ public class Chunk<W> implements Iterable<W> {
return next;
}
public void remove(Exception e) {
public void remove(Throwable e) {
remove();
skips.add(new SkipWrapper<W>(next, e));
}

View File

@@ -248,7 +248,7 @@ public class FaultTolerantChunkProcessor<I, O> extends SimpleChunkProcessor<I, O
RecoveryCallback<O> recoveryCallback = new RecoveryCallback<O>() {
public O recover(RetryContext context) throws Exception {
Exception e = context.getLastThrowable();
Throwable e = context.getLastThrowable();
if (itemProcessSkipPolicy.shouldSkip(e, contribution.getStepSkipCount())) {
contribution.incrementProcessSkipCount();
iterator.remove(e);
@@ -315,7 +315,7 @@ public class FaultTolerantChunkProcessor<I, O> extends SimpleChunkProcessor<I, O
public Object recover(RetryContext context) throws Exception {
Exception e = context.getLastThrowable();
Throwable e = context.getLastThrowable();
if (outputs.size() > 1 && !rollbackClassifier.classify(e)) {
throw new RetryException("Invalid retry state during write caused by "
+ "exception that does not classify for rollback: ", e);
@@ -387,12 +387,12 @@ public class FaultTolerantChunkProcessor<I, O> extends SimpleChunkProcessor<I, O
if (item == null) {
continue;
}
Exception e = wrapper.getException();
Throwable e = wrapper.getException();
callProcessSkipListener(item, e);
}
for (SkipWrapper<O> wrapper : outputs.getSkips()) {
Exception e = wrapper.getException();
Throwable e = wrapper.getException();
try {
getListener().onSkipInWrite(wrapper.getItem(), e);
}
@@ -414,7 +414,7 @@ public class FaultTolerantChunkProcessor<I, O> extends SimpleChunkProcessor<I, O
* @param item the item that is skipped
* @param e the cause of the skip
*/
private void callProcessSkipListener(I item, Exception e) {
private void callProcessSkipListener(I item, Throwable e) {
try {
getListener().onSkipInProcess(item, e);
}
@@ -442,7 +442,7 @@ public class FaultTolerantChunkProcessor<I, O> extends SimpleChunkProcessor<I, O
}
private void checkSkipPolicy(Chunk<I>.ChunkIterator inputIterator, Chunk<O>.ChunkIterator outputIterator,
Exception e, StepContribution contribution) {
Throwable e, StepContribution contribution) {
logger.debug("Checking skip policy after failed write");
if (itemWriteSkipPolicy.shouldSkip(e, contribution.getStepSkipCount())) {
contribution.incrementWriteSkipCount();

View File

@@ -24,7 +24,7 @@ package org.springframework.batch.core.step.item;
*/
public class SkipWrapper<T> {
final private Exception exception;
final private Throwable exception;
final private T item;
@@ -38,12 +38,12 @@ public class SkipWrapper<T> {
/**
* @param e
*/
public SkipWrapper(Exception e) {
public SkipWrapper(Throwable e) {
this(null, e);
}
public SkipWrapper(T item, Exception e) {
public SkipWrapper(T item, Throwable e) {
this.item = item;
this.exception = e;
}
@@ -52,7 +52,7 @@ public class SkipWrapper<T> {
* Public getter for the exception.
* @return the exception
*/
public Exception getException() {
public Throwable getException() {
return exception;
}

View File

@@ -99,10 +99,10 @@ public class FaultTolerantChunkProcessorTests {
}
/**
* An Error pops right back up (no skips, no retry)
* An Error can be retried or skipped but by default it is just propagated
* @throws Exception
*/
@Test(expected=AssertionError.class)
@Test
public void testWriteSkipOnError() throws Exception {
processor.setWriteSkipPolicy(new AlwaysSkipItemSkipPolicy());
processor.setItemWriter(new ItemWriter<String>() {

View File

@@ -64,6 +64,6 @@ public interface RetryContext extends AttributeAccessor {
* be null if this is the first attempt, but also if the enclosing policy
* decides not to provide it (e.g. because of concerns about memory usage).
*/
Exception getLastThrowable();
Throwable getLastThrowable();
}

View File

@@ -58,6 +58,6 @@ public interface RetryPolicy {
* @param context the current status object.
*
*/
void registerThrowable(RetryContext context, Exception throwable);
void registerThrowable(RetryContext context, Throwable throwable);
}

View File

@@ -55,6 +55,6 @@ public interface RetryState {
* @param exception the exception that caused a retry attempt to fail
* @return true if this exception should cause a rollback
*/
boolean rollbackFor(Exception exception);
boolean rollbackFor(Throwable exception);
}

View File

@@ -26,7 +26,7 @@ public class RetryContextSupport extends AttributeAccessorSupport implements Ret
private int count;
private Exception lastException;
private Throwable lastException;
private RetryContext parent;
@@ -51,7 +51,7 @@ public class RetryContextSupport extends AttributeAccessorSupport implements Ret
return count;
}
public Exception getLastThrowable() {
public Throwable getLastThrowable() {
return lastException;
}
@@ -69,7 +69,7 @@ public class RetryContextSupport extends AttributeAccessorSupport implements Ret
* @param throwable the exception that caused the current retry attempt to
* fail.
*/
public void registerThrowable(Exception throwable) {
public void registerThrowable(Throwable throwable) {
this.lastException = throwable;
if (throwable != null)
count++;

View File

@@ -107,7 +107,7 @@ public class CompositeRetryPolicy implements RetryPolicy {
*
* @see org.springframework.batch.retry.RetryPolicy#close(org.springframework.batch.retry.RetryContext)
*/
public void registerThrowable(RetryContext context, Exception throwable) {
public void registerThrowable(RetryContext context, Throwable throwable) {
RetryContext[] contexts = ((CompositeRetryContext) context).contexts;
RetryPolicy[] policies = ((CompositeRetryContext) context).policies;
for (int i = 0; i < contexts.length; i++) {

View File

@@ -99,9 +99,9 @@ public class ExceptionClassifierRetryPolicy implements RetryPolicy {
* Delegate to the policy currently activated in the context.
*
* @see org.springframework.batch.retry.RetryPolicy#registerThrowable(org.springframework.batch.retry.RetryContext,
* Exception)
* Throwable)
*/
public void registerThrowable(RetryContext context, Exception throwable) {
public void registerThrowable(RetryContext context, Throwable throwable) {
RetryPolicy policy = (RetryPolicy) context;
policy.registerThrowable(context, throwable);
((RetryContextSupport) context).registerThrowable(throwable);
@@ -144,7 +144,7 @@ public class ExceptionClassifierRetryPolicy implements RetryPolicy {
return this;
}
public void registerThrowable(RetryContext context, Exception throwable) {
public void registerThrowable(RetryContext context, Throwable throwable) {
policy = exceptionClassifier.classify(throwable);
Assert.notNull(policy, "Could not locate policy for exception=[" + throwable + "].");
this.context = getContext(policy, context.getParent());

View File

@@ -60,11 +60,11 @@ public class NeverRetryPolicy implements RetryPolicy {
}
/**
* Do nothing.
* Make the throwable available for downstream use through the context.
* @see org.springframework.batch.retry.RetryPolicy#registerThrowable(org.springframework.batch.retry.RetryContext,
* Exception)
* Throwable)
*/
public void registerThrowable(RetryContext context, Exception throwable) {
public void registerThrowable(RetryContext context, Throwable throwable) {
((NeverRetryContext) context).setFinished();
((RetryContextSupport) context).registerThrowable(throwable);
}

View File

@@ -57,7 +57,8 @@ public class SimpleRetryPolicy implements RetryPolicy {
* attempts.
*/
public SimpleRetryPolicy() {
this(DEFAULT_MAX_ATTEMPTS, Collections.<Class<? extends Throwable>, Boolean>singletonMap(Exception.class, true));
this(DEFAULT_MAX_ATTEMPTS, Collections
.<Class<? extends Throwable>, Boolean> singletonMap(Exception.class, true));
}
/**
@@ -105,10 +106,9 @@ public class SimpleRetryPolicy implements RetryPolicy {
/**
* Update the status with another attempted retry and the latest exception.
*
* @see org.springframework.batch.retry.RetryPolicy#registerThrowable(org.springframework.batch.retry.RetryContext,
* Exception)
* @see RetryPolicy#registerThrowable(RetryContext, Throwable)
*/
public void registerThrowable(RetryContext context, Exception throwable) {
public void registerThrowable(RetryContext context, Throwable throwable) {
SimpleRetryContext simpleContext = ((SimpleRetryContext) context);
simpleContext.registerThrowable(throwable);
}

View File

@@ -61,7 +61,7 @@ public class TimeoutRetryPolicy implements RetryPolicy {
return new TimeoutRetryContext(parent, timeout);
}
public void registerThrowable(RetryContext context, Exception throwable) {
public void registerThrowable(RetryContext context, Throwable throwable) {
((RetryContextSupport) context).registerThrowable(throwable);
// otherwise no-op - we only time out, otherwise retry everything...
}

View File

@@ -103,10 +103,10 @@ public class DefaultRetryState implements RetryState {
* (non-Javadoc)
*
* @see
* org.springframework.batch.retry.IRetryState#rollbackFor(java.lang.Exception
* org.springframework.batch.retry.RetryState#rollbackFor(java.lang.Throwable
* )
*/
public boolean rollbackFor(Exception exception) {
public boolean rollbackFor(Throwable exception) {
if (rollbackClassifier == null) {
return true;
}

View File

@@ -23,6 +23,7 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.repeat.RepeatException;
import org.springframework.batch.retry.ExhaustedRetryException;
import org.springframework.batch.retry.RecoveryCallback;
import org.springframework.batch.retry.RetryCallback;
@@ -236,7 +237,7 @@ public class RetryTemplate implements RetryOperations {
lastException = null;
return retryCallback.doWithRetry(context);
}
catch (Exception e) {
catch (Throwable e) {
lastException = e;
@@ -258,7 +259,7 @@ public class RetryTemplate implements RetryOperations {
logger.debug("Checking for rethrow: count=" + context.getRetryCount());
if (shouldRethrow(retryPolicy, context, state)) {
logger.debug("Rethrow in retry for policy: count=" + context.getRetryCount());
throw e;
throw wrapIfNecessary(e);
}
}
@@ -327,7 +328,7 @@ public class RetryTemplate implements RetryOperations {
* @param context
* @param e
*/
protected void registerThrowable(RetryPolicy retryPolicy, RetryState state, RetryContext context, Exception e) {
protected void registerThrowable(RetryPolicy retryPolicy, RetryState state, RetryContext context, Throwable e) {
if (state != null) {
Object key = state.getKey();
if (context.getRetryCount() > 0 && !retryContextCache.containsKey(key)) {
@@ -415,7 +416,7 @@ public class RetryTemplate implements RetryOperations {
throw new ExhaustedRetryException("Retry exhausted after last attempt with no recovery path", context
.getLastThrowable());
}
throw context.getLastThrowable();
throw wrapIfNecessary(context.getLastThrowable());
}
/**
@@ -462,4 +463,20 @@ public class RetryTemplate implements RetryOperations {
}
}
/**
* Re-throws the original throwable if it is unchecked, wraps checked
* exceptions into {@link RepeatException}.
*/
private static Exception wrapIfNecessary(Throwable throwable) {
if (throwable instanceof Error) {
throw (Error) throwable;
}
else if (throwable instanceof Exception) {
return (Exception) throwable;
}
else {
return new RetryException("Exception in batch process", throwable);
}
}
}

View File

@@ -62,7 +62,7 @@ public class CompositeRetryPolicyTests extends TestCase {
return !errorRegistered;
}
public void registerThrowable(RetryContext context, Exception throwable) {
public void registerThrowable(RetryContext context, Throwable throwable) {
errorRegistered = true;
}
} });
@@ -70,7 +70,7 @@ public class CompositeRetryPolicyTests extends TestCase {
assertNotNull(context);
assertTrue(policy.canRetry(context));
policy.registerThrowable(context, null);
assertFalse(policy.canRetry(context));
assertFalse("Should be still able to retry", policy.canRetry(context));
}
public void testNonTrivialPoliciesClose() throws Exception {

View File

@@ -16,14 +16,18 @@
package org.springframework.batch.retry.support;
import static org.easymock.EasyMock.createStrictMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.fail;
import static org.easymock.EasyMock.*;
import java.util.Collections;
import org.junit.Test;
@@ -295,7 +299,7 @@ public class RetryTemplateTests {
}, null, new DefaultRetryState(tested) {
@Override
public boolean rollbackFor(Exception exception) {
public boolean rollbackFor(Throwable exception) {
return true;
}