diff --git a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainerIntegrationTests.java b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainerIntegrationTests.java
index 46d6403ae..c730d0dff 100644
--- a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainerIntegrationTests.java
+++ b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/container/jms/BatchMessageListenerContainerIntegrationTests.java
@@ -30,8 +30,8 @@ import org.junit.runner.RunWith;
import org.springframework.batch.retry.RecoveryCallback;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
-import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.policy.NeverRetryPolicy;
+import org.springframework.batch.retry.support.DefaultRetryState;
import org.springframework.batch.retry.support.RetryTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
@@ -134,7 +134,7 @@ public class BatchMessageListenerContainerIntegrationTests {
return msg;
}
};
- retryTemplate.execute(callback, recoveryCallback, new RetryState(msg.getJMSMessageID()));
+ retryTemplate.execute(callback, recoveryCallback, new DefaultRetryState(msg.getJMSMessageID()));
}
catch (Exception e) {
throw (RuntimeException) e;
diff --git a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java
index 533c952cd..631ca0a13 100644
--- a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java
+++ b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/jms/ExternalRetryInBatchTests.java
@@ -37,8 +37,8 @@ import org.springframework.batch.repeat.support.RepeatTemplate;
import org.springframework.batch.retry.RecoveryCallback;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
-import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
+import org.springframework.batch.retry.support.DefaultRetryState;
import org.springframework.batch.retry.support.RetryTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
@@ -152,7 +152,7 @@ public class ExternalRetryInBatchTests {
}
};
- retryTemplate.execute(callback, recoveryCallback, new RetryState(item));
+ retryTemplate.execute(callback, recoveryCallback, new DefaultRetryState(item));
return ExitStatus.CONTINUABLE;
diff --git a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java
index d2af73012..3eaf09f16 100644
--- a/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java
+++ b/spring-batch-infrastructure-tests/src/test/java/org/springframework/batch/retry/jms/ExternalRetryTests.java
@@ -33,7 +33,7 @@ import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.retry.RecoveryCallback;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
-import org.springframework.batch.retry.RetryState;
+import org.springframework.batch.retry.support.DefaultRetryState;
import org.springframework.batch.retry.support.RetryTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
@@ -126,7 +126,7 @@ public class ExternalRetryTests {
return null;
}
};
- return retryTemplate.execute(callback, new RetryState(item));
+ return retryTemplate.execute(callback, new DefaultRetryState(item));
}
catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
@@ -154,7 +154,7 @@ public class ExternalRetryTests {
return null;
}
};
- return retryTemplate.execute(callback, new RetryState(item));
+ return retryTemplate.execute(callback, new DefaultRetryState(item));
}
catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
@@ -202,7 +202,7 @@ public class ExternalRetryTests {
result = (String) new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
public Object doInTransaction(TransactionStatus status) {
try {
- return retryTemplate.execute(callback, recoveryCallback, new RetryState(item));
+ return retryTemplate.execute(callback, recoveryCallback, new DefaultRetryState(item));
}
catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/RetryOperations.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/RetryOperations.java
index 3742dd914..158987dcd 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/RetryOperations.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/RetryOperations.java
@@ -16,6 +16,8 @@
package org.springframework.batch.retry;
+import org.springframework.batch.retry.support.DefaultRetryState;
+
/**
* Defines the basic set of operations implemented by {@link RetryOperations} to
* execute operations with configurable retry behaviour.
@@ -50,7 +52,7 @@ public interface RetryOperations {
/**
* A simple stateful retry. Execute the supplied {@link RetryCallback} with
- * a target object for the attempt identified by the {@link RetryState}.
+ * a target object for the attempt identified by the {@link DefaultRetryState}.
* Exceptions thrown by the callback are always propagated immediately so
* the state is required to be able to identify the previous attempt, if
* there is one - hence the state is required. Normal patterns would see
@@ -72,7 +74,7 @@ public interface RetryOperations {
* A stateful retry with a recovery path. Execute the supplied
* {@link RetryCallback} with a fallback on exhausted retry to the
* {@link RecoveryCallback} and a target object for the retry attempt
- * identified by the {@link RetryState}.
+ * identified by the {@link DefaultRetryState}.
*
* @see #execute(RetryCallback, RetryState)
*
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/RetryState.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/RetryState.java
index 632de9187..b17ea816c 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/RetryState.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/RetryState.java
@@ -16,38 +16,45 @@
package org.springframework.batch.retry;
/**
+ * Stateful retry is characterised by having to recognise the items that are
+ * being processed, so this interface is used primarily to provide a cache key in
+ * between failed attempts. It also provides a hints to the
+ * {@link RetryOperations} for optimisations to do with avoidable cache hits and
+ * switching to stateless retry if a rollback is not needed.
+ *
* @author Dave Syer
*
*/
-public class RetryState {
-
- final private Object key;
- final private boolean forceRefresh;
+public interface RetryState {
/**
- * @param key
- * @param forceRefresh
- */
- public RetryState(Object key, boolean forceRefresh) {
- this.key = key;
- this.forceRefresh = forceRefresh;
- }
-
- public RetryState(Object key) {
- this(key, false);
- }
- /**
+ * Key representing the state for a retry attempt. Stateful retry is
+ * characterised by having to recognise the items that are being processed,
+ * so this value is used as a cache key in between failed attempts.
+ *
* @return the key that this state represents
*/
- public Object getKey() {
- return key;
- }
+ Object getKey();
/**
- * @return true if the state requires an explicit check for the key
+ * Indicate whether a cache lookup can be avoided. If the key is known ahead
+ * of the retry attempt to be fresh (i.e. has never been seen before) then a
+ * cache lookup can be avoided if this flag is true.
+ *
+ * @return true if the state does not require an explicit check for the key
*/
- public boolean isForceRefresh() {
- return forceRefresh;
- }
+ boolean isForceRefresh();
-}
+ /**
+ * Check whether this exception requires a rollback. The default is always
+ * true, which is conservative, so this method provides an optimisation for
+ * switching to stateless retry if there is an exception for which rollback
+ * is unnecessary. Example usage would be for a stateful retry to specify a
+ * validation exception as not for rollback.
+ *
+ * @param exception the exception that caused a retry attempt to fail
+ * @return true if this exception should cause a rollback
+ */
+ boolean rollbackFor(Exception exception);
+
+}
\ No newline at end of file
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/interceptor/StatefulRetryOperationsInterceptor.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/interceptor/StatefulRetryOperationsInterceptor.java
index fdf1fb417..d2ac9a9fb 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/interceptor/StatefulRetryOperationsInterceptor.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/interceptor/StatefulRetryOperationsInterceptor.java
@@ -21,13 +21,14 @@ import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.retry.ExhaustedRetryException;
+import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.RecoveryCallback;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
import org.springframework.batch.retry.RetryOperations;
import org.springframework.batch.retry.RetryPolicy;
-import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.policy.NeverRetryPolicy;
+import org.springframework.batch.retry.support.DefaultRetryState;
import org.springframework.batch.retry.support.RetryTemplate;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -138,7 +139,7 @@ public class StatefulRetryOperationsInterceptor implements MethodInterceptor {
}
final Object item = arg;
- RetryState retryState = new RetryState(keyGenerator != null ? keyGenerator.getKey(args) : item, newMethodArgumentsIdentifier != null ? newMethodArgumentsIdentifier.isNew(args) : false );
+ RetryState retryState = new DefaultRetryState(keyGenerator != null ? keyGenerator.getKey(args) : item, newMethodArgumentsIdentifier != null ? newMethodArgumentsIdentifier.isNew(args) : false );
Object result = retryTemplate.execute(new MethodInvocationRetryCallback(invocation), new ItemRecovererCallback(args, recoverer), retryState);
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/support/DefaultRetryState.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/support/DefaultRetryState.java
new file mode 100644
index 000000000..7924a4bb7
--- /dev/null
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/support/DefaultRetryState.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2006-2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.batch.retry.support;
+
+import org.springframework.batch.retry.RecoveryCallback;
+import org.springframework.batch.retry.RetryCallback;
+import org.springframework.batch.retry.RetryOperations;
+import org.springframework.batch.retry.RetryState;
+import org.springframework.batch.support.Classifier;
+
+/**
+ *
+ * @author Dave Syer
+ *
+ */
+public class DefaultRetryState implements RetryState {
+
+ final private Object key;
+
+ final private boolean forceRefresh;
+
+ final private Classifier super Throwable, Boolean> rollbackClassifier;
+
+ /**
+ * Create a {@link DefaultRetryState} representing the state for a new retry
+ * attempt.
+ *
+ * @see RetryOperations#execute(RetryCallback, RetryState)
+ * @see RetryOperations#execute(RetryCallback, RecoveryCallback, RetryState)
+ *
+ * @param key the key for the state to allow this retry attempt to be
+ * recognised
+ * @param forceRefresh true if the attempt is known to be a brand new state
+ * @param rollbackClassifier the rollback classifier to set. The rollback
+ * classifier answers true if the exception provided should cause a
+ * rollback.
+ */
+ public DefaultRetryState(Object key, boolean forceRefresh, Classifier super Throwable, Boolean> rollbackClassifier) {
+ this.key = key;
+ this.forceRefresh = forceRefresh;
+ this.rollbackClassifier = rollbackClassifier;
+ }
+
+ /**
+ * Defaults the rollback classifier to null.
+ * @see DefaultRetryState#DefaultRetryState(Object, boolean, Classifier)
+ */
+ public DefaultRetryState(Object key, Classifier super Throwable, Boolean> rollbackClassifier) {
+ this(key, false, rollbackClassifier);
+ }
+
+ /**
+ * Defaults the rollback classifier to null.
+ * @see DefaultRetryState#DefaultRetryState(Object, boolean, Classifier)
+ */
+ public DefaultRetryState(Object key, boolean forceRefresh) {
+ this(key, forceRefresh, null);
+ }
+
+ /**
+ * Defaults the force refresh flag (to false) and the rollback classifier
+ * (to null).
+ *
+ * @see DefaultRetryState#DefaultRetryState(Object, boolean, Classifier)
+ */
+ public DefaultRetryState(Object key) {
+ this(key, false, null);
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.batch.retry.IRetryState#getKey()
+ */
+ public Object getKey() {
+ return key;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.batch.retry.IRetryState#isForceRefresh()
+ */
+ public boolean isForceRefresh() {
+ return forceRefresh;
+ }
+
+ /* (non-Javadoc)
+ * @see org.springframework.batch.retry.IRetryState#rollbackFor(java.lang.Exception)
+ */
+ public boolean rollbackFor(Exception exception) {
+ if (rollbackClassifier == null) {
+ return true;
+ }
+ return rollbackClassifier.classify(exception);
+ }
+
+}
diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/support/RetryTemplate.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/support/RetryTemplate.java
index b3c6f0c2a..621e4c192 100644
--- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/support/RetryTemplate.java
+++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/retry/support/RetryTemplate.java
@@ -23,6 +23,7 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.retry.ExhaustedRetryException;
+import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.RecoveryCallback;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
@@ -30,7 +31,6 @@ import org.springframework.batch.retry.RetryException;
import org.springframework.batch.retry.RetryListener;
import org.springframework.batch.retry.RetryOperations;
import org.springframework.batch.retry.RetryPolicy;
-import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.TerminatedRetryException;
import org.springframework.batch.retry.backoff.BackOffContext;
import org.springframework.batch.retry.backoff.BackOffInterruptedException;
@@ -39,7 +39,6 @@ import org.springframework.batch.retry.backoff.NoBackOffPolicy;
import org.springframework.batch.retry.policy.MapRetryContextCache;
import org.springframework.batch.retry.policy.RetryContextCache;
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
-import org.springframework.batch.support.Classifier;
/**
* Template class that simplifies the execution of operations with retry
@@ -79,45 +78,6 @@ public class RetryTemplate implements RetryOperations {
private RetryContextCache retryContextCache = new MapRetryContextCache();
- private Classifier super Throwable, Boolean> rollbackClassifier = null;
-
- /**
- * Public setter for the rollback classifier. This classifier answers its
- * default if the exception provided should not cause a rollback. I.e.
- * anything other than the default will lead to a rollback.
- *
- * The decision whether to rollback or not is unrelated to that of the
- * {@link RetryPolicy}, but the policy can be accidentally inconsistent
- * with the rollback decision. E.g. in a stateless retry the policy might be
- * configured to allow retry on a rollback, but that wouldn't make sense - a
- * stateful retry should have been used. The best we can do in such
- * circumstances is throw a {@link RetryException} from
- * {@link #execute(RetryCallback)} or
- * {@link #execute(RetryCallback, RecoveryCallback)}. The recovery path
- * will not be taken in such situations.
- *
- * For stateless retry it is often adequate to use the default behaviour, as
- * long as one is careful with the retry policy (exceptions which should
- * cause rollback are still not really retryable in a transactional
- * setting).
- *
- * For stateful retry adding a classifier will allow an optimisation:
- * exceptions which are not marked for rollback can still be retried, but
- * without paying the cost of a rollback. Effectively one is overriding the
- * stateful quality of the retry dynamically, according to the exception
- * type.
- *
- * Example usage would be for a stateful retry to specify a validation exception as not for rollback
- *
- * If not set then the default is to rollback for all exceptions when the
- * retry is stateful, and for none when it is stateless.
- *
- * @param rollbackClassifier the rollback classifier to set
- */
- public void setRollbackClassifier(Classifier super Throwable, Boolean> rollbackClassifier) {
- this.rollbackClassifier = rollbackClassifier;
- }
-
/**
* Public setter for the {@link RetryContextCache}.
* @param retryContextCache the {@link RetryContextCache} to set.
@@ -446,20 +406,12 @@ public class RetryTemplate implements RetryOperations {
* otherwise
*/
protected boolean shouldRethrow(RetryPolicy retryPolicy, RetryContext context, RetryState state) {
- // Allow stateless behaviour to take over for certain exception types
- if (rollbackClassifier != null) {
- // TODO: remove this. Make it part of the stateful execution parameters?
- // Then we wouldn't have to make assertions about the stateless case.
- boolean rollback = rollbackClassifier.classify(context.getLastThrowable());
- if (rollback && state == null && retryPolicy.canRetry(context)) {
- throw new RetryException("Inconsistent configuration. The retry policy says we can retry but "
- + "the exception has been marked for rollback.", context.getLastThrowable());
- }
- return rollback;
+ if (state == null) {
+ return false;
+ }
+ else {
+ return state.rollbackFor(context.getLastThrowable());
}
- // If no classifier is provided, just assume the all exceptions are for
- // rollback if the execution is stateful, and none otherwise.
- return state != null;
}
private boolean doOpenInterceptors(RetryCallback callback, RetryContext context) {
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/FatalExceptionRetryPolicyTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/FatalExceptionRetryPolicyTests.java
index e815f721c..56caae4d6 100644
--- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/FatalExceptionRetryPolicyTests.java
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/FatalExceptionRetryPolicyTests.java
@@ -24,7 +24,7 @@ import junit.framework.TestCase;
import org.springframework.batch.retry.RecoveryCallback;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
-import org.springframework.batch.retry.RetryState;
+import org.springframework.batch.retry.support.DefaultRetryState;
import org.springframework.batch.retry.support.RetryTemplate;
public class FatalExceptionRetryPolicyTests extends TestCase {
@@ -82,14 +82,14 @@ public class FatalExceptionRetryPolicyTests extends TestCase {
Object result = null;
try {
- retryTemplate.execute(callback, recoveryCallback, new RetryState("foo"));
+ retryTemplate.execute(callback, recoveryCallback, new DefaultRetryState("foo"));
fail("Expected IllegalArgumentException");
}
catch (IllegalArgumentException e) {
// If stateful we have to always rethrow. Clients who want special
// cases have to implement them in the callback
}
- result = retryTemplate.execute(callback, recoveryCallback, new RetryState("foo"));
+ result = retryTemplate.execute(callback, recoveryCallback, new DefaultRetryState("foo"));
// Callback is called once: the recovery path should also be called
assertEquals(1, callback.attempts);
assertEquals("bar", result);
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/StatefulRetryIntegrationTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/StatefulRetryIntegrationTests.java
index fa712c480..30ab5955e 100644
--- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/StatefulRetryIntegrationTests.java
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/policy/StatefulRetryIntegrationTests.java
@@ -24,9 +24,10 @@ import static org.junit.Assert.fail;
import org.junit.Test;
import org.springframework.batch.retry.ExhaustedRetryException;
+import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
-import org.springframework.batch.retry.RetryState;
+import org.springframework.batch.retry.support.DefaultRetryState;
import org.springframework.batch.retry.support.RetryTemplate;
/**
@@ -39,7 +40,7 @@ public class StatefulRetryIntegrationTests {
public void testExternalRetryWithFailAndNoRetry() throws Exception {
MockRetryCallback callback = new MockRetryCallback();
- RetryState retryState = new RetryState("foo");
+ RetryState retryState = new DefaultRetryState("foo");
RetryTemplate retryTemplate = new RetryTemplate();
MapRetryContextCache cache = new MapRetryContextCache();
@@ -80,7 +81,7 @@ public class StatefulRetryIntegrationTests {
public void testExternalRetryWithSuccessOnRetry() throws Exception {
MockRetryCallback callback = new MockRetryCallback();
- RetryState retryState = new RetryState("foo");
+ RetryState retryState = new DefaultRetryState("foo");
RetryTemplate retryTemplate = new RetryTemplate();
MapRetryContextCache cache = new MapRetryContextCache();
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/DefaultRetryStateTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/DefaultRetryStateTests.java
new file mode 100644
index 000000000..9d13caaeb
--- /dev/null
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/DefaultRetryStateTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2006-2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.batch.retry.support;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.springframework.batch.support.Classifier;
+
+/**
+ * @author Dave Syer
+ *
+ */
+public class DefaultRetryStateTests {
+
+ /**
+ * Test method for
+ * {@link org.springframework.batch.retry.support.DefaultRetryState#DefaultRetryState(java.lang.Object, boolean, org.springframework.batch.support.Classifier)}.
+ */
+ @Test
+ public void testDefaultRetryStateObjectBooleanClassifierOfQsuperThrowableBoolean() {
+ DefaultRetryState state = new DefaultRetryState("foo", true, new Classifier() {
+ public Boolean classify(Throwable classifiable) {
+ return false;
+ }
+ });
+ assertEquals("foo", state.getKey());
+ assertTrue(state.isForceRefresh());
+ assertFalse(state.rollbackFor(null));
+ }
+
+ /**
+ * Test method for
+ * {@link org.springframework.batch.retry.support.DefaultRetryState#DefaultRetryState(java.lang.Object, org.springframework.batch.support.Classifier)}.
+ */
+ @Test
+ public void testDefaultRetryStateObjectClassifierOfQsuperThrowableBoolean() {
+ DefaultRetryState state = new DefaultRetryState("foo", new Classifier() {
+ public Boolean classify(Throwable classifiable) {
+ return false;
+ }
+ });
+ assertEquals("foo", state.getKey());
+ assertFalse(state.isForceRefresh());
+ assertFalse(state.rollbackFor(null));
+ }
+
+ /**
+ * Test method for
+ * {@link org.springframework.batch.retry.support.DefaultRetryState#DefaultRetryState(java.lang.Object, boolean)}.
+ */
+ @Test
+ public void testDefaultRetryStateObjectBoolean() {
+ DefaultRetryState state = new DefaultRetryState("foo", true);
+ assertEquals("foo", state.getKey());
+ assertTrue(state.isForceRefresh());
+ assertTrue(state.rollbackFor(null));
+ }
+
+ /**
+ * Test method for
+ * {@link org.springframework.batch.retry.support.DefaultRetryState#DefaultRetryState(java.lang.Object)}.
+ */
+ @Test
+ public void testDefaultRetryStateObject() {
+ DefaultRetryState state = new DefaultRetryState("foo");
+ assertEquals("foo", state.getKey());
+ assertFalse(state.isForceRefresh());
+ assertTrue(state.rollbackFor(null));
+ }
+
+}
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/RetryTemplateTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/RetryTemplateTests.java
index 16d4464cf..72e7544fd 100644
--- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/RetryTemplateTests.java
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/RetryTemplateTests.java
@@ -29,7 +29,6 @@ import org.springframework.batch.retry.ExhaustedRetryException;
import org.springframework.batch.retry.RecoveryCallback;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
-import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.backoff.BackOffContext;
import org.springframework.batch.retry.backoff.BackOffInterruptedException;
import org.springframework.batch.retry.backoff.BackOffPolicy;
@@ -130,8 +129,7 @@ public class RetryTemplateTests {
retryTemplate.setRetryPolicy(new SimpleRetryPolicy(attempts));
BinaryExceptionClassifier classifier = new BinaryExceptionClassifier(Collections
.> singleton(IllegalArgumentException.class), false);
- retryTemplate.setRollbackClassifier(classifier);
- retryTemplate.execute(callback, new RetryState("foo"));
+ retryTemplate.execute(callback, new DefaultRetryState("foo",classifier));
assertEquals(attempts, callback.attempts);
}
diff --git a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/StatefulRecoveryRetryTests.java b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/StatefulRecoveryRetryTests.java
index 6c407167b..dd3082b80 100644
--- a/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/StatefulRecoveryRetryTests.java
+++ b/spring-batch-infrastructure/src/test/java/org/springframework/batch/retry/support/StatefulRecoveryRetryTests.java
@@ -31,12 +31,12 @@ import org.springframework.batch.repeat.RepeatContext;
import org.springframework.batch.repeat.context.RepeatContextSupport;
import org.springframework.batch.repeat.support.RepeatSynchronizationManager;
import org.springframework.batch.retry.ExhaustedRetryException;
+import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.RecoveryCallback;
import org.springframework.batch.retry.RetryCallback;
import org.springframework.batch.retry.RetryContext;
import org.springframework.batch.retry.RetryException;
import org.springframework.batch.retry.RetryPolicy;
-import org.springframework.batch.retry.RetryState;
import org.springframework.batch.retry.policy.MapRetryContextCache;
import org.springframework.batch.retry.policy.NeverRetryPolicy;
import org.springframework.batch.retry.policy.SimpleRetryPolicy;
@@ -53,7 +53,7 @@ public class StatefulRecoveryRetryTests {
@Test
public void testOpenSunnyDay() throws Exception {
- RetryContext context = retryTemplate.open(new NeverRetryPolicy(), new RetryState("foo"));
+ RetryContext context = retryTemplate.open(new NeverRetryPolicy(), new DefaultRetryState("foo"));
assertNotNull(context);
// we haven't called the processor yet...
assertEquals(0, count);
@@ -62,7 +62,7 @@ public class StatefulRecoveryRetryTests {
@Test
public void testRegisterThrowable() {
NeverRetryPolicy retryPolicy = new NeverRetryPolicy();
- RetryState state = new RetryState("foo");
+ RetryState state = new DefaultRetryState("foo");
RetryContext context = retryTemplate.open(retryPolicy, state);
assertNotNull(context);
retryTemplate.registerThrowable(retryPolicy, state, context, new Exception());
@@ -72,7 +72,7 @@ public class StatefulRecoveryRetryTests {
@Test
public void testClose() throws Exception {
NeverRetryPolicy retryPolicy = new NeverRetryPolicy();
- RetryState state = new RetryState("foo");
+ RetryState state = new DefaultRetryState("foo");
RetryContext context = retryTemplate.open(retryPolicy, state);
assertNotNull(context);
retryTemplate.registerThrowable(retryPolicy, state, context, new Exception());
@@ -96,7 +96,7 @@ public class StatefulRecoveryRetryTests {
public void testRecover() throws Exception {
retryTemplate.setRetryPolicy(new SimpleRetryPolicy(1));
final String input = "foo";
- RetryState state = new RetryState(input);
+ RetryState state = new DefaultRetryState(input);
RetryCallback callback = new RetryCallback() {
public String doWithRetry(RetryContext context) throws Exception {
throw new RuntimeException("Barf!");
@@ -132,9 +132,8 @@ public class StatefulRecoveryRetryTests {
.> singleton(DataAccessException.class));
// ...but not these:
assertFalse(classifier.classify(new RuntimeException()));
- retryTemplate.setRollbackClassifier(classifier);
final String input = "foo";
- RetryState state = new RetryState(input);
+ RetryState state = new DefaultRetryState(input,classifier);
RetryCallback callback = new RetryCallback() {
public String doWithRetry(RetryContext context) throws Exception {
throw new RuntimeException("Barf!");
@@ -161,7 +160,7 @@ public class StatefulRecoveryRetryTests {
retryTemplate.setRetryPolicy(retryPolicy);
final String input = "foo";
- RetryState state = new RetryState(input);
+ RetryState state = new DefaultRetryState(input);
RetryCallback callback = new RetryCallback() {
public String doWithRetry(RetryContext context) throws Exception {
throw new RuntimeException("Barf!");
@@ -195,7 +194,7 @@ public class StatefulRecoveryRetryTests {
RetryPolicy retryPolicy = new SimpleRetryPolicy(3);
retryTemplate.setRetryPolicy(retryPolicy);
final StringHolder item = new StringHolder("bar");
- RetryState state = new RetryState(item);
+ RetryState state = new DefaultRetryState(item);
RetryCallback callback = new RetryCallback() {
public StringHolder doWithRetry(RetryContext context) throws Exception {
@@ -247,7 +246,7 @@ public class StatefulRecoveryRetryTests {
};
try {
- retryTemplate.execute(callback, new RetryState("foo"));
+ retryTemplate.execute(callback, new DefaultRetryState("foo"));
fail("Expected RuntimeException");
}
catch (RuntimeException e) {
@@ -255,7 +254,7 @@ public class StatefulRecoveryRetryTests {
}
try {
- retryTemplate.execute(callback, new RetryState("bar"));
+ retryTemplate.execute(callback, new DefaultRetryState("bar"));
fail("Expected RetryException");
}
catch (RetryException e) {
@@ -271,7 +270,7 @@ public class StatefulRecoveryRetryTests {
retryTemplate.setRetryPolicy(retryPolicy);
retryTemplate.setRetryContextCache(new MapRetryContextCache(2));
final StringHolder item = new StringHolder("foo");
- RetryState state = new RetryState(item);
+ RetryState state = new DefaultRetryState(item);
RetryCallback