diff --git a/src/main/java/org/springframework/retry/backoff/BackOffContext.java b/src/main/java/org/springframework/retry/backoff/BackOffContext.java index 8d7249f..31752d1 100644 --- a/src/main/java/org/springframework/retry/backoff/BackOffContext.java +++ b/src/main/java/org/springframework/retry/backoff/BackOffContext.java @@ -16,10 +16,12 @@ package org.springframework.retry.backoff; +import java.io.Serializable; + /** * @author Rob Harrop * @since 2.1 */ -public interface BackOffContext { +public interface BackOffContext extends Serializable { } diff --git a/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java index 902732e..ea6984b 100644 --- a/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java @@ -22,31 +22,29 @@ import org.springframework.retry.RetryContext; import org.springframework.util.ClassUtils; /** - * Implementation of {@link BackOffPolicy} that increases the back off period - * for each retry attempt in a given set using the {@link Math#exp(double) - * exponential} function. + * Implementation of {@link BackOffPolicy} that increases the back off period for each + * retry attempt in a given set using the {@link Math#exp(double) exponential} function. * - * This implementation is thread-safe and suitable for concurrent access. - * Modifications to the configuration do not affect any retry sets that are - * already in progress. + * This implementation is thread-safe and suitable for concurrent access. Modifications to + * the configuration do not affect any retry sets that are already in progress. * - * The {@link #setInitialInterval(long)} property controls the initial value - * passed to {@link Math#exp(double)} and the {@link #setMultiplier(double)} - * property controls by how much this value is increased for each subsequent - * attempt. + * The {@link #setInitialInterval(long)} property controls the initial value passed to + * {@link Math#exp(double)} and the {@link #setMultiplier(double)} property controls by + * how much this value is increased for each subsequent attempt. * * @author Rob Harrop * @author Dave Syer * @author Gary Russell * @author Artem Bilan */ -public class ExponentialBackOffPolicy implements SleepingBackOffPolicy { +@SuppressWarnings("serial") +public class ExponentialBackOffPolicy + implements SleepingBackOffPolicy { protected final Log logger = LogFactory.getLog(this.getClass()); /** - * The default 'initialInterval' value - 100 millisecs. Coupled with the - * default 'multiplier' value this gives a useful initial spread of pauses - * for 1-5 retries. + * The default 'initialInterval' value - 100 millisecs. Coupled with the default + * 'multiplier' value this gives a useful initial spread of pauses for 1-5 retries. */ public static final long DEFAULT_INITIAL_INTERVAL = 100L; @@ -85,27 +83,27 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicy2.0'. Hint: do not use - * values much in excess of 1.0 (or the backoff will get very long very - * fast). + * Set the multiplier value. Default is '2.0'. Hint: do not use values + * much in excess of 1.0 (or the backoff will get very long very fast). * @param multiplier the multiplier */ public void setMultiplier(double multiplier) { @@ -124,10 +121,10 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicyexp(backOffContext.expSeed)'. + * Pause for a length of time equal to ' exp(backOffContext.expSeed)'. */ - public void backOff(BackOffContext backOffContext) throws BackOffInterruptedException { + public void backOff(BackOffContext backOffContext) + throws BackOffInterruptedException { ExponentialBackOffContext context = (ExponentialBackOffContext) backOffContext; try { long sleepTime = context.getSleepAndIncrement(); @@ -188,7 +185,7 @@ public class ExponentialBackOffPolicy implements SleepingBackOffPolicy maxInterval) { - sleep = maxInterval; - } - else { - this.interval = getNextInterval(); - } - return sleep; - } + public synchronized long getSleepAndIncrement() { + long sleep = this.interval; + if (sleep > maxInterval) { + sleep = maxInterval; + } + else { + this.interval = getNextInterval(); + } + return sleep; + } - protected long getNextInterval() { - return (long)(this.interval * this.multiplier); - } + protected long getNextInterval() { + return (long) (this.interval * this.multiplier); + } - public double getMultiplier() { - return multiplier; - } + public double getMultiplier() { + return multiplier; + } - public long getInterval() { - return interval; - } + public long getInterval() { + return interval; + } - public long getMaxInterval() { - return maxInterval; - } + public long getMaxInterval() { + return maxInterval; + } } public String toString() { - return ClassUtils.getShortName(getClass()) + "[initialInterval=" + initialInterval + ", multiplier=" - + multiplier + ", maxInterval=" + maxInterval + "]"; + return ClassUtils.getShortName(getClass()) + "[initialInterval=" + initialInterval + + ", multiplier=" + multiplier + ", maxInterval=" + maxInterval + "]"; } } diff --git a/src/main/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicy.java index 8e87d1e..6e16d41 100644 --- a/src/main/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicy.java @@ -41,6 +41,7 @@ import java.util.Random; * @author Jon Travis * @author Dave Syer */ +@SuppressWarnings("serial") public class ExponentialRandomBackOffPolicy extends ExponentialBackOffPolicy { /** * Returns a new instance of {@link org.springframework.retry.backoff.BackOffContext}, diff --git a/src/main/java/org/springframework/retry/backoff/NoBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/NoBackOffPolicy.java index 231bd55..fc89746 100644 --- a/src/main/java/org/springframework/retry/backoff/NoBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/NoBackOffPolicy.java @@ -28,4 +28,10 @@ public class NoBackOffPolicy extends StatelessBackOffPolicy { protected void doBackOff() throws BackOffInterruptedException { } + + @Override + public String toString() { + return "NoBackOffPolicy []"; + } + } diff --git a/src/main/java/org/springframework/retry/backoff/ObjectWaitSleeper.java b/src/main/java/org/springframework/retry/backoff/ObjectWaitSleeper.java index 208ee05..c9b0fe0 100644 --- a/src/main/java/org/springframework/retry/backoff/ObjectWaitSleeper.java +++ b/src/main/java/org/springframework/retry/backoff/ObjectWaitSleeper.java @@ -22,6 +22,7 @@ package org.springframework.retry.backoff; * @author Dave Syer * */ +@SuppressWarnings("serial") @Deprecated public class ObjectWaitSleeper implements Sleeper { diff --git a/src/main/java/org/springframework/retry/backoff/Sleeper.java b/src/main/java/org/springframework/retry/backoff/Sleeper.java index 2e7d3dd..e64cda7 100644 --- a/src/main/java/org/springframework/retry/backoff/Sleeper.java +++ b/src/main/java/org/springframework/retry/backoff/Sleeper.java @@ -15,13 +15,15 @@ */ package org.springframework.retry.backoff; +import java.io.Serializable; + /** * Strategy interface for backoff policies to delegate the pausing of execution. * * @author Dave Syer * */ -public interface Sleeper { +public interface Sleeper extends Serializable { /** * Pause for the specified period using whatever means available. diff --git a/src/main/java/org/springframework/retry/backoff/ThreadWaitSleeper.java b/src/main/java/org/springframework/retry/backoff/ThreadWaitSleeper.java index 322ab62..ee2c04a 100644 --- a/src/main/java/org/springframework/retry/backoff/ThreadWaitSleeper.java +++ b/src/main/java/org/springframework/retry/backoff/ThreadWaitSleeper.java @@ -22,6 +22,7 @@ package org.springframework.retry.backoff; * @author Artem Bilan * @since 1.1 */ +@SuppressWarnings("serial") public class ThreadWaitSleeper implements Sleeper { @Override diff --git a/src/main/java/org/springframework/retry/support/RetrySimulator.java b/src/main/java/org/springframework/retry/support/RetrySimulator.java index fe6a1dd..0d969fe 100644 --- a/src/main/java/org/springframework/retry/support/RetrySimulator.java +++ b/src/main/java/org/springframework/retry/support/RetrySimulator.java @@ -106,7 +106,8 @@ public class RetrySimulator { static class FailingRetryException extends Exception { } - static class StealingSleeper implements Sleeper { + @SuppressWarnings("serial") + static class StealingSleeper implements Sleeper { private final List sleeps = new ArrayList(); public void sleep(long backOffPeriod) throws InterruptedException { diff --git a/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java b/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java index 5914447..122cde2 100644 --- a/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java +++ b/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java @@ -171,6 +171,7 @@ public class EnableRetryTests { @EnableRetry protected static class TestConfiguration { + @SuppressWarnings("serial") @Bean public Sleeper sleeper() { return new Sleeper() { diff --git a/src/test/java/org/springframework/retry/annotation/EnableRetryWithBackoffTests.java b/src/test/java/org/springframework/retry/annotation/EnableRetryWithBackoffTests.java index 84396c0..a9c86bd 100644 --- a/src/test/java/org/springframework/retry/annotation/EnableRetryWithBackoffTests.java +++ b/src/test/java/org/springframework/retry/annotation/EnableRetryWithBackoffTests.java @@ -121,6 +121,7 @@ public class EnableRetryWithBackoffTests { } + @SuppressWarnings("serial") protected static class PeriodSleeper implements Sleeper { private List periods = new ArrayList(); diff --git a/src/test/java/org/springframework/retry/backoff/BackOffPolicySerializationTests.java b/src/test/java/org/springframework/retry/backoff/BackOffPolicySerializationTests.java new file mode 100644 index 0000000..03ff7c3 --- /dev/null +++ b/src/test/java/org/springframework/retry/backoff/BackOffPolicySerializationTests.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012-2015 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.retry.backoff; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AssignableTypeFilter; +import org.springframework.core.type.filter.RegexPatternTypeFilter; +import org.springframework.retry.context.RetryContextSupport; +import org.springframework.util.ClassUtils; +import org.springframework.util.SerializationUtils; + +import static org.junit.Assert.assertTrue; + +/** + * @author Dave Syer + * + */ +@RunWith(Parameterized.class) +public class BackOffPolicySerializationTests { + + private static Log logger = LogFactory.getLog(BackOffPolicySerializationTests.class); + + private BackOffPolicy policy; + + @Parameters(name = "{index}: {0}") + public static List policies() { + List result = new ArrayList(); + ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider( + true); + scanner.addIncludeFilter(new AssignableTypeFilter(BackOffPolicy.class)); + scanner.addExcludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*Test.*"))); + scanner.addExcludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*Mock.*"))); + scanner.addExcludeFilter( + new RegexPatternTypeFilter(Pattern.compile(".*Configuration.*"))); + Set candidates = scanner + .findCandidateComponents("org.springframework.retry"); + for (BeanDefinition beanDefinition : candidates) { + try { + result.add(new Object[] { BeanUtils.instantiate(ClassUtils + .resolveClassName(beanDefinition.getBeanClassName(), null)) }); + } + catch (Exception e) { + logger.warn( + "Cannot create instance of " + beanDefinition.getBeanClassName()); + } + } + return result; + } + + public BackOffPolicySerializationTests(BackOffPolicy policy) { + this.policy = policy; + } + + @Test + public void testSerializationCycleForContext() { + BackOffContext context = policy.start(new RetryContextSupport(null)); + if (context != null) { + assertTrue(SerializationUtils.deserialize( + SerializationUtils.serialize(context)) instanceof BackOffContext); + } + } + +} diff --git a/src/test/java/org/springframework/retry/backoff/DummySleeper.java b/src/test/java/org/springframework/retry/backoff/DummySleeper.java index 9e56251..f796000 100644 --- a/src/test/java/org/springframework/retry/backoff/DummySleeper.java +++ b/src/test/java/org/springframework/retry/backoff/DummySleeper.java @@ -25,6 +25,7 @@ import java.util.List; * @author Dave Syer * */ +@SuppressWarnings("serial") public class DummySleeper implements Sleeper { private List backOffs = new ArrayList(); diff --git a/src/test/java/org/springframework/retry/policy/RetryContextSerializationTests.java b/src/test/java/org/springframework/retry/policy/RetryContextSerializationTests.java index da911a7..1a5d448 100644 --- a/src/test/java/org/springframework/retry/policy/RetryContextSerializationTests.java +++ b/src/test/java/org/springframework/retry/policy/RetryContextSerializationTests.java @@ -17,7 +17,6 @@ package org.springframework.retry.policy; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Set; import java.util.regex.Pattern; diff --git a/src/test/java/org/springframework/retry/support/RetryTemplateTests.java b/src/test/java/org/springframework/retry/support/RetryTemplateTests.java index a687076..2e94b8a 100644 --- a/src/test/java/org/springframework/retry/support/RetryTemplateTests.java +++ b/src/test/java/org/springframework/retry/support/RetryTemplateTests.java @@ -349,6 +349,7 @@ public class RetryTemplateTests { tested.setRetryPolicy(new SimpleRetryPolicy(1)); BackOffPolicy bop = createStrictMock(BackOffPolicy.class); + @SuppressWarnings("serial") BackOffContext backOffContext = new BackOffContext() { }; tested.setBackOffPolicy(bop);