diff --git a/pom.xml b/pom.xml index 7af3c2e..e6358f3 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,7 @@ true 4.3.22.RELEASE + false @@ -348,6 +349,22 @@ + + io.spring.javaformat + spring-javaformat-maven-plugin + + + validate + + ${disable.checks} + + + apply + validate + + + + diff --git a/src/main/java/org/springframework/classify/BackToBackPatternClassifier.java b/src/main/java/org/springframework/classify/BackToBackPatternClassifier.java index 1e800ce..7082aa2 100644 --- a/src/main/java/org/springframework/classify/BackToBackPatternClassifier.java +++ b/src/main/java/org/springframework/classify/BackToBackPatternClassifier.java @@ -18,11 +18,11 @@ package org.springframework.classify; import java.util.Map; /** - * A special purpose {@link Classifier} with easy configuration options for - * mapping from one arbitrary type of object to another via a pattern matcher. - * + * A special purpose {@link Classifier} with easy configuration options for mapping from + * one arbitrary type of object to another via a pattern matcher. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class BackToBackPatternClassifier implements Classifier { @@ -32,28 +32,26 @@ public class BackToBackPatternClassifier implements Classifier { private Classifier matcher; /** - * Default constructor, provided as a convenience for people using setter - * injection. + * Default constructor, provided as a convenience for people using setter injection. */ public BackToBackPatternClassifier() { } /** * Set up a classifier with input to the router and output from the matcher. - * * @param router see {@link #setRouterDelegate(Object)} * @param matcher see {@link #setMatcherMap(Map)} */ - public BackToBackPatternClassifier(Classifier router, Classifier matcher) { + public BackToBackPatternClassifier(Classifier router, + Classifier matcher) { super(); this.router = router; this.matcher = matcher; } /** - * A convenience method for creating a pattern matching classifier for the - * matcher component. - * + * A convenience method for creating a pattern matching classifier for the matcher + * component. * @param map maps pattern keys with wildcards to output values */ public void setMatcherMap(Map map) { @@ -61,21 +59,19 @@ public class BackToBackPatternClassifier implements Classifier { } /** - * A convenience method of creating a router classifier based on a plain old - * Java Object. The object provided must have precisely one public method - * that either has the @Classifier annotation or accepts a single argument - * and outputs a String. This will be used to create an input classifier for - * the router component. - * + * A convenience method of creating a router classifier based on a plain old Java + * Object. The object provided must have precisely one public method that either has + * the @Classifier annotation or accepts a single argument and outputs a + * String. This will be used to create an input classifier for the router component. * @param delegate the delegate object used to create a router classifier */ public void setRouterDelegate(Object delegate) { - this.router = new ClassifierAdapter(delegate); + this.router = new ClassifierAdapter(delegate); } /** - * Classify the input and map to a String, then take that and put it into a - * pattern matcher to match to an output value. + * Classify the input and map to a String, then take that and put it into a pattern + * matcher to match to an output value. */ public T classify(C classifiable) { return matcher.classify(router.classify(classifiable)); diff --git a/src/main/java/org/springframework/classify/BinaryExceptionClassifier.java b/src/main/java/org/springframework/classify/BinaryExceptionClassifier.java index 8d338e1..54ca49f 100644 --- a/src/main/java/org/springframework/classify/BinaryExceptionClassifier.java +++ b/src/main/java/org/springframework/classify/BinaryExceptionClassifier.java @@ -21,14 +21,12 @@ import java.util.HashMap; import java.util.Map; /** - * A {@link Classifier} for exceptions that has only two classes (true and - * false). Classifies objects according to their inheritance relation with the - * supplied types. If the object to be classified is one of the provided types, - * or is a subclass of one of the types, then the non-default value is returned - * (usually true). + * A {@link Classifier} for exceptions that has only two classes (true and false). + * Classifies objects according to their inheritance relation with the supplied types. If + * the object to be classified is one of the provided types, or is a subclass of one of + * the types, then the non-default value is returned (usually true). * * @see SubclassClassifier - * * @author Dave Syer * @author Gary Russell * @@ -44,14 +42,13 @@ public class BinaryExceptionClassifier extends SubclassClassifier, Boolean> singletonMap(Exception.class, true), false - ); + return new BinaryExceptionClassifier(Collections + ., Boolean>singletonMap(Exception.class, true), + false); } /** * Create a binary exception classifier with the provided default value. - * * @param defaultValue defaults to false */ public BinaryExceptionClassifier(boolean defaultValue) { @@ -60,13 +57,13 @@ public class BinaryExceptionClassifier extends SubclassClassifier> exceptionClasses, boolean value) { + public BinaryExceptionClassifier( + Collection> exceptionClasses, boolean value) { this(!value); if (exceptionClasses != null) { Map, Boolean> map = new HashMap, Boolean>(); @@ -78,18 +75,18 @@ public class BinaryExceptionClassifier extends SubclassClassifier> exceptionClasses) { + public BinaryExceptionClassifier( + Collection> exceptionClasses) { this(exceptionClasses, true); } /** - * Create a binary exception classifier using the given classification map - * and a default classification of false. + * Create a binary exception classifier using the given classification map and a + * default classification of false. * @param typeMap the map of types */ public BinaryExceptionClassifier(Map, Boolean> typeMap) { @@ -97,25 +94,25 @@ public class BinaryExceptionClassifier extends SubclassClassifier, Boolean> typeMap, boolean defaultValue) { + public BinaryExceptionClassifier(Map, Boolean> typeMap, + boolean defaultValue) { super(typeMap, defaultValue); } /** * Create a binary exception classifier. - * * @param defaultValue the default value to use * @param typeMap the map of types to classify - * @param traverseCauses if true, throwable's causes will be inspected to find non-default class + * @param traverseCauses if true, throwable's causes will be inspected to find + * non-default class */ - public BinaryExceptionClassifier(Map, Boolean> typeMap, boolean defaultValue, - boolean traverseCauses) { + public BinaryExceptionClassifier(Map, Boolean> typeMap, + boolean defaultValue, boolean traverseCauses) { super(typeMap, defaultValue); this.traverseCauses = traverseCauses; } @@ -132,8 +129,8 @@ public class BinaryExceptionClassifier extends SubclassClassifier - * Can be used in while list style: - *
{@code
+ * Can be used in while list style: 
{@code
  * BinaryExceptionClassifier.newBuilder()
  * 			.retryOn(IOException.class)
  * 			.retryOn(IllegalArgumentException.class)
  * 			.build();
- * } 
- * or in black list style: - *
{@code
+ * } 
or in black list style:
{@code
  * BinaryExceptionClassifier.newBuilder()
  *            .notRetryOn(Error.class)
  *            .build();
@@ -40,18 +37,16 @@ import org.springframework.util.Assert;
  * 

* Provides traverseCauses=false by default, and no default rules for exceptions. *

- * Not thread safe. Building should be performed in a single thread, publishing of - * newly created instance should be safe. + * Not thread safe. Building should be performed in a single thread, publishing of newly + * created instance should be safe. * * @author Aleksandr Shamukov */ public class BinaryExceptionClassifierBuilder { /** - * Building notation type (white list or black list) - * - null: has not selected yet - * - true: white list - * - false: black list + * Building notation type (white list or black list) - null: has not selected yet - + * true: white list - false: black list */ private Boolean isWhiteList = null; @@ -59,7 +54,8 @@ public class BinaryExceptionClassifierBuilder { private List> exceptionClasses = new ArrayList>(); - public BinaryExceptionClassifierBuilder retryOn(Class throwable) { + public BinaryExceptionClassifierBuilder retryOn( + Class throwable) { Assert.isTrue(isWhiteList == null || isWhiteList, "Please use only retryOn() or only notRetryOn()"); Assert.notNull(throwable, "Exception class can not be null"); @@ -69,7 +65,8 @@ public class BinaryExceptionClassifierBuilder { } - public BinaryExceptionClassifierBuilder notRetryOn(Class throwable) { + public BinaryExceptionClassifierBuilder notRetryOn( + Class throwable) { Assert.isTrue(isWhiteList == null || !isWhiteList, "Please use only retryOn() or only notRetryOn()"); Assert.notNull(throwable, "Exception class can not be null"); @@ -88,10 +85,12 @@ public class BinaryExceptionClassifierBuilder { "Attempt to build classifier with empty rules. To build always true, or always false " + "instance, please use explicit rule for Throwable"); BinaryExceptionClassifier classifier = new BinaryExceptionClassifier( - exceptionClasses, - isWhiteList // using white list means classifying provided classes as "true" (is retryable) + exceptionClasses, isWhiteList // using white list means classifying + // provided classes as "true" (is + // retryable) ); classifier.setTraverseCauses(traverseCauses); return classifier; } + } diff --git a/src/main/java/org/springframework/classify/Classifier.java b/src/main/java/org/springframework/classify/Classifier.java index a440550..056a384 100644 --- a/src/main/java/org/springframework/classify/Classifier.java +++ b/src/main/java/org/springframework/classify/Classifier.java @@ -26,14 +26,13 @@ import java.io.Serializable; * themselves serializable. * * @author Dave Syer - * + * */ public interface Classifier extends Serializable { /** * Classify the given object and return an object of a different type, possibly an * enumerated type. - * * @param classifiable the input object. Can be null. * @return an object. Can be null, but implementations should declare if this is the * case. diff --git a/src/main/java/org/springframework/classify/ClassifierAdapter.java b/src/main/java/org/springframework/classify/ClassifierAdapter.java index 0341db6..14020d3 100644 --- a/src/main/java/org/springframework/classify/ClassifierAdapter.java +++ b/src/main/java/org/springframework/classify/ClassifierAdapter.java @@ -21,9 +21,9 @@ import org.springframework.util.Assert; /** * Wrapper for an object to adapt it to the {@link Classifier} interface. - * + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class ClassifierAdapter implements Classifier { @@ -40,9 +40,8 @@ public class ClassifierAdapter implements Classifier { } /** - * Create a new {@link Classifier} from the delegate provided. Use the - * constructor as an alternative to the {@link #setDelegate(Object)} method. - * + * Create a new {@link Classifier} from the delegate provided. Use the constructor as + * an alternative to the {@link #setDelegate(Object)} method. * @param delegate the delegate */ public ClassifierAdapter(Object delegate) { @@ -50,10 +49,8 @@ public class ClassifierAdapter implements Classifier { } /** - * Create a new {@link Classifier} from the delegate provided. Use the - * constructor as an alternative to the {@link #setDelegate(Classifier)} - * method. - * + * Create a new {@link Classifier} from the delegate provided. Use the constructor as + * an alternative to the {@link #setDelegate(Classifier)} method. * @param delegate the classifier to delegate to */ public ClassifierAdapter(Classifier delegate) { @@ -66,15 +63,13 @@ public class ClassifierAdapter implements Classifier { } /** - * Search for the - * {@link org.springframework.classify.annotation.Classifier - * Classifier} annotation on a method in the supplied delegate and use that - * to create a {@link Classifier} from the parameter type to the return - * type. If the annotation is not found a unique non-void method with a - * single parameter will be used, if it exists. The signature of the method - * cannot be checked here, so might be a runtime exception when the method - * is invoked if the signature doesn't match the classifier types. - * + * Search for the {@link org.springframework.classify.annotation.Classifier + * Classifier} annotation on a method in the supplied delegate and use that to create + * a {@link Classifier} from the parameter type to the return type. If the annotation + * is not found a unique non-void method with a single parameter will be used, if it + * exists. The signature of the method cannot be checked here, so might be a runtime + * exception when the method is invoked if the signature doesn't match the classifier + * types. * @param delegate an object with an annotated method */ public final void setDelegate(Object delegate) { @@ -82,7 +77,8 @@ public class ClassifierAdapter implements Classifier { invoker = MethodInvokerUtils.getMethodInvokerByAnnotation( org.springframework.classify.annotation.Classifier.class, delegate); if (invoker == null) { - invoker = MethodInvokerUtils. getMethodInvokerForSingleArgument(delegate); + invoker = MethodInvokerUtils + .getMethodInvokerForSingleArgument(delegate); } Assert.state(invoker != null, "No single argument public method with or without " + "@Classifier was found in delegate of type " + delegate.getClass()); diff --git a/src/main/java/org/springframework/classify/ClassifierSupport.java b/src/main/java/org/springframework/classify/ClassifierSupport.java index 5e0a54b..b5bcded 100644 --- a/src/main/java/org/springframework/classify/ClassifierSupport.java +++ b/src/main/java/org/springframework/classify/ClassifierSupport.java @@ -17,11 +17,11 @@ package org.springframework.classify; /** - * Base class for {@link Classifier} implementations. Provides default behaviour - * and some convenience members, like constants. - * + * Base class for {@link Classifier} implementations. Provides default behaviour and some + * convenience members, like constants. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class ClassifierSupport implements Classifier { @@ -37,9 +37,9 @@ public class ClassifierSupport implements Classifier { } /** - * Always returns the default value. This is the main extension point for - * subclasses, so it must be able to classify null. - * + * Always returns the default value. This is the main extension point for subclasses, + * so it must be able to classify null. + * * @see org.springframework.classify.Classifier#classify(Object) */ public T classify(C throwable) { diff --git a/src/main/java/org/springframework/classify/PatternMatcher.java b/src/main/java/org/springframework/classify/PatternMatcher.java index b8d96a0..9c810f2 100644 --- a/src/main/java/org/springframework/classify/PatternMatcher.java +++ b/src/main/java/org/springframework/classify/PatternMatcher.java @@ -31,6 +31,7 @@ import org.springframework.util.Assert; public class PatternMatcher { private Map map = new HashMap(); + private List sorted = new ArrayList(); /** @@ -52,12 +53,10 @@ public class PatternMatcher { } /** - * Lifted from AntPathMatcher in Spring Core. Tests whether or not a string - * matches against a pattern. The pattern may contain two special - * characters:
+ * Lifted from AntPathMatcher in Spring Core. Tests whether or not a string matches + * against a pattern. The pattern may contain two special characters:
* '*' means zero or more characters
* '?' means one and only one character - * * @param pattern pattern to match against. Must not be null. * @param str string which must be matched against the pattern. Must not be * null. @@ -192,20 +191,17 @@ public class PatternMatcher { /** *

- * This method takes a String key and a map from Strings to values of any - * type. During processing, the method will identify the most specific key - * in the map that matches the line. Once the correct is identified, its - * value is returned. Note that if the map contains the wildcard string "*" - * as a key, then it will serve as the "default" case, matching every line - * that does not match anything else. - * + * This method takes a String key and a map from Strings to values of any type. During + * processing, the method will identify the most specific key in the map that matches + * the line. Once the correct is identified, its value is returned. Note that if the + * map contains the wildcard string "*" as a key, then it will serve as the "default" + * case, matching every line that does not match anything else. + * *

- * If no matching prefix is found, a {@link IllegalStateException} will be - * thrown. - * + * If no matching prefix is found, a {@link IllegalStateException} will be thrown. + * *

* Null keys are not allowed in the map. - * * @param line An input string * @return the value whose prefix matches the given line */ @@ -222,7 +218,8 @@ public class PatternMatcher { } if (value == null) { - throw new IllegalStateException("Could not find a matching pattern for key=[" + line + "]"); + throw new IllegalStateException( + "Could not find a matching pattern for key=[" + line + "]"); } return value; diff --git a/src/main/java/org/springframework/classify/PatternMatchingClassifier.java b/src/main/java/org/springframework/classify/PatternMatchingClassifier.java index b0efef7..4ee2783 100644 --- a/src/main/java/org/springframework/classify/PatternMatchingClassifier.java +++ b/src/main/java/org/springframework/classify/PatternMatchingClassifier.java @@ -19,13 +19,13 @@ import java.util.HashMap; import java.util.Map; /** - * A {@link Classifier} that maps from String patterns with wildcards to a set - * of values of a given type. An input String is matched with the most specific - * pattern possible to the corresponding value in an input map. A default value - * should be specified with a pattern key of "*". - * + * A {@link Classifier} that maps from String patterns with wildcards to a set of values + * of a given type. An input String is matched with the most specific pattern possible to + * the corresponding value in an input map. A default value should be specified with a + * pattern key of "*". + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class PatternMatchingClassifier implements Classifier { @@ -33,17 +33,16 @@ public class PatternMatchingClassifier implements Classifier { private PatternMatcher values; /** - * Default constructor. Use the setter or the other constructor to create a - * sensible classifier, otherwise all inputs will cause an exception. + * Default constructor. Use the setter or the other constructor to create a sensible + * classifier, otherwise all inputs will cause an exception. */ public PatternMatchingClassifier() { this(new HashMap()); } /** - * Create a classifier from the provided map. The keys are patterns, using - * '?' as a single character and '*' as multi-character wildcard. - * + * Create a classifier from the provided map. The keys are patterns, using '?' as a + * single character and '*' as multi-character wildcard. * @param values the values to use in the {@link PatternMatcher} */ public PatternMatchingClassifier(Map values) { @@ -61,11 +60,9 @@ public class PatternMatchingClassifier implements Classifier { /** * Classify the input by matching it against the patterns provided in - * {@link #setPatternMap(Map)}. The most specific pattern that matches will - * be used to locate a value. - * + * {@link #setPatternMap(Map)}. The most specific pattern that matches will be used to + * locate a value. * @return the value matching the most specific pattern possible - * * @throws IllegalStateException if no matching value is found. */ public T classify(String classifiable) { diff --git a/src/main/java/org/springframework/classify/SubclassClassifier.java b/src/main/java/org/springframework/classify/SubclassClassifier.java index 7156bb1..098a266 100644 --- a/src/main/java/org/springframework/classify/SubclassClassifier.java +++ b/src/main/java/org/springframework/classify/SubclassClassifier.java @@ -21,12 +21,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** - * A {@link Classifier} for a parameterised object type based on a map. - * Classifies objects according to their inheritance relation with the supplied - * type map. If the object to be classified is one of the keys of the provided - * map, or is a subclass of one of the keys, then the map entry value for that - * key is returned. Otherwise returns the default value which is null by - * default. + * A {@link Classifier} for a parameterised object type based on a map. Classifies objects + * according to their inheritance relation with the supplied type map. If the object to be + * classified is one of the keys of the provided map, or is a subclass of one of the keys, + * then the map entry value for that key is returned. Otherwise returns the default value + * which is null by default. * * @author Dave Syer * @author Gary Russell @@ -49,7 +48,6 @@ public class SubclassClassifier implements Classifier { /** * Create a {@link SubclassClassifier} with supplied default value. - * * @param defaultValue the default value */ public SubclassClassifier(C defaultValue) { @@ -58,7 +56,6 @@ public class SubclassClassifier implements Classifier { /** * Create a {@link SubclassClassifier} with supplied default value. - * * @param defaultValue the default value * @param typeMap the map of types */ @@ -69,9 +66,8 @@ public class SubclassClassifier implements Classifier { } /** - * Public setter for the default value for mapping keys that are not found - * in the map (or their subclasses). Defaults to false. - * + * Public setter for the default value for mapping keys that are not found in the map + * (or their subclasses). Defaults to false. * @param defaultValue the default value to set */ public void setDefaultValue(C defaultValue) { @@ -79,10 +75,9 @@ public class SubclassClassifier implements Classifier { } /** - * Set the classifications up as a map. The keys are types and these will be - * mapped along with all their subclasses to the corresponding value. The - * most specific types will match first. - * + * Set the classifications up as a map. The keys are types and these will be mapped + * along with all their subclasses to the corresponding value. The most specific types + * will match first. * @param map a map from type to class */ public void setTypeMap(Map, C> map) { @@ -90,9 +85,8 @@ public class SubclassClassifier implements Classifier { } /** - * Return the value from the type map whose key is the class of the given - * Throwable, or its nearest ancestor if a subclass. - * + * Return the value from the type map whose key is the class of the given Throwable, + * or its nearest ancestor if a subclass. * @return C the classified value * @param classifiable the classifiable thing */ @@ -110,11 +104,12 @@ public class SubclassClassifier implements Classifier { // check for subclasses C value = null; - for (Class cls = exceptionClass; !cls.equals(Object.class) && value == null; cls = cls.getSuperclass()) { + for (Class cls = exceptionClass; !cls.equals(Object.class) + && value == null; cls = cls.getSuperclass()) { value = classified.get(cls); } - //ConcurrentHashMap doesn't allow nulls + // ConcurrentHashMap doesn't allow nulls if (value != null) { this.classified.put(exceptionClass, value); } @@ -128,7 +123,6 @@ public class SubclassClassifier implements Classifier { /** * Return the default value supplied in the constructor (default false). - * * @return C the default value */ final public C getDefault() { @@ -138,4 +132,5 @@ public class SubclassClassifier implements Classifier { protected Map, C> getClassified() { return classified; } + } diff --git a/src/main/java/org/springframework/classify/annotation/Classifier.java b/src/main/java/org/springframework/classify/annotation/Classifier.java index fdd612b..fceda2f 100644 --- a/src/main/java/org/springframework/classify/annotation/Classifier.java +++ b/src/main/java/org/springframework/classify/annotation/Classifier.java @@ -23,11 +23,11 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * Mark a method as capable of classifying its input to an instance of its - * output. Should only be used on non-void methods with one parameter. - * + * Mark a method as capable of classifying its input to an instance of its output. Should + * only be used on non-void methods with one parameter. + * * @author Dave Syer - * + * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) diff --git a/src/main/java/org/springframework/classify/util/AnnotationMethodResolver.java b/src/main/java/org/springframework/classify/util/AnnotationMethodResolver.java index 0b59c66..f91206c 100644 --- a/src/main/java/org/springframework/classify/util/AnnotationMethodResolver.java +++ b/src/main/java/org/springframework/classify/util/AnnotationMethodResolver.java @@ -29,16 +29,15 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; /** - * MethodResolver implementation that finds a single Method on the - * given Class that contains the specified annotation type. - * + * MethodResolver implementation that finds a single Method on the given Class + * that contains the specified annotation type. + * * @author Mark Fisher */ public class AnnotationMethodResolver implements MethodResolver { private Class annotationType; - /** * Create a MethodResolver for the specified Method-level annotation type * @param annotationType the type of the annotation @@ -51,19 +50,14 @@ public class AnnotationMethodResolver implements MethodResolver { this.annotationType = annotationType; } - /** - * Find a single Method on the Class of the given candidate object - * that contains the annotation type for which this resolver is searching. - * - * @param candidate the instance whose Class will be checked for the + * Find a single Method on the Class of the given candidate object that + * contains the annotation type for which this resolver is searching. + * @param candidate the instance whose Class will be checked for the annotation + * @return a single matching Method instance or null if the candidate's + * Class contains no Methods with the specified annotation + * @throws IllegalArgumentException if more than one Method has the specified * annotation - * - * @return a single matching Method instance or null if the - * candidate's Class contains no Methods with the specified annotation - * - * @throws IllegalArgumentException if more than one Method has the - * specified annotation */ public Method findMethod(Object candidate) { Assert.notNull(candidate, "candidate object must not be null"); @@ -75,26 +69,27 @@ public class AnnotationMethodResolver implements MethodResolver { } /** - * Find a single Method on the given Class that contains the - * annotation type for which this resolver is searching. - * + * Find a single Method on the given Class that contains the annotation type + * for which this resolver is searching. * @param clazz the Class instance to check for the annotation - * - * @return a single matching Method instance or null if the - * Class contains no Methods with the specified annotation - * - * @throws IllegalArgumentException if more than one Method has the - * specified annotation + * @return a single matching Method instance or null if the Class + * contains no Methods with the specified annotation + * @throws IllegalArgumentException if more than one Method has the specified + * annotation */ public Method findMethod(final Class clazz) { Assert.notNull(clazz, "class must not be null"); final AtomicReference annotatedMethod = new AtomicReference(); ReflectionUtils.doWithMethods(clazz, new ReflectionUtils.MethodCallback() { - public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { - Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType); + public void doWith(Method method) + throws IllegalArgumentException, IllegalAccessException { + Annotation annotation = AnnotationUtils.findAnnotation(method, + annotationType); if (annotation != null) { - Assert.isNull(annotatedMethod.get(), "found more than one method on target class [" - + clazz + "] with the annotation type [" + annotationType + "]"); + Assert.isNull(annotatedMethod.get(), + "found more than one method on target class [" + clazz + + "] with the annotation type [" + annotationType + + "]"); annotatedMethod.set(method); } } diff --git a/src/main/java/org/springframework/classify/util/MethodInvoker.java b/src/main/java/org/springframework/classify/util/MethodInvoker.java index 2e276e2..1083b80 100644 --- a/src/main/java/org/springframework/classify/util/MethodInvoker.java +++ b/src/main/java/org/springframework/classify/util/MethodInvoker.java @@ -17,13 +17,12 @@ package org.springframework.classify.util; /** - * A strategy interface for invoking a method. - * Typically used by adapters. - * + * A strategy interface for invoking a method. Typically used by adapters. + * * @author Mark Fisher */ public interface MethodInvoker { - Object invokeMethod(Object ... args); + Object invokeMethod(Object... args); } diff --git a/src/main/java/org/springframework/classify/util/MethodInvokerUtils.java b/src/main/java/org/springframework/classify/util/MethodInvokerUtils.java index bb4af58..4266159 100644 --- a/src/main/java/org/springframework/classify/util/MethodInvokerUtils.java +++ b/src/main/java/org/springframework/classify/util/MethodInvokerUtils.java @@ -41,7 +41,6 @@ public class MethodInvokerUtils { /** * Create a {@link MethodInvoker} using the provided method name to search. - * * @param object to be invoked * @param methodName of the method to be invoked * @param paramsRequired boolean indicating whether the parameters are required, if @@ -71,7 +70,6 @@ public class MethodInvokerUtils { /** * Create a String representation of the array of parameter types. - * * @param paramTypes the types of parameters * @return the paramTypes as String representation */ @@ -89,7 +87,6 @@ public class MethodInvokerUtils { /** * Create a {@link MethodInvoker} using the provided interface, and method name from * that interface. - * * @param cls the interface to search for the method named * @param methodName of the method to be invoked * @param object to be invoked @@ -111,7 +108,6 @@ public class MethodInvokerUtils { /** * Create a MethodInvoker from the delegate based on the annotationType. Ensure that * the annotated method has a valid set of parameters. - * * @param annotationType the annotation to scan for * @param target the target object * @param expectedParamTypes the expected parameter types for the method @@ -163,7 +159,6 @@ public class MethodInvokerUtils { * Create {@link MethodInvoker} for the method with the provided annotation on the * provided object. Annotations that cannot be applied to methods (i.e. that aren't * annotated with an element type of METHOD) will cause an exception to be thrown. - * * @param annotationType to be searched for * @param target to be invoked * @return MethodInvoker for the provided annotation, null if none is found. @@ -209,7 +204,6 @@ public class MethodInvokerUtils { /** * Create a {@link MethodInvoker} for the delegate from a single public method. - * * @param target an object to search for an appropriate method * @return a MethodInvoker that calls a method on the delegate * @param the t @@ -241,4 +235,5 @@ public class MethodInvokerUtils { Method method = methodHolder.get(); return new SimpleMethodInvoker(target, method); } + } diff --git a/src/main/java/org/springframework/classify/util/MethodResolver.java b/src/main/java/org/springframework/classify/util/MethodResolver.java index cc71ea8..1020652 100644 --- a/src/main/java/org/springframework/classify/util/MethodResolver.java +++ b/src/main/java/org/springframework/classify/util/MethodResolver.java @@ -20,37 +20,29 @@ import java.lang.reflect.Method; /** * Strategy interface for detecting a single Method on a Class. - * + * * @author Mark Fisher */ public interface MethodResolver { /** - * Find a single Method on the provided Object that matches this resolver's - * criteria. - * - * @param candidate the candidate Object whose Class should be searched for - * a Method - * - * @return a single Method or null if no Method matching this - * resolver's criteria can be found. - * - * @throws IllegalArgumentException if more than one Method defined on the - * given candidate's Class matches this resolver's criteria + * Find a single Method on the provided Object that matches this resolver's criteria. + * @param candidate the candidate Object whose Class should be searched for a Method + * @return a single Method or null if no Method matching this resolver's + * criteria can be found. + * @throws IllegalArgumentException if more than one Method defined on the given + * candidate's Class matches this resolver's criteria */ Method findMethod(Object candidate) throws IllegalArgumentException; /** - * Find a single Method on the given Class that matches this - * resolver's criteria. - * + * Find a single Method on the given Class that matches this resolver's + * criteria. * @param clazz the Class instance on which to search for a Method - * - * @return a single Method or null if no Method matching this - * resolver's criteria can be found. - * - * @throws IllegalArgumentException if more than one Method defined on the - * given Class matches this resolver's criteria + * @return a single Method or null if no Method matching this resolver's + * criteria can be found. + * @throws IllegalArgumentException if more than one Method defined on the given Class + * matches this resolver's criteria */ Method findMethod(Class clazz); diff --git a/src/main/java/org/springframework/classify/util/SimpleMethodInvoker.java b/src/main/java/org/springframework/classify/util/SimpleMethodInvoker.java index db1b934..6ca4aaa 100644 --- a/src/main/java/org/springframework/classify/util/SimpleMethodInvoker.java +++ b/src/main/java/org/springframework/classify/util/SimpleMethodInvoker.java @@ -24,10 +24,10 @@ import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** - * Simple implementation of the {@link MethodInvoker} interface that invokes a - * method on an object. If the method has no arguments, but arguments are - * provided, they are ignored and the method is invoked anyway. If there are - * more arguments than there are provided, then an exception is thrown. + * Simple implementation of the {@link MethodInvoker} interface that invokes a method on + * an object. If the method has no arguments, but arguments are provided, they are ignored + * and the method is invoked anyway. If there are more arguments than there are provided, + * then an exception is thrown. * * @author Lucas Ward * @author Artem Bilan @@ -54,14 +54,18 @@ public class SimpleMethodInvoker implements MethodInvoker { public SimpleMethodInvoker(Object object, String methodName, Class... paramTypes) { Assert.notNull(object, "Object to invoke must not be null"); - Method method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, paramTypes); + Method method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, + paramTypes); if (method == null) { // try with no params - method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, new Class[] {}); + method = ClassUtils.getMethodIfAvailable(object.getClass(), methodName, + new Class[] {}); } - Assert.notNull(method, "No methods found for name: [" + methodName + "] in class: [" - + object.getClass() + "] with arguments of type: [" + Arrays.toString(paramTypes) + "]"); + Assert.notNull(method, + "No methods found for name: [" + methodName + "] in class: [" + + object.getClass() + "] with arguments of type: [" + + Arrays.toString(paramTypes) + "]"); this.object = object; this.method = method; @@ -72,14 +76,14 @@ public class SimpleMethodInvoker implements MethodInvoker { /* * (non-Javadoc) * - * @see - * org.springframework.batch.core.configuration.util.MethodInvoker#invokeMethod + * @see org.springframework.batch.core.configuration.util.MethodInvoker#invokeMethod * (java.lang.Object[]) */ @Override public Object invokeMethod(Object... args) { Assert.state(this.parameterTypes.length == args.length, - "Wrong number of arguments, expected no more than: [" + this.parameterTypes.length + "]"); + "Wrong number of arguments, expected no more than: [" + + this.parameterTypes.length + "]"); try { // Extract the target from an Advised as late as possible @@ -88,8 +92,9 @@ public class SimpleMethodInvoker implements MethodInvoker { return method.invoke(target, args); } catch (Exception e) { - throw new IllegalArgumentException("Unable to invoke method: [" + this.method + "] on object: [" - + this.object + "] with arguments: [" + Arrays.toString(args) + "]", e); + throw new IllegalArgumentException("Unable to invoke method: [" + this.method + + "] on object: [" + this.object + "] with arguments: [" + + Arrays.toString(args) + "]", e); } } @@ -101,7 +106,8 @@ public class SimpleMethodInvoker implements MethodInvoker { source = ((Advised) target).getTargetSource().getTarget(); } catch (Exception e) { - throw new IllegalStateException("Could not extract target from proxy", e); + throw new IllegalStateException("Could not extract target from proxy", + e); } if (source instanceof Advised) { source = extractTarget(source, method); diff --git a/src/main/java/org/springframework/retry/RecoveryCallback.java b/src/main/java/org/springframework/retry/RecoveryCallback.java index 354484d..b55e798 100644 --- a/src/main/java/org/springframework/retry/RecoveryCallback.java +++ b/src/main/java/org/springframework/retry/RecoveryCallback.java @@ -17,9 +17,8 @@ package org.springframework.retry; /** * Callback for stateful retry after all tries are exhausted. - * + * * @author Dave Syer - * * @since 1.1 */ public interface RecoveryCallback { diff --git a/src/main/java/org/springframework/retry/RetryCallback.java b/src/main/java/org/springframework/retry/RetryCallback.java index c2989cd..b2b63c5 100644 --- a/src/main/java/org/springframework/retry/RetryCallback.java +++ b/src/main/java/org/springframework/retry/RetryCallback.java @@ -22,7 +22,6 @@ package org.springframework.retry; * * @param the type of object returned by the callback * @param the type of exception it declares may be thrown - * * @author Rob Harrop * @author Dave Syer */ @@ -30,11 +29,12 @@ public interface RetryCallback { /** * Execute an operation with retry semantics. Operations should generally be - * idempotent, but implementations may choose to implement compensation - * semantics when an operation is retried. + * idempotent, but implementations may choose to implement compensation semantics when + * an operation is retried. * @param context the current retry context. * @return the result of the successful operation. * @throws E of type E if processing fails */ T doWithRetry(RetryContext context) throws E; + } diff --git a/src/main/java/org/springframework/retry/RetryContext.java b/src/main/java/org/springframework/retry/RetryContext.java index 5240baf..0ad438e 100644 --- a/src/main/java/org/springframework/retry/RetryContext.java +++ b/src/main/java/org/springframework/retry/RetryContext.java @@ -21,9 +21,9 @@ import org.springframework.core.AttributeAccessor; /** * Low-level access to ongoing retry operation. Normally not needed by clients, but can be * used to alter the course of the retry, e.g. force an early termination. - * + * * @author Dave Syer - * + * */ public interface RetryContext extends AttributeAccessor { @@ -35,7 +35,8 @@ public interface RetryContext extends AttributeAccessor { String NAME = "context.name"; /** - * Retry context attribute name for state key. Can be used to identify a stateful retry from its context. + * Retry context attribute name for state key. Can be used to identify a stateful + * retry from its context. */ String STATE_KEY = "context.state"; @@ -62,14 +63,12 @@ public interface RetryContext extends AttributeAccessor { /** * Public accessor for the exhausted flag {@link #setExhaustedOnly()}. - * * @return true if the flag has been set. */ boolean isExhaustedOnly(); /** * Accessor for the parent context if retry blocks are nested. - * * @return the parent or null if there is none. */ RetryContext getParent(); @@ -77,14 +76,12 @@ public interface RetryContext extends AttributeAccessor { /** * Counts the number of retry attempts. Before the first attempt this counter is zero, * and before the first and subsequent attempts it should increment accordingly. - * * @return the number of retries. */ int getRetryCount(); /** * Accessor for the exception object that caused the current retry. - * * @return the last exception that caused a retry, or possibly null. It will 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). diff --git a/src/main/java/org/springframework/retry/RetryListener.java b/src/main/java/org/springframework/retry/RetryListener.java index 2a20d76..3732c36 100644 --- a/src/main/java/org/springframework/retry/RetryListener.java +++ b/src/main/java/org/springframework/retry/RetryListener.java @@ -16,53 +16,51 @@ package org.springframework.retry; - /** - * Interface for listener that can be used to add behaviour to a retry. - * Implementations of {@link RetryOperations} can chose to issue callbacks to an - * interceptor during the retry lifecycle. - * + * Interface for listener that can be used to add behaviour to a retry. Implementations of + * {@link RetryOperations} can chose to issue callbacks to an interceptor during the retry + * lifecycle. + * * @author Dave Syer - * + * */ public interface RetryListener { /** - * Called before the first attempt in a retry. For instance, implementers - * can set up state that is needed by the policies in the - * {@link RetryOperations}. The whole retry can be vetoed by returning - * false from this method, in which case a {@link TerminatedRetryException} - * will be thrown. - * + * Called before the first attempt in a retry. For instance, implementers can set up + * state that is needed by the policies in the {@link RetryOperations}. The whole + * retry can be vetoed by returning false from this method, in which case a + * {@link TerminatedRetryException} will be thrown. * @param the type of object returned by the callback * @param the type of exception it declares may be thrown * @param context the current {@link RetryContext}. * @param callback the current {@link RetryCallback}. * @return true if the retry should proceed. */ - boolean open(RetryContext context, RetryCallback callback); + boolean open(RetryContext context, + RetryCallback callback); /** - * Called after the final attempt (successful or not). Allow the interceptor - * to clean up any resource it is holding before control returns to the - * retry caller. - * + * Called after the final attempt (successful or not). Allow the interceptor to clean + * up any resource it is holding before control returns to the retry caller. * @param context the current {@link RetryContext}. * @param callback the current {@link RetryCallback}. * @param throwable the last exception that was thrown by the callback. * @param the exception type * @param the return value */ - void close(RetryContext context, RetryCallback callback, Throwable throwable); + void close(RetryContext context, + RetryCallback callback, Throwable throwable); /** * Called after every unsuccessful attempt at a retry. - * * @param context the current {@link RetryContext}. * @param callback the current {@link RetryCallback}. * @param throwable the last exception that was thrown by the callback. * @param the return value * @param the exception to throw */ - void onError(RetryContext context, RetryCallback callback, Throwable throwable); + void onError(RetryContext context, + RetryCallback callback, Throwable throwable); + } diff --git a/src/main/java/org/springframework/retry/RetryOperations.java b/src/main/java/org/springframework/retry/RetryOperations.java index ebb565a..a620081 100644 --- a/src/main/java/org/springframework/retry/RetryOperations.java +++ b/src/main/java/org/springframework/retry/RetryOperations.java @@ -19,22 +19,20 @@ package org.springframework.retry; import org.springframework.retry.support.DefaultRetryState; /** - * Defines the basic set of operations implemented by {@link RetryOperations} to - * execute operations with configurable retry behaviour. - * + * Defines the basic set of operations implemented by {@link RetryOperations} to execute + * operations with configurable retry behaviour. + * * @author Rob Harrop * @author Dave Syer */ public interface RetryOperations { /** - * Execute the supplied {@link RetryCallback} with the configured retry - * semantics. See implementations for configuration details. - * - * @return the value returned by the {@link RetryCallback} upon successful - * invocation. - * @throws E any {@link Exception} raised by the - * {@link RetryCallback} upon unsuccessful retry. + * Execute the supplied {@link RetryCallback} with the configured retry semantics. See + * implementations for configuration details. + * @return the value returned by the {@link RetryCallback} upon successful invocation. + * @throws E any {@link Exception} raised by the {@link RetryCallback} upon + * unsuccessful retry. * @throws E the exception thrown * @param the return value * @param retryCallback the {@link RetryCallback} @@ -43,60 +41,58 @@ public interface RetryOperations { T execute(RetryCallback retryCallback) throws E; /** - * Execute the supplied {@link RetryCallback} with a fallback on exhausted - * retry to the {@link RecoveryCallback}. See implementations for - * configuration details. - * - * @return the value returned by the {@link RetryCallback} upon successful - * invocation, and that returned by the {@link RecoveryCallback} otherwise. + * Execute the supplied {@link RetryCallback} with a fallback on exhausted retry to + * the {@link RecoveryCallback}. See implementations for configuration details. + * @return the value returned by the {@link RetryCallback} upon successful invocation, + * and that returned by the {@link RecoveryCallback} otherwise. * @throws E any {@link Exception} raised by the * @param the type to return * @param the type of the exception * @param recoveryCallback the {@link RecoveryCallback} - * @param retryCallback the {@link RetryCallback} - * {@link RecoveryCallback} upon unsuccessful retry. + * @param retryCallback the {@link RetryCallback} {@link RecoveryCallback} upon + * unsuccessful retry. */ - T execute(RetryCallback retryCallback, RecoveryCallback recoveryCallback) throws E; + T execute(RetryCallback retryCallback, + RecoveryCallback recoveryCallback) throws E; /** - * A simple stateful retry. Execute the supplied {@link RetryCallback} with - * 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 - * this method being used inside a transaction, where the callback might - * invalidate the transaction if it fails. - * - * See implementations for configuration details. + * A simple stateful retry. Execute the supplied {@link RetryCallback} with 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 this method being used inside a transaction, + * where the callback might invalidate the transaction if it fails. * + * See implementations for configuration details. * @param retryCallback the {@link RetryCallback} * @param retryState the {@link RetryState} - * @return the value returned by the {@link RetryCallback} upon successful - * invocation, and that returned by the {@link RecoveryCallback} otherwise. + * @return the value returned by the {@link RetryCallback} upon successful invocation, + * and that returned by the {@link RecoveryCallback} otherwise. * @throws E any {@link Exception} raised by the {@link RecoveryCallback}. - * @throws ExhaustedRetryException if the last attempt for this state has - * already been reached + * @throws ExhaustedRetryException if the last attempt for this state has already been + * reached * @param the type of the return value * @param the type of the exception to return */ - T execute(RetryCallback retryCallback, RetryState retryState) throws E, ExhaustedRetryException; + T execute(RetryCallback retryCallback, + RetryState retryState) throws E, ExhaustedRetryException; /** - * 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 DefaultRetryState}. + * 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 DefaultRetryState}. * @param recoveryCallback the {@link RecoveryCallback} * @param retryState the {@link RetryState} * @param retryCallback the {@link RetryCallback} * @see #execute(RetryCallback, RetryState) * @param the return value type * @param the exception type - * @return the value returned by the {@link RetryCallback} upon successful - * invocation, and that returned by the {@link RecoveryCallback} otherwise. - * @throws E any {@link Exception} raised by the {@link RecoveryCallback} upon unsuccessful retry. + * @return the value returned by the {@link RetryCallback} upon successful invocation, + * and that returned by the {@link RecoveryCallback} otherwise. + * @throws E any {@link Exception} raised by the {@link RecoveryCallback} upon + * unsuccessful retry. */ - T execute(RetryCallback retryCallback, RecoveryCallback recoveryCallback, RetryState retryState) - throws E; + T execute(RetryCallback retryCallback, + RecoveryCallback recoveryCallback, RetryState retryState) throws E; } diff --git a/src/main/java/org/springframework/retry/RetryPolicy.java b/src/main/java/org/springframework/retry/RetryPolicy.java index a0dc3dc..9538595 100644 --- a/src/main/java/org/springframework/retry/RetryPolicy.java +++ b/src/main/java/org/springframework/retry/RetryPolicy.java @@ -19,12 +19,11 @@ package org.springframework.retry; import java.io.Serializable; /** - * A {@link RetryPolicy} is responsible for allocating and managing resources - * needed by {@link RetryOperations}. The {@link RetryPolicy} allows retry - * operations to be aware of their context. Context can be internal to the retry - * framework, e.g. to support nested retries. Context can also be external, and - * the {@link RetryPolicy} provides a uniform API for a range of different - * platforms for the external context. + * A {@link RetryPolicy} is responsible for allocating and managing resources needed by + * {@link RetryOperations}. The {@link RetryPolicy} allows retry operations to be aware of + * their context. Context can be internal to the retry framework, e.g. to support nested + * retries. Context can also be external, and the {@link RetryPolicy} provides a uniform + * API for a range of different platforms for the external context. * * @author Dave Syer * @@ -38,25 +37,23 @@ public interface RetryPolicy extends Serializable { boolean canRetry(RetryContext context); /** - * Acquire resources needed for the retry operation. The callback is passed - * in so that marker interfaces can be used and a manager can collaborate - * with the callback to set up some state in the status token. + * Acquire resources needed for the retry operation. The callback is passed in so that + * marker interfaces can be used and a manager can collaborate with the callback to + * set up some state in the status token. * @param parent the parent context if we are in a nested retry. - * * @return a {@link RetryContext} object specific to this policy. * */ RetryContext open(RetryContext parent); /** - * @param context a retry status created by the - * {@link #open(RetryContext)} method of this policy. + * @param context a retry status created by the {@link #open(RetryContext)} method of + * this policy. */ void close(RetryContext context); /** * Called once per retry attempt, after the callback fails. - * * @param context the current status object. * @param throwable the exception to throw */ diff --git a/src/main/java/org/springframework/retry/RetryState.java b/src/main/java/org/springframework/retry/RetryState.java index 8089dc9..0758a11 100644 --- a/src/main/java/org/springframework/retry/RetryState.java +++ b/src/main/java/org/springframework/retry/RetryState.java @@ -16,42 +16,39 @@ package org.springframework.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. - * + * 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 interface RetryState { /** - * 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. - * + * 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 */ Object getKey(); /** - * 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. - * + * 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 */ 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. - * + * 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 */ diff --git a/src/main/java/org/springframework/retry/RetryStatistics.java b/src/main/java/org/springframework/retry/RetryStatistics.java index a86e1b8..35bd68c 100644 --- a/src/main/java/org/springframework/retry/RetryStatistics.java +++ b/src/main/java/org/springframework/retry/RetryStatistics.java @@ -17,11 +17,11 @@ package org.springframework.retry; /** - * Interface for statistics reporting of retry attempts. Counts the number of - * retry attempts, successes, errors (including retries), and aborts. - * + * Interface for statistics reporting of retry attempts. Counts the number of retry + * attempts, successes, errors (including retries), and aborts. + * * @author Dave Syer - * + * */ public interface RetryStatistics { @@ -31,39 +31,32 @@ public interface RetryStatistics { int getCompleteCount(); /** - * Get the number of times a retry block has been entered, irrespective of - * how many times the operation was retried. - * + * Get the number of times a retry block has been entered, irrespective of how many + * times the operation was retried. * @return the number of retry blocks started. */ int getStartedCount(); /** - * Get the number of errors detected, whether or not they resulted in a - * retry. - * + * Get the number of errors detected, whether or not they resulted in a retry. * @return the number of errors detected. */ int getErrorCount(); /** - * Get the number of times a block failed to complete successfully, even - * after retry. - * + * Get the number of times a block failed to complete successfully, even after retry. * @return the number of retry attempts that failed overall. */ int getAbortCount(); /** * Get the number of times a recovery callback was applied. - * * @return the number of recovered attempts. */ int getRecoveryCount(); /** * Get an identifier for the retry block for reporting purposes. - * * @return an identifier for the block. */ String getName(); diff --git a/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java b/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java index eb68953..110cf52 100644 --- a/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java +++ b/src/main/java/org/springframework/retry/annotation/AnnotationAwareRetryOperationsInterceptor.java @@ -63,8 +63,8 @@ import org.springframework.util.ReflectionUtils.MethodCallback; import org.springframework.util.StringUtils; /** - * Interceptor that parses the retry metadata on the method it is invoking and - * delegates to an appropriate RetryOperationsInterceptor. + * Interceptor that parses the retry metadata on the method it is invoking and delegates + * to an appropriate RetryOperationsInterceptor. * * @author Dave Syer * @author Artem Bilan @@ -72,7 +72,8 @@ import org.springframework.util.StringUtils; * @since 1.1 * */ -public class AnnotationAwareRetryOperationsInterceptor implements IntroductionInterceptor, BeanFactoryAware { +public class AnnotationAwareRetryOperationsInterceptor + implements IntroductionInterceptor, BeanFactoryAware { private static final TemplateParserContext PARSER_CONTEXT = new TemplateParserContext(); @@ -80,8 +81,7 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); - private final Map> delegates = - new HashMap>(); + private final Map> delegates = new HashMap>(); private RetryContextCache retryContextCache = new MapRetryContextCache(); @@ -104,7 +104,6 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn /** * Public setter for the {@link RetryContextCache}. - * * @param retryContextCache the {@link RetryContextCache} to set. */ public void setRetryContextCache(RetryContextCache retryContextCache) { @@ -121,7 +120,8 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn /** * @param newMethodArgumentsIdentifier the {@link NewMethodArgumentsIdentifier} */ - public void setNewItemIdentifier(NewMethodArgumentsIdentifier newMethodArgumentsIdentifier) { + public void setNewItemIdentifier( + NewMethodArgumentsIdentifier newMethodArgumentsIdentifier) { this.newMethodArgumentsIdentifier = newMethodArgumentsIdentifier; } @@ -130,7 +130,8 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn * @param globalListeners the default listeners */ public void setListeners(Collection globalListeners) { - ArrayList retryListeners = new ArrayList(globalListeners); + ArrayList retryListeners = new ArrayList( + globalListeners); AnnotationAwareOrderComparator.sort(retryListeners); this.globalListeners = retryListeners.toArray(new RetryListener[0]); } @@ -143,12 +144,14 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn @Override public boolean implementsInterface(Class intf) { - return org.springframework.retry.interceptor.Retryable.class.isAssignableFrom(intf); + return org.springframework.retry.interceptor.Retryable.class + .isAssignableFrom(intf); } @Override public Object invoke(MethodInvocation invocation) throws Throwable { - MethodInterceptor delegate = getDelegate(invocation.getThis(), invocation.getMethod()); + MethodInterceptor delegate = getDelegate(invocation.getThis(), + invocation.getMethod()); if (delegate != null) { return delegate.invoke(invocation); } @@ -158,16 +161,20 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn } private MethodInterceptor getDelegate(Object target, Method method) { - if (!this.delegates.containsKey(target) || !this.delegates.get(target).containsKey(method)) { + if (!this.delegates.containsKey(target) + || !this.delegates.get(target).containsKey(method)) { synchronized (this.delegates) { if (!this.delegates.containsKey(target)) { this.delegates.put(target, new HashMap()); } - Map delegatesForTarget = this.delegates.get(target); + Map delegatesForTarget = this.delegates + .get(target); if (!delegatesForTarget.containsKey(method)) { - Retryable retryable = AnnotationUtils.findAnnotation(method, Retryable.class); + Retryable retryable = AnnotationUtils.findAnnotation(method, + Retryable.class); if (retryable == null) { - retryable = AnnotationUtils.findAnnotation(method.getDeclaringClass(), Retryable.class); + retryable = AnnotationUtils.findAnnotation( + method.getDeclaringClass(), Retryable.class); } if (retryable == null) { retryable = findAnnotationOnTarget(target, method); @@ -177,7 +184,8 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn } MethodInterceptor delegate; if (StringUtils.hasText(retryable.interceptor())) { - delegate = this.beanFactory.getBean(retryable.interceptor(), MethodInterceptor.class); + delegate = this.beanFactory.getBean(retryable.interceptor(), + MethodInterceptor.class); } else if (retryable.stateful()) { delegate = getStatefulInterceptor(target, method, retryable); @@ -194,10 +202,13 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn private Retryable findAnnotationOnTarget(Object target, Method method) { try { - Method targetMethod = target.getClass().getMethod(method.getName(), method.getParameterTypes()); - Retryable retryable = AnnotationUtils.findAnnotation(targetMethod, Retryable.class); + Method targetMethod = target.getClass().getMethod(method.getName(), + method.getParameterTypes()); + Retryable retryable = AnnotationUtils.findAnnotation(targetMethod, + Retryable.class); if (retryable == null) { - retryable = AnnotationUtils.findAnnotation(targetMethod.getDeclaringClass(), Retryable.class); + retryable = AnnotationUtils.findAnnotation( + targetMethod.getDeclaringClass(), Retryable.class); } return retryable; @@ -207,23 +218,23 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn } } - private MethodInterceptor getStatelessInterceptor(Object target, Method method, Retryable retryable) { + private MethodInterceptor getStatelessInterceptor(Object target, Method method, + Retryable retryable) { RetryTemplate template = createTemplate(retryable.listeners()); template.setRetryPolicy(getRetryPolicy(retryable)); template.setBackOffPolicy(getBackoffPolicy(retryable.backoff())); - return RetryInterceptorBuilder.stateless() - .retryOperations(template) - .label(retryable.label()) - .recoverer(getRecoverer(target, method)) - .build(); + return RetryInterceptorBuilder.stateless().retryOperations(template) + .label(retryable.label()).recoverer(getRecoverer(target, method)).build(); } - private MethodInterceptor getStatefulInterceptor(Object target, Method method, Retryable retryable) { + private MethodInterceptor getStatefulInterceptor(Object target, Method method, + Retryable retryable) { RetryTemplate template = createTemplate(retryable.listeners()); template.setRetryContextCache(this.retryContextCache); - CircuitBreaker circuit = AnnotationUtils.findAnnotation(method, CircuitBreaker.class); - if (circuit!=null) { + CircuitBreaker circuit = AnnotationUtils.findAnnotation(method, + CircuitBreaker.class); + if (circuit != null) { RetryPolicy policy = getRetryPolicy(circuit); CircuitBreakerRetryPolicy breaker = new CircuitBreakerRetryPolicy(policy); breaker.setOpenTimeout(getOpenTimeout(circuit)); @@ -231,15 +242,13 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn template.setRetryPolicy(breaker); template.setBackOffPolicy(new NoBackOffPolicy()); String label = circuit.label(); - if (!StringUtils.hasText(label)) { + if (!StringUtils.hasText(label)) { label = method.toGenericString(); } return RetryInterceptorBuilder.circuitBreaker() .keyGenerator(new FixedKeyGenerator("circuit")) - .retryOperations(template) - .recoverer(getRecoverer(target, method)) - .label(label) - .build(); + .retryOperations(template).recoverer(getRecoverer(target, method)) + .label(label).build(); } RetryPolicy policy = getRetryPolicy(retryable); template.setRetryPolicy(policy); @@ -248,16 +257,14 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn return RetryInterceptorBuilder.stateful() .keyGenerator(this.methodArgumentsKeyGenerator) .newMethodArgumentsIdentifier(this.newMethodArgumentsIdentifier) - .retryOperations(template) - .label(label) - .recoverer(getRecoverer(target, method)) - .build(); + .retryOperations(template).label(label) + .recoverer(getRecoverer(target, method)).build(); } private long getOpenTimeout(CircuitBreaker circuit) { if (StringUtils.hasText(circuit.openTimeoutExpression())) { - Long value = PARSER.parseExpression(resolve(circuit.openTimeoutExpression()), PARSER_CONTEXT) - .getValue(Long.class); + Long value = PARSER.parseExpression(resolve(circuit.openTimeoutExpression()), + PARSER_CONTEXT).getValue(Long.class); if (value != null) { return value; } @@ -267,8 +274,8 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn private long getResetTimeout(CircuitBreaker circuit) { if (StringUtils.hasText(circuit.resetTimeoutExpression())) { - Long value = PARSER.parseExpression(resolve(circuit.resetTimeoutExpression()), PARSER_CONTEXT) - .getValue(Long.class); + Long value = PARSER.parseExpression(resolve(circuit.resetTimeoutExpression()), + PARSER_CONTEXT).getValue(Long.class); if (value != null) { return value; } @@ -280,7 +287,8 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn RetryTemplate template = new RetryTemplate(); if (listenersBeanNames.length > 0) { template.setListeners(getListenersBeans(listenersBeanNames)); - } else if (globalListeners !=null) { + } + else if (globalListeners != null) { template.setListeners(globalListeners); } return template; @@ -289,7 +297,8 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn private RetryListener[] getListenersBeans(String[] listenersBeanNames) { RetryListener[] listeners = new RetryListener[listenersBeanNames.length]; for (int i = 0; i < listeners.length; i++) { - listeners[i] = beanFactory.getBean(listenersBeanNames[i], RetryListener.class); + listeners[i] = beanFactory.getBean(listenersBeanNames[i], + RetryListener.class); } return listeners; } @@ -301,8 +310,8 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn final AtomicBoolean foundRecoverable = new AtomicBoolean(false); ReflectionUtils.doWithMethods(target.getClass(), new MethodCallback() { @Override - public void doWith(Method method) throws IllegalArgumentException, - IllegalAccessException { + public void doWith(Method method) + throws IllegalArgumentException, IllegalAccessException { if (AnnotationUtils.findAnnotation(method, Recover.class) != null) { foundRecoverable.set(true); } @@ -318,26 +327,31 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn private RetryPolicy getRetryPolicy(Annotation retryable) { Map attrs = AnnotationUtils.getAnnotationAttributes(retryable); @SuppressWarnings("unchecked") - Class[] includes = (Class[]) attrs.get("value"); + Class[] includes = (Class[]) attrs + .get("value"); String exceptionExpression = (String) attrs.get("exceptionExpression"); boolean hasExpression = StringUtils.hasText(exceptionExpression); if (includes.length == 0) { @SuppressWarnings("unchecked") - Class[] value = (Class[]) attrs.get("include"); + Class[] value = (Class[]) attrs + .get("include"); includes = value; } @SuppressWarnings("unchecked") - Class[] excludes = (Class[]) attrs.get("exclude"); + Class[] excludes = (Class[]) attrs + .get("exclude"); Integer maxAttempts = (Integer) attrs.get("maxAttempts"); String maxAttemptsExpression = (String) attrs.get("maxAttemptsExpression"); if (StringUtils.hasText(maxAttemptsExpression)) { - maxAttempts = PARSER.parseExpression(resolve(maxAttemptsExpression), PARSER_CONTEXT) + maxAttempts = PARSER + .parseExpression(resolve(maxAttemptsExpression), PARSER_CONTEXT) .getValue(this.evaluationContext, Integer.class); } if (includes.length == 0 && excludes.length == 0) { - SimpleRetryPolicy simple = hasExpression ? new ExpressionRetryPolicy(resolve(exceptionExpression)) - .withBeanFactory(this.beanFactory) - : new SimpleRetryPolicy(); + SimpleRetryPolicy simple = hasExpression + ? new ExpressionRetryPolicy(resolve(exceptionExpression)) + .withBeanFactory(this.beanFactory) + : new SimpleRetryPolicy(); simple.setMaxAttempts(maxAttempts); return simple; } @@ -350,8 +364,9 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn } boolean retryNotExcluded = includes.length == 0; if (hasExpression) { - return new ExpressionRetryPolicy(maxAttempts, policyMap, true, exceptionExpression, retryNotExcluded) - .withBeanFactory(this.beanFactory); + return new ExpressionRetryPolicy(maxAttempts, policyMap, true, + exceptionExpression, retryNotExcluded) + .withBeanFactory(this.beanFactory); } else { return new SimpleRetryPolicy(maxAttempts, policyMap, true, retryNotExcluded); @@ -361,17 +376,20 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn private BackOffPolicy getBackoffPolicy(Backoff backoff) { long min = backoff.delay() == 0 ? backoff.value() : backoff.delay(); if (StringUtils.hasText(backoff.delayExpression())) { - min = PARSER.parseExpression(resolve(backoff.delayExpression()), PARSER_CONTEXT) + min = PARSER + .parseExpression(resolve(backoff.delayExpression()), PARSER_CONTEXT) .getValue(this.evaluationContext, Long.class); } long max = backoff.maxDelay(); if (StringUtils.hasText(backoff.maxDelayExpression())) { - max = PARSER.parseExpression(resolve(backoff.maxDelayExpression()), PARSER_CONTEXT) - .getValue(this.evaluationContext, Long.class); + max = PARSER.parseExpression(resolve(backoff.maxDelayExpression()), + PARSER_CONTEXT).getValue(this.evaluationContext, Long.class); } double multiplier = backoff.multiplier(); if (StringUtils.hasText(backoff.multiplierExpression())) { - multiplier = PARSER.parseExpression(resolve(backoff.multiplierExpression()), PARSER_CONTEXT) + multiplier = PARSER + .parseExpression(resolve(backoff.multiplierExpression()), + PARSER_CONTEXT) .getValue(this.evaluationContext, Double.class); } if (multiplier > 0) { @@ -381,7 +399,8 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn } policy.setInitialInterval(min); policy.setMultiplier(multiplier); - policy.setMaxInterval(max > min ? max : ExponentialBackOffPolicy.DEFAULT_MAX_INTERVAL); + policy.setMaxInterval( + max > min ? max : ExponentialBackOffPolicy.DEFAULT_MAX_INTERVAL); if (this.sleeper != null) { policy.setSleeper(this.sleeper); } @@ -410,8 +429,10 @@ public class AnnotationAwareRetryOperationsInterceptor implements IntroductionIn * @see ConfigurableBeanFactory#resolveEmbeddedValue */ private String resolve(String value) { - if (this.beanFactory != null && this.beanFactory instanceof ConfigurableBeanFactory) { - return ((ConfigurableBeanFactory) this.beanFactory).resolveEmbeddedValue(value); + if (this.beanFactory != null + && this.beanFactory instanceof ConfigurableBeanFactory) { + return ((ConfigurableBeanFactory) this.beanFactory) + .resolveEmbeddedValue(value); } return value; } diff --git a/src/main/java/org/springframework/retry/annotation/Backoff.java b/src/main/java/org/springframework/retry/annotation/Backoff.java index 15283f7..cf00b21 100644 --- a/src/main/java/org/springframework/retry/annotation/Backoff.java +++ b/src/main/java/org/springframework/retry/annotation/Backoff.java @@ -49,19 +49,17 @@ import org.springframework.retry.backoff.BackOffPolicy; public @interface Backoff { /** - * Synonym for {@link #delay()}. When {@link #delay()} is non-zero, value of this element - * is ignored, otherwise value of this element is taken. - * + * Synonym for {@link #delay()}. When {@link #delay()} is non-zero, value of this + * element is ignored, otherwise value of this element is taken. * @return the delay in milliseconds (default 1000) */ long value() default 1000; /** * A canonical backoff period. Used as an initial value in the exponential case, and - * as a minimum value in the uniform case. When the value of this element is 0, - * value of element {@link #value()} istaken, otherwise value of this - * element is taken and {@link #value()} is ignored. - * + * as a minimum value in the uniform case. When the value of this element is 0, value + * of element {@link #value()} istaken, otherwise value of this element is taken and + * {@link #value()} is ignored. * @return the initial or canonical backoff period in milliseconds (default 0) */ long delay() default 0; @@ -71,14 +69,12 @@ public @interface Backoff { * {@link #delay()} then the default of * {@value org.springframework.retry.backoff.ExponentialBackOffPolicy#DEFAULT_MAX_INTERVAL} * is applied. - * * @return the maximum delay between retries (default 0 = ignored) */ long maxDelay() default 0; /** * If positive, then used as a multiplier for generating the next delay for backoff. - * * @return a multiplier to use to calculate the next backoff delay (default 0 = * ignored) */ @@ -98,7 +94,6 @@ public @interface Backoff { * If less than the {@link #delay()} then the default of * {@value org.springframework.retry.backoff.ExponentialBackOffPolicy#DEFAULT_MAX_INTERVAL} * is applied. Overrides {@link #maxDelay()} - * * @return the maximum delay between retries (default 0 = ignored) * @since 1.2 */ @@ -107,7 +102,6 @@ public @interface Backoff { /** * Evaluates to a vaule used as a multiplier for generating the next delay for * backoff. Overrides {@link #multiplier()}. - * * @return a multiplier expression to use to calculate the next backoff delay (default * 0 = ignored) * @since 1.2 @@ -118,7 +112,6 @@ public @interface Backoff { * In the exponential case ({@link #multiplier()} > 0) set this to true to have the * backoff delays randomized, so that the maximum delay is multiplier times the * previous delay and the distribution is uniform between the two values. - * * @return the flag to signal randomization is required (default false) */ boolean random() default false; diff --git a/src/main/java/org/springframework/retry/annotation/CircuitBreaker.java b/src/main/java/org/springframework/retry/annotation/CircuitBreaker.java index 706a453..b97bc0d 100644 --- a/src/main/java/org/springframework/retry/annotation/CircuitBreaker.java +++ b/src/main/java/org/springframework/retry/annotation/CircuitBreaker.java @@ -53,8 +53,8 @@ public @interface CircuitBreaker { /** * Exception types that are not retryable. Defaults to empty (and if includes is also - * empty all exceptions are retried). - * If includes is empty but excludes is not, all not excluded exceptions are retried + * empty all exceptions are retried). If includes is empty but excludes is not, all + * not excluded exceptions are retried * @return exception types not to retry */ Class[] exclude() default {}; @@ -74,7 +74,6 @@ public @interface CircuitBreaker { /** * A unique label for the circuit for reporting and state management. Defaults to the * method signature where the annotation is declared. - * * @return the label for the circuit */ String label() default ""; @@ -82,7 +81,6 @@ public @interface CircuitBreaker { /** * If the circuit is open for longer than this timeout then it resets on the next call * to give the downstream component a chance to respond again. - * * @return the timeout before an open circuit is reset in milliseconds, defaults to * 20000 */ @@ -92,7 +90,6 @@ public @interface CircuitBreaker { * If the circuit is open for longer than this timeout then it resets on the next call * to give the downstream component a chance to respond again. Overrides * {@link #resetTimeout()}. - * * @return the timeout before an open circuit is reset in milliseconds, no default. * @since 1.2.3 */ @@ -101,7 +98,6 @@ public @interface CircuitBreaker { /** * When {@link #maxAttempts()} failures are reached within this timeout, the circuit * is opened automatically, preventing access to the downstream component. - * * @return the timeout before an closed circuit is opened in milliseconds, defaults to * 5000 */ @@ -111,7 +107,6 @@ public @interface CircuitBreaker { * When {@link #maxAttempts()} failures are reached within this timeout, the circuit * is opened automatically, preventing access to the downstream component. Overrides * {@link #openTimeout()}. - * * @return the timeout before an closed circuit is opened in milliseconds, no default. * @since 1.2.3 */ @@ -133,7 +128,6 @@ public @interface CircuitBreaker { *

 	 *  {@code "@someBean.shouldRetry(#root)"}.
 	 * 
- * * @return the expression. * @since 1.2.3 */ diff --git a/src/main/java/org/springframework/retry/annotation/EnableRetry.java b/src/main/java/org/springframework/retry/annotation/EnableRetry.java index ea3944c..497d96a 100644 --- a/src/main/java/org/springframework/retry/annotation/EnableRetry.java +++ b/src/main/java/org/springframework/retry/annotation/EnableRetry.java @@ -30,7 +30,7 @@ import org.springframework.context.annotation.Import; * declared on any @Configuration in the context then beans that have * retryable methods will be proxied and the retry handled according to the metadata in * the annotations. - * + * * @author Dave Syer * @since 2.0 * @@ -43,9 +43,8 @@ import org.springframework.context.annotation.Import; public @interface EnableRetry { /** - * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed - * to standard Java interface-based proxies. The default is {@code false}. - * + * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed to + * standard Java interface-based proxies. The default is {@code false}. * @return whether to proxy or not to proxy the class */ boolean proxyTargetClass() default false; diff --git a/src/main/java/org/springframework/retry/annotation/Recover.java b/src/main/java/org/springframework/retry/annotation/Recover.java index 9ca936a..afd9d5f 100644 --- a/src/main/java/org/springframework/retry/annotation/Recover.java +++ b/src/main/java/org/springframework/retry/annotation/Recover.java @@ -31,7 +31,7 @@ import org.springframework.context.annotation.Import; * The Throwable first argument is optional (but a method without it will only be called * if no others match). Subsequent arguments are populated from the argument list of the * failed method in order. - * + * * @author Dave Syer * @since 2.0 * @@ -41,4 +41,5 @@ import org.springframework.context.annotation.Import; @Import(RetryConfiguration.class) @Documented public @interface Recover { + } diff --git a/src/main/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandler.java b/src/main/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandler.java index c586acf..fe976cc 100644 --- a/src/main/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandler.java +++ b/src/main/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandler.java @@ -46,7 +46,9 @@ import org.springframework.util.ReflectionUtils.MethodCallback; public class RecoverAnnotationRecoveryHandler implements MethodInvocationRecoverer { private SubclassClassifier classifier = new SubclassClassifier(); + private Map methods = new HashMap(); + private Object target; public RecoverAnnotationRecoveryHandler(Object target, Method method) { @@ -92,8 +94,8 @@ public class RecoverAnnotationRecoveryHandler implements MethodInvocationReco result = method; } else if (distance == min) { - boolean parametersMatch = compareParameters( args, meta.getArgCount(), - method.getParameterTypes() ); + boolean parametersMatch = compareParameters(args, meta.getArgCount(), + method.getParameterTypes()); if (parametersMatch) { result = method; } @@ -114,14 +116,16 @@ public class RecoverAnnotationRecoveryHandler implements MethodInvocationReco return result; } - private boolean compareParameters(Object[] args, int argCount, Class[] parameterTypes) { + private boolean compareParameters(Object[] args, int argCount, + Class[] parameterTypes) { if (argCount == (args.length + 1)) { int startingIndex = 0; - if (parameterTypes.length > 0 && Throwable.class.isAssignableFrom(parameterTypes[0])) { + if (parameterTypes.length > 0 + && Throwable.class.isAssignableFrom(parameterTypes[0])) { startingIndex = 1; } for (int i = startingIndex; i < parameterTypes.length; i++) { - final Object argument = args[i-1]; + final Object argument = args[i - 1]; if (argument == null) { continue; } @@ -140,26 +144,25 @@ public class RecoverAnnotationRecoveryHandler implements MethodInvocationReco ReflectionUtils.doWithMethods(failingMethod.getDeclaringClass(), new MethodCallback() { @Override - public void doWith(Method method) throws IllegalArgumentException, - IllegalAccessException { + public void doWith(Method method) + throws IllegalArgumentException, IllegalAccessException { Recover recover = AnnotationUtils.findAnnotation(method, Recover.class); - if (recover != null - && method.getReturnType().isAssignableFrom( - failingMethod.getReturnType())) { + if (recover != null && method.getReturnType() + .isAssignableFrom(failingMethod.getReturnType())) { Class[] parameterTypes = method.getParameterTypes(); - if (parameterTypes.length > 0 - && Throwable.class - .isAssignableFrom(parameterTypes[0])) { + if (parameterTypes.length > 0 && Throwable.class + .isAssignableFrom(parameterTypes[0])) { @SuppressWarnings("unchecked") Class type = (Class) parameterTypes[0]; types.put(type, method); - methods.put(method, new SimpleMetadata( - parameterTypes.length, type)); - } else { + methods.put(method, + new SimpleMetadata(parameterTypes.length, type)); + } + else { classifier.setDefaultValue(method); - methods.put(method, new SimpleMetadata( - parameterTypes.length, null)); + methods.put(method, + new SimpleMetadata(parameterTypes.length, null)); } } } @@ -181,7 +184,9 @@ public class RecoverAnnotationRecoveryHandler implements MethodInvocationReco } private static class SimpleMetadata { + private int argCount; + private Class type; public SimpleMetadata(int argCount, Class type) { @@ -208,6 +213,7 @@ public class RecoverAnnotationRecoveryHandler implements MethodInvocationReco System.arraycopy(args, 0, result, startArgs, result.length - startArgs); return result; } + } } diff --git a/src/main/java/org/springframework/retry/annotation/RetryConfiguration.java b/src/main/java/org/springframework/retry/annotation/RetryConfiguration.java index bf95264..19c284a 100644 --- a/src/main/java/org/springframework/retry/annotation/RetryConfiguration.java +++ b/src/main/java/org/springframework/retry/annotation/RetryConfiguration.java @@ -50,10 +50,10 @@ import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils.MethodCallback; /** - * Basic configuration for @Retryable processing. For stateful retry, if there is a unique bean elsewhere - * in the context of type {@link RetryContextCache}, {@link MethodArgumentsKeyGenerator} or - * {@link NewMethodArgumentsIdentifier} it will be used by the corresponding retry interceptor (otherwise sensible - * defaults are adopted). + * Basic configuration for @Retryable processing. For stateful retry, if + * there is a unique bean elsewhere in the context of type {@link RetryContextCache}, + * {@link MethodArgumentsKeyGenerator} or {@link NewMethodArgumentsIdentifier} it will be + * used by the corresponding retry interceptor (otherwise sensible defaults are adopted). * * @author Dave Syer * @author Artem Bilan @@ -62,7 +62,8 @@ import org.springframework.util.ReflectionUtils.MethodCallback; */ @SuppressWarnings("serial") @Configuration -public class RetryConfiguration extends AbstractPointcutAdvisor implements IntroductionAdvisor, BeanFactoryAware { +public class RetryConfiguration extends AbstractPointcutAdvisor + implements IntroductionAdvisor, BeanFactoryAware { private Advice advice; @@ -87,7 +88,8 @@ public class RetryConfiguration extends AbstractPointcutAdvisor implements Intro @PostConstruct public void init() { - Set> retryableAnnotationTypes = new LinkedHashSet>(1); + Set> retryableAnnotationTypes = new LinkedHashSet>( + 1); retryableAnnotationTypes.add(Retryable.class); this.pointcut = buildPointcut(retryableAnnotationTypes); this.advice = buildAdvice(); @@ -150,11 +152,11 @@ public class RetryConfiguration extends AbstractPointcutAdvisor implements Intro /** * Calculate a pointcut for the given retry annotation types, if any. - * * @param retryAnnotationTypes the retry annotation types to introspect * @return the applicable Pointcut object, or {@code null} if none */ - protected Pointcut buildPointcut(Set> retryAnnotationTypes) { + protected Pointcut buildPointcut( + Set> retryAnnotationTypes) { ComposablePointcut result = null; for (Class retryAnnotationType : retryAnnotationTypes) { Pointcut filter = new AnnotationClassOrMethodPointcut(retryAnnotationType); @@ -168,7 +170,8 @@ public class RetryConfiguration extends AbstractPointcutAdvisor implements Intro return result; } - private final class AnnotationClassOrMethodPointcut extends StaticMethodMatcherPointcut { + private final class AnnotationClassOrMethodPointcut + extends StaticMethodMatcherPointcut { private final MethodMatcher methodResolver; @@ -179,9 +182,10 @@ public class RetryConfiguration extends AbstractPointcutAdvisor implements Intro @Override public boolean matches(Method method, Class targetClass) { - return getClassFilter().matches(targetClass) || this.methodResolver.matches(method, targetClass); + return getClassFilter().matches(targetClass) + || this.methodResolver.matches(method, targetClass); } - + @Override public boolean equals(Object other) { if (this == other) { @@ -191,7 +195,8 @@ public class RetryConfiguration extends AbstractPointcutAdvisor implements Intro return false; } AnnotationClassOrMethodPointcut otherAdvisor = (AnnotationClassOrMethodPointcut) other; - return ObjectUtils.nullSafeEquals(this.methodResolver, otherAdvisor.methodResolver); + return ObjectUtils.nullSafeEquals(this.methodResolver, + otherAdvisor.methodResolver); } } @@ -213,31 +218,32 @@ public class RetryConfiguration extends AbstractPointcutAdvisor implements Intro } private static class AnnotationMethodsResolver { - + private Class annotationType; - + public AnnotationMethodsResolver(Class annotationType) { this.annotationType = annotationType; } - + public boolean hasAnnotatedMethods(Class clazz) { final AtomicBoolean found = new AtomicBoolean(false); - ReflectionUtils.doWithMethods(clazz, - new MethodCallback() { - @Override - public void doWith(Method method) throws IllegalArgumentException, - IllegalAccessException { - if (found.get()) { - return; - } - Annotation annotation = AnnotationUtils.findAnnotation(method, - annotationType); - if (annotation != null) { found.set(true); } - } + ReflectionUtils.doWithMethods(clazz, new MethodCallback() { + @Override + public void doWith(Method method) + throws IllegalArgumentException, IllegalAccessException { + if (found.get()) { + return; + } + Annotation annotation = AnnotationUtils.findAnnotation(method, + annotationType); + if (annotation != null) { + found.set(true); + } + } }); return found.get(); } - + } - + } diff --git a/src/main/java/org/springframework/retry/annotation/Retryable.java b/src/main/java/org/springframework/retry/annotation/Retryable.java index e970b7e..a37507a 100644 --- a/src/main/java/org/springframework/retry/annotation/Retryable.java +++ b/src/main/java/org/springframework/retry/annotation/Retryable.java @@ -59,8 +59,8 @@ public @interface Retryable { /** * Exception types that are not retryable. Defaults to empty (and if includes is also - * empty all exceptions are retried). - * If includes is empty but excludes is not, all not excluded exceptions are retried + * empty all exceptions are retried). If includes is empty but excludes is not, all + * not excluded exceptions are retried * @return exception types not to retry */ Class[] exclude() default {}; @@ -68,7 +68,6 @@ public @interface Retryable { /** * A unique label for statistics reporting. If not provided the caller may choose to * ignore it, or provide a default. - * * @return the label for the statistics */ String label() default ""; @@ -87,31 +86,28 @@ public @interface Retryable { int maxAttempts() default 3; /** - * @return an expression evaluated to the maximum number of attempts (including the first failure), defaults to 3 - * Overrides {@link #maxAttempts()}. + * @return an expression evaluated to the maximum number of attempts (including the + * first failure), defaults to 3 Overrides {@link #maxAttempts()}. * @since 1.2 */ String maxAttemptsExpression() default ""; /** - * Specify the backoff properties for retrying this operation. The default is a - * simple {@link Backoff} specification with no properties - see it's documentation - * for defaults. + * Specify the backoff properties for retrying this operation. The default is a simple + * {@link Backoff} specification with no properties - see it's documentation for + * defaults. * @return a backoff specification */ Backoff backoff() default @Backoff(); /** - * Specify an expression to be evaluated after the {@code SimpleRetryPolicy.canRetry()} - * returns true - can be used to conditionally suppress the retry. Only invoked after - * an exception is thrown. The root object for the evaluation is the last {@code Throwable}. - * Other beans in the context can be referenced. - * For example: - *
+	 * Specify an expression to be evaluated after the
+	 * {@code SimpleRetryPolicy.canRetry()} returns true - can be used to conditionally
+	 * suppress the retry. Only invoked after an exception is thrown. The root object for
+	 * the evaluation is the last {@code Throwable}. Other beans in the context can be
+	 * referenced. For example: 
 	 *  {@code "message.contains('you can retry this')"}.
-	 * 
- * and - *
+	 * 
and
 	 *  {@code "@someBean.shouldRetry(#root)"}.
 	 * 
* @return the expression. @@ -120,7 +116,8 @@ public @interface Retryable { String exceptionExpression() default ""; /** - * Bean names of retry listeners to use instead of default ones defined in Spring context + * Bean names of retry listeners to use instead of default ones defined in Spring + * context * @return retry listeners bean names */ String[] listeners() default {}; diff --git a/src/main/java/org/springframework/retry/backoff/BackOffInterruptedException.java b/src/main/java/org/springframework/retry/backoff/BackOffInterruptedException.java index 1723b76..32e049c 100644 --- a/src/main/java/org/springframework/retry/backoff/BackOffInterruptedException.java +++ b/src/main/java/org/springframework/retry/backoff/BackOffInterruptedException.java @@ -19,10 +19,10 @@ package org.springframework.retry.backoff; import org.springframework.retry.RetryException; /** - * Exception class signifiying that an attempt to back off using a - * {@link BackOffPolicy} was interrupted, most likely by an - * {@link InterruptedException} during a call to {@link Thread#sleep(long)}. - * + * Exception class signifiying that an attempt to back off using a {@link BackOffPolicy} + * was interrupted, most likely by an {@link InterruptedException} during a call to + * {@link Thread#sleep(long)}. + * * @author Rob Harrop * @since 2.1 */ @@ -36,4 +36,5 @@ public class BackOffInterruptedException extends RetryException { public BackOffInterruptedException(String msg, Throwable cause) { super(msg, cause); } + } diff --git a/src/main/java/org/springframework/retry/backoff/BackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/BackOffPolicy.java index 455a2bb..47eebe1 100644 --- a/src/main/java/org/springframework/retry/backoff/BackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/BackOffPolicy.java @@ -22,28 +22,27 @@ import org.springframework.retry.RetryContext; * Strategy interface to control back off between attempts in a single * {@link org.springframework.retry.support.RetryTemplate retry operation}. * - * Implementations are expected to be thread-safe and should be designed - * for concurrent access. Configuration for each implementation is also expected - * to be thread-safe but need not be suitable for high load concurrent access. + * Implementations are expected to be thread-safe and should be designed for concurrent + * access. Configuration for each implementation is also expected to be thread-safe but + * need not be suitable for high load concurrent access. * - * For each block of retry operations the {@link #start} method is called - * and implementations can return an implementation-specific + * For each block of retry operations the {@link #start} method is called and + * implementations can return an implementation-specific * - * {@link BackOffContext} that can be used to track state through subsequent - * back off invocations. Each back off process is handled via a call to {@link #backOff}. + * {@link BackOffContext} that can be used to track state through subsequent back off + * invocations. Each back off process is handled via a call to {@link #backOff}. + * + * The {@link org.springframework.retry.support.RetryTemplate} will pass in the + * corresponding {@link BackOffContext} object created by the call to {@link #start}. * - * The {@link org.springframework.retry.support.RetryTemplate} will pass in - * the corresponding {@link BackOffContext} object created by the call to {@link #start}. - * * @author Rob Harrop * @author Dave Syer */ public interface BackOffPolicy { /** - * Start a new block of back off operations. Implementations can choose to - * pause when this method is called, but normally it returns immediately. - * + * Start a new block of back off operations. Implementations can choose to pause when + * this method is called, but normally it returns immediately. * @param context the {@link RetryContext} context, which might contain information * that we can use to decide how to proceed. * @return the implementation-specific {@link BackOffContext} or 'null'. @@ -52,11 +51,9 @@ public interface BackOffPolicy { /** * Back off/pause in an implementation-specific fashion. The passed in - * {@link BackOffContext} corresponds to the one created by the call to - * {@link #start} for a given retry operation set. - * - * @throws BackOffInterruptedException if the attempt at back off is - * interrupted. + * {@link BackOffContext} corresponds to the one created by the call to {@link #start} + * for a given retry operation set. + * @throws BackOffInterruptedException if the attempt at back off is interrupted. * @param backOffContext the {@link BackOffContext} */ void backOff(BackOffContext backOffContext) throws BackOffInterruptedException; diff --git a/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java index ea6984b..2b73f2f 100644 --- a/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/ExponentialBackOffPolicy.java @@ -42,6 +42,7 @@ 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. @@ -104,7 +105,6 @@ public class ExponentialBackOffPolicy /** * Set the initial sleep interval value. Default is {@code 100} millisecond. Cannot be * set to a value less than one. - * * @param initialInterval the initial interval */ public void setInitialInterval(long initialInterval) { @@ -125,7 +125,6 @@ public class ExponentialBackOffPolicy * be reset to 1 if this method is called with a value less than 1. Set this to avoid * infinite waits if backing off a large number of times (or if the multiplier is set * too high). - * * @param maxInterval in milliseconds. */ public void setMaxInterval(long maxInterval) { @@ -142,7 +141,6 @@ public class ExponentialBackOffPolicy /** * The maximum interval to sleep for. Defaults to 30 seconds. - * * @return the maximum interval. */ public long getMaxInterval() { @@ -151,7 +149,6 @@ public class ExponentialBackOffPolicy /** * The multiplier to use to generate the next backoff interval from the last. - * * @return the multiplier in use */ public double getMultiplier() { @@ -226,6 +223,7 @@ public class ExponentialBackOffPolicy public long getMaxInterval() { return maxInterval; } + } public String toString() { diff --git a/src/main/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicy.java index 6e16d41..ced2f62 100644 --- a/src/main/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicy.java @@ -38,11 +38,13 @@ import java.util.Random; * * {@link ExponentialRandomBackOffPolicy} may yield [76, 151, 304, 580, 901] or [53, 190, * 267, 451, 815] + * * @author Jon Travis * @author Dave Syer */ @SuppressWarnings("serial") public class ExponentialRandomBackOffPolicy extends ExponentialBackOffPolicy { + /** * Returns a new instance of {@link org.springframework.retry.backoff.BackOffContext}, * seeded with this policies settings. @@ -58,6 +60,7 @@ public class ExponentialRandomBackOffPolicy extends ExponentialBackOffPolicy { static class ExponentialRandomBackOffContext extends ExponentialBackOffPolicy.ExponentialBackOffContext { + private final Random r = new Random(); public ExponentialRandomBackOffContext(long expSeed, double multiplier, @@ -73,4 +76,5 @@ public class ExponentialRandomBackOffPolicy extends ExponentialBackOffPolicy { } } + } diff --git a/src/main/java/org/springframework/retry/backoff/FixedBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/FixedBackOffPolicy.java index 5b884f1..450b6c9 100644 --- a/src/main/java/org/springframework/retry/backoff/FixedBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/FixedBackOffPolicy.java @@ -28,8 +28,8 @@ package org.springframework.retry.backoff; * @author Dave Syer * @author Artem Bilan */ -public class FixedBackOffPolicy extends StatelessBackOffPolicy implements - SleepingBackOffPolicy { +public class FixedBackOffPolicy extends StatelessBackOffPolicy + implements SleepingBackOffPolicy { /** * Default back off period - 1000ms. @@ -90,4 +90,5 @@ public class FixedBackOffPolicy extends StatelessBackOffPolicy implements public String toString() { return "FixedBackOffPolicy[backOffPeriod=" + backOffPeriod + "]"; } + } diff --git a/src/main/java/org/springframework/retry/backoff/NoBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/NoBackOffPolicy.java index fc89746..f894ed8 100644 --- a/src/main/java/org/springframework/retry/backoff/NoBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/NoBackOffPolicy.java @@ -16,11 +16,10 @@ package org.springframework.retry.backoff; - /** - * Implementation of {@link BackOffPolicy} that performs a no-op and as such all - * retry operation in a given set proceed one after the other with no pause. - * + * Implementation of {@link BackOffPolicy} that performs a no-op and as such all retry + * operation in a given set proceed one after the other with no pause. + * * @author Rob Harrop * @since 2.1 */ diff --git a/src/main/java/org/springframework/retry/backoff/ObjectWaitSleeper.java b/src/main/java/org/springframework/retry/backoff/ObjectWaitSleeper.java index c9b0fe0..a467419 100644 --- a/src/main/java/org/springframework/retry/backoff/ObjectWaitSleeper.java +++ b/src/main/java/org/springframework/retry/backoff/ObjectWaitSleeper.java @@ -17,8 +17,8 @@ package org.springframework.retry.backoff; /** * Simple {@link Sleeper} implementation that just waits on a local Object. - * @deprecated in favor of {@link org.springframework.retry.backoff.ThreadWaitSleeper} * + * @deprecated in favor of {@link org.springframework.retry.backoff.ThreadWaitSleeper} * @author Dave Syer * */ @@ -28,6 +28,7 @@ public class ObjectWaitSleeper implements Sleeper { /* * (non-Javadoc) + * * @see org.springframework.batch.retry.backoff.Sleeper#sleep(long) */ public void sleep(long backOffPeriod) throws InterruptedException { diff --git a/src/main/java/org/springframework/retry/backoff/Sleeper.java b/src/main/java/org/springframework/retry/backoff/Sleeper.java index e64cda7..265ef0a 100644 --- a/src/main/java/org/springframework/retry/backoff/Sleeper.java +++ b/src/main/java/org/springframework/retry/backoff/Sleeper.java @@ -19,15 +19,14 @@ import java.io.Serializable; /** * Strategy interface for backoff policies to delegate the pausing of execution. - * + * * @author Dave Syer - * + * */ public interface Sleeper extends Serializable { /** * Pause for the specified period using whatever means available. - * * @param backOffPeriod the backoff period * @throws InterruptedException the exception when interrupted */ diff --git a/src/main/java/org/springframework/retry/backoff/SleepingBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/SleepingBackOffPolicy.java index c18d0c5..5b0ebc1 100644 --- a/src/main/java/org/springframework/retry/backoff/SleepingBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/SleepingBackOffPolicy.java @@ -20,13 +20,15 @@ package org.springframework.retry.backoff; * A interface which can be mixed in by {@link BackOffPolicy}s indicating that they sleep * when backing off. */ -public interface SleepingBackOffPolicy> extends BackOffPolicy { - /** - * Clone the policy and return a new policy which uses the passed sleeper. - * - * @param sleeper Target to be invoked any time the backoff policy sleeps - * @return a clone of this policy which will have all of its backoff sleeps - * routed into the passed sleeper - */ - T withSleeper(Sleeper sleeper); +public interface SleepingBackOffPolicy> + extends BackOffPolicy { + + /** + * Clone the policy and return a new policy which uses the passed sleeper. + * @param sleeper Target to be invoked any time the backoff policy sleeps + * @return a clone of this policy which will have all of its backoff sleeps routed + * into the passed sleeper + */ + T withSleeper(Sleeper sleeper); + } diff --git a/src/main/java/org/springframework/retry/backoff/StatelessBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/StatelessBackOffPolicy.java index 3a16170..01ac2ae 100644 --- a/src/main/java/org/springframework/retry/backoff/StatelessBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/StatelessBackOffPolicy.java @@ -19,26 +19,26 @@ package org.springframework.retry.backoff; import org.springframework.retry.RetryContext; /** - * Simple base class for {@link BackOffPolicy} implementations that maintain no - * state across invocations. - * + * Simple base class for {@link BackOffPolicy} implementations that maintain no state + * across invocations. + * * @author Rob Harrop * @author Dave Syer */ public abstract class StatelessBackOffPolicy implements BackOffPolicy { /** - * Delegates directly to the {@link #doBackOff()} method without passing on - * the {@link BackOffContext} argument which is not needed for stateless - * implementations. + * Delegates directly to the {@link #doBackOff()} method without passing on the + * {@link BackOffContext} argument which is not needed for stateless implementations. */ - public final void backOff(BackOffContext backOffContext) throws BackOffInterruptedException { + public final void backOff(BackOffContext backOffContext) + throws BackOffInterruptedException { doBackOff(); } /** - * Returns 'null'. Subclasses can add behaviour, e.g. - * initial sleep before first attempt. + * Returns 'null'. Subclasses can add behaviour, e.g. initial sleep + * before first attempt. */ public BackOffContext start(RetryContext status) { return null; @@ -48,4 +48,5 @@ public abstract class StatelessBackOffPolicy implements BackOffPolicy { * Sub-classes should implement this method to perform the actual back off. */ protected abstract void doBackOff() throws BackOffInterruptedException; + } diff --git a/src/main/java/org/springframework/retry/backoff/ThreadWaitSleeper.java b/src/main/java/org/springframework/retry/backoff/ThreadWaitSleeper.java index ee2c04a..f5b9b4a 100644 --- a/src/main/java/org/springframework/retry/backoff/ThreadWaitSleeper.java +++ b/src/main/java/org/springframework/retry/backoff/ThreadWaitSleeper.java @@ -17,7 +17,8 @@ package org.springframework.retry.backoff; /** - * Simple {@link Sleeper} implementation that just blocks the current Thread with sleep period. + * Simple {@link Sleeper} implementation that just blocks the current Thread with sleep + * period. * * @author Artem Bilan * @since 1.1 diff --git a/src/main/java/org/springframework/retry/backoff/UniformRandomBackOffPolicy.java b/src/main/java/org/springframework/retry/backoff/UniformRandomBackOffPolicy.java index 5ba464a..641b40d 100644 --- a/src/main/java/org/springframework/retry/backoff/UniformRandomBackOffPolicy.java +++ b/src/main/java/org/springframework/retry/backoff/UniformRandomBackOffPolicy.java @@ -18,20 +18,19 @@ package org.springframework.retry.backoff; import java.util.Random; - /** - * Implementation of {@link BackOffPolicy} that pauses for a random period of - * time before continuing. A pause is implemented using {@link Sleeper#sleep(long)}. + * Implementation of {@link BackOffPolicy} that pauses for a random period of time before + * continuing. A pause is implemented using {@link Sleeper#sleep(long)}. * * {@link #setMinBackOffPeriod(long)} is thread-safe and it is safe to call - * {@link #setMaxBackOffPeriod(long)} during execution from multiple threads, however - * this may cause a single retry operation to have pauses of different - * intervals. + * {@link #setMaxBackOffPeriod(long)} during execution from multiple threads, however this + * may cause a single retry operation to have pauses of different intervals. * * @author Rob Harrop * @author Dave Syer */ -public class UniformRandomBackOffPolicy extends StatelessBackOffPolicy implements SleepingBackOffPolicy { +public class UniformRandomBackOffPolicy extends StatelessBackOffPolicy + implements SleepingBackOffPolicy { /** * Default min back off period - 500ms. @@ -51,12 +50,12 @@ public class UniformRandomBackOffPolicy extends StatelessBackOffPolicy implement private Sleeper sleeper = new ThreadWaitSleeper(); - public UniformRandomBackOffPolicy withSleeper(Sleeper sleeper) { - UniformRandomBackOffPolicy res = new UniformRandomBackOffPolicy(); - res.setMinBackOffPeriod(minBackOffPeriod); - res.setSleeper(sleeper); - return res; - } + public UniformRandomBackOffPolicy withSleeper(Sleeper sleeper) { + UniformRandomBackOffPolicy res = new UniformRandomBackOffPolicy(); + res.setMinBackOffPeriod(minBackOffPeriod); + res.setSleeper(sleeper); + return res; + } /** * Public setter for the {@link Sleeper} strategy. @@ -67,9 +66,8 @@ public class UniformRandomBackOffPolicy extends StatelessBackOffPolicy implement } /** - * Set the minimum back off period in milliseconds. Cannot be < 1. Default value - * is 500ms. - * + * Set the minimum back off period in milliseconds. Cannot be < 1. Default value is + * 500ms. * @param backOffPeriod the backoff period */ public void setMinBackOffPeriod(long backOffPeriod) { @@ -85,8 +83,8 @@ public class UniformRandomBackOffPolicy extends StatelessBackOffPolicy implement } /** - * Set the maximum back off period in milliseconds. Cannot be < 1. Default value - * is 1500ms. + * Set the maximum back off period in milliseconds. Cannot be < 1. Default value is + * 1500ms. * @param backOffPeriod the back off period */ public void setMaxBackOffPeriod(long backOffPeriod) { @@ -107,15 +105,18 @@ public class UniformRandomBackOffPolicy extends StatelessBackOffPolicy implement */ protected void doBackOff() throws BackOffInterruptedException { try { - long delta = maxBackOffPeriod==minBackOffPeriod ? 0 : random.nextInt((int) (maxBackOffPeriod - minBackOffPeriod)); - sleeper.sleep(minBackOffPeriod + delta ); + long delta = maxBackOffPeriod == minBackOffPeriod ? 0 + : random.nextInt((int) (maxBackOffPeriod - minBackOffPeriod)); + sleeper.sleep(minBackOffPeriod + delta); } catch (InterruptedException e) { throw new BackOffInterruptedException("Thread interrupted while sleeping", e); } } - public String toString() { - return "RandomBackOffPolicy[backOffPeriod=" + minBackOffPeriod + ", " + maxBackOffPeriod + "]"; - } + public String toString() { + return "RandomBackOffPolicy[backOffPeriod=" + minBackOffPeriod + ", " + + maxBackOffPeriod + "]"; + } + } diff --git a/src/main/java/org/springframework/retry/context/RetryContextSupport.java b/src/main/java/org/springframework/retry/context/RetryContextSupport.java index d692239..d5b61ce 100644 --- a/src/main/java/org/springframework/retry/context/RetryContextSupport.java +++ b/src/main/java/org/springframework/retry/context/RetryContextSupport.java @@ -24,7 +24,8 @@ import org.springframework.retry.RetryPolicy; * @author Dave Syer */ @SuppressWarnings("serial") -public class RetryContextSupport extends AttributeAccessorSupport implements RetryContext { +public class RetryContextSupport extends AttributeAccessorSupport + implements RetryContext { private final RetryContext parent; @@ -60,18 +61,16 @@ public class RetryContextSupport extends AttributeAccessorSupport implements Ret } /** - * Set the exception for the public interface {@link RetryContext}, and - * also increment the retry count if the throwable is non-null. + * Set the exception for the public interface {@link RetryContext}, and also increment + * the retry count if the throwable is non-null. * - * All {@link RetryPolicy} implementations should use this method when they - * register the throwable. It should only be called once per retry attempt - * because it increments a counter. + * All {@link RetryPolicy} implementations should use this method when they register + * the throwable. It should only be called once per retry attempt because it + * increments a counter. * - * Use of this method is not enforced by the framework - it is a service - * provider contract for authors of policies. - * - * @param throwable the exception that caused the current retry attempt to - * fail. + * Use of this method is not enforced by the framework - it is a service provider + * contract for authors of policies. + * @param throwable the exception that caused the current retry attempt to fail. */ public void registerThrowable(Throwable throwable) { this.lastException = throwable; @@ -81,7 +80,8 @@ public class RetryContextSupport extends AttributeAccessorSupport implements Ret @Override public String toString() { - return String.format("[RetryContext: count=%d, lastException=%s, exhausted=%b]", count, lastException, terminate); + return String.format("[RetryContext: count=%d, lastException=%s, exhausted=%b]", + count, lastException, terminate); } } diff --git a/src/main/java/org/springframework/retry/interceptor/MethodArgumentsKeyGenerator.java b/src/main/java/org/springframework/retry/interceptor/MethodArgumentsKeyGenerator.java index 0c7cab9..435c75d 100644 --- a/src/main/java/org/springframework/retry/interceptor/MethodArgumentsKeyGenerator.java +++ b/src/main/java/org/springframework/retry/interceptor/MethodArgumentsKeyGenerator.java @@ -16,8 +16,7 @@ package org.springframework.retry.interceptor; /** - * Interface that allows method parameters to be identified and tagged by a - * unique key. + * Interface that allows method parameters to be identified and tagged by a unique key. * * @author Dave Syer * @@ -25,9 +24,8 @@ package org.springframework.retry.interceptor; public interface MethodArgumentsKeyGenerator { /** - * Get a unique identifier for the item that can be used to cache it between - * calls if necessary, and then identify it later. - * + * Get a unique identifier for the item that can be used to cache it between calls if + * necessary, and then identify it later. * @param item the current method arguments (may be null if there are none). * @return a unique identifier. */ diff --git a/src/main/java/org/springframework/retry/interceptor/MethodInvocationRecoverer.java b/src/main/java/org/springframework/retry/interceptor/MethodInvocationRecoverer.java index ebe46b2..25ac910 100644 --- a/src/main/java/org/springframework/retry/interceptor/MethodInvocationRecoverer.java +++ b/src/main/java/org/springframework/retry/interceptor/MethodInvocationRecoverer.java @@ -16,25 +16,21 @@ package org.springframework.retry.interceptor; - /** * Strategy interface for recovery action when processing of an item fails. - * + * * @author Dave Syer */ public interface MethodInvocationRecoverer { /** - * Recover gracefully from an error. Clients can call this if processing of - * the item throws an unexpected exception. Caller can use the return value - * to decide whether to try more corrective action or perhaps throw an - * exception. - * - * @param args - * the arguments for the method invocation that failed. - * @param cause - * the cause of the failure that led to this recovery. + * Recover gracefully from an error. Clients can call this if processing of the item + * throws an unexpected exception. Caller can use the return value to decide whether + * to try more corrective action or perhaps throw an exception. + * @param args the arguments for the method invocation that failed. + * @param cause the cause of the failure that led to this recovery. * @return the value to be returned to the caller */ T recover(Object[] args, Throwable cause); + } diff --git a/src/main/java/org/springframework/retry/interceptor/NewMethodArgumentsIdentifier.java b/src/main/java/org/springframework/retry/interceptor/NewMethodArgumentsIdentifier.java index 2d5c0c6..6c28831 100644 --- a/src/main/java/org/springframework/retry/interceptor/NewMethodArgumentsIdentifier.java +++ b/src/main/java/org/springframework/retry/interceptor/NewMethodArgumentsIdentifier.java @@ -17,18 +17,17 @@ package org.springframework.retry.interceptor; /** - * Strategy interface to distinguish new arguments from ones that have been - * processed before, e.g. by examining a message flag. - * + * Strategy interface to distinguish new arguments from ones that have been processed + * before, e.g. by examining a message flag. + * * @author Dave Syer - * + * */ public interface NewMethodArgumentsIdentifier { /** - * Inspect the arguments and determine if they have never been processed - * before. The safest choice when the answer is indeterminate is 'false'. - * + * Inspect the arguments and determine if they have never been processed before. The + * safest choice when the answer is indeterminate is 'false'. * @param args the current method arguments. * @return true if the item is known to have never been processed before. */ diff --git a/src/main/java/org/springframework/retry/interceptor/RetryInterceptorBuilder.java b/src/main/java/org/springframework/retry/interceptor/RetryInterceptorBuilder.java index 4556466..74a4b7a 100644 --- a/src/main/java/org/springframework/retry/interceptor/RetryInterceptorBuilder.java +++ b/src/main/java/org/springframework/retry/interceptor/RetryInterceptorBuilder.java @@ -47,7 +47,6 @@ import org.springframework.util.Assert; * @author Gary Russell * @author Artem Bilan * @since 1.1 - * * @param The type of {@link org.aopalliance.intercept.MethodInterceptor} returned by * the builder's {@link #build()} method. */ @@ -109,8 +108,8 @@ public abstract class RetryInterceptorBuilder { } /** - * Apply the max attempts - a SimpleRetryPolicy will be used. Cannot be used if a custom retry operations - * or retry policy has been set. + * Apply the max attempts - a SimpleRetryPolicy will be used. Cannot be used if a + * custom retry operations or retry policy has been set. * @param maxAttempts the max attempts (including the initial attempt). * @return this. */ @@ -345,7 +344,8 @@ public abstract class RetryInterceptorBuilder { return this; } - public CircuitBreakerInterceptorBuilder keyGenerator(MethodArgumentsKeyGenerator keyGenerator) { + public CircuitBreakerInterceptorBuilder keyGenerator( + MethodArgumentsKeyGenerator keyGenerator) { this.keyGenerator = keyGenerator; return this; } diff --git a/src/main/java/org/springframework/retry/interceptor/RetryOperationsInterceptor.java b/src/main/java/org/springframework/retry/interceptor/RetryOperationsInterceptor.java index 58fff7e..7677eca 100644 --- a/src/main/java/org/springframework/retry/interceptor/RetryOperationsInterceptor.java +++ b/src/main/java/org/springframework/retry/interceptor/RetryOperationsInterceptor.java @@ -69,7 +69,8 @@ public class RetryOperationsInterceptor implements MethodInterceptor { String name; if (StringUtils.hasText(label)) { name = label; - } else { + } + else { name = invocation.getMethod().toGenericString(); } final String label = name; @@ -77,7 +78,7 @@ public class RetryOperationsInterceptor implements MethodInterceptor { RetryCallback retryCallback = new RetryCallback() { public Object doWithRetry(RetryContext context) throws Exception { - + context.setAttribute(RetryContext.NAME, label); /* @@ -88,7 +89,8 @@ public class RetryOperationsInterceptor implements MethodInterceptor { */ if (invocation instanceof ProxyMethodInvocation) { try { - return ((ProxyMethodInvocation) invocation).invocableClone().proceed(); + return ((ProxyMethodInvocation) invocation).invocableClone() + .proceed(); } catch (Exception e) { throw e; @@ -102,8 +104,8 @@ public class RetryOperationsInterceptor implements MethodInterceptor { } else { throw new IllegalStateException( - "MethodInvocation of the wrong type detected - this should not happen with Spring AOP, " + - "so please raise an issue if you see this exception"); + "MethodInvocation of the wrong type detected - this should not happen with Spring AOP, " + + "so please raise an issue if you see this exception"); } } @@ -132,7 +134,8 @@ public class RetryOperationsInterceptor implements MethodInterceptor { /** * @param args the item that failed. */ - private ItemRecovererCallback(Object[] args, MethodInvocationRecoverer recoverer) { + private ItemRecovererCallback(Object[] args, + MethodInvocationRecoverer recoverer) { this.args = Arrays.asList(args).toArray(); this.recoverer = recoverer; } diff --git a/src/main/java/org/springframework/retry/interceptor/StatefulRetryOperationsInterceptor.java b/src/main/java/org/springframework/retry/interceptor/StatefulRetryOperationsInterceptor.java index 07210ba..990ba63 100644 --- a/src/main/java/org/springframework/retry/interceptor/StatefulRetryOperationsInterceptor.java +++ b/src/main/java/org/springframework/retry/interceptor/StatefulRetryOperationsInterceptor.java @@ -98,7 +98,6 @@ public class StatefulRetryOperationsInterceptor implements MethodInterceptor { /** * Rollback classifier for the retry state. Default to null (meaning rollback for * all). - * * @param rollbackClassifier the rollbackClassifier to set */ public void setRollbackClassifier( @@ -128,8 +127,7 @@ public class StatefulRetryOperationsInterceptor implements MethodInterceptor { /** * Set to true to use the raw key generated by the key generator. Should only be set * to true for cases where the key is guaranteed to be unique in all cases. When - * false, a compound key is used, including invocation metadata. - * Default: false. + * false, a compound key is used, including invocation metadata. Default: false. * @param useRawKey the useRawKey to set. */ public void setUseRawKey(boolean useRawKey) { @@ -210,6 +208,7 @@ public class StatefulRetryOperationsInterceptor implements MethodInterceptor { implements RetryCallback { private final MethodInvocation invocation; + private String label; private MethodInvocationRetryCallback(MethodInvocation invocation, String label) { @@ -238,6 +237,7 @@ public class StatefulRetryOperationsInterceptor implements MethodInterceptor { throw new IllegalStateException(e); } } + } /** diff --git a/src/main/java/org/springframework/retry/listener/RetryListenerSupport.java b/src/main/java/org/springframework/retry/listener/RetryListenerSupport.java index 96e866c..7edbe0f 100644 --- a/src/main/java/org/springframework/retry/listener/RetryListenerSupport.java +++ b/src/main/java/org/springframework/retry/listener/RetryListenerSupport.java @@ -22,19 +22,22 @@ import org.springframework.retry.RetryListener; /** * Empty method implementation of {@link RetryListener}. - * + * * @author Dave Syer * */ public class RetryListenerSupport implements RetryListener { - public void close(RetryContext context, RetryCallback callback, Throwable throwable) { + public void close(RetryContext context, + RetryCallback callback, Throwable throwable) { } - public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { } - public boolean open(RetryContext context, RetryCallback callback) { + public boolean open(RetryContext context, + RetryCallback callback) { return true; } diff --git a/src/main/java/org/springframework/retry/policy/AlwaysRetryPolicy.java b/src/main/java/org/springframework/retry/policy/AlwaysRetryPolicy.java index 29609d4..7de829e 100644 --- a/src/main/java/org/springframework/retry/policy/AlwaysRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/AlwaysRetryPolicy.java @@ -20,18 +20,18 @@ import org.springframework.retry.RetryContext; import org.springframework.retry.RetryPolicy; /** - * A {@link RetryPolicy} that always permits a retry. Can also be used as a base - * class for other policies, e.g. for test purposes as a stub. - * + * A {@link RetryPolicy} that always permits a retry. Can also be used as a base class for + * other policies, e.g. for test purposes as a stub. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class AlwaysRetryPolicy extends NeverRetryPolicy { /** * Always returns true. - * + * * @see org.springframework.retry.RetryPolicy#canRetry(org.springframework.retry.RetryContext) */ public boolean canRetry(RetryContext context) { diff --git a/src/main/java/org/springframework/retry/policy/BinaryExceptionClassifierRetryPolicy.java b/src/main/java/org/springframework/retry/policy/BinaryExceptionClassifierRetryPolicy.java index 712dd92..69347a6 100644 --- a/src/main/java/org/springframework/retry/policy/BinaryExceptionClassifierRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/BinaryExceptionClassifierRetryPolicy.java @@ -20,12 +20,11 @@ import org.springframework.classify.BinaryExceptionClassifier; import org.springframework.retry.RetryContext; import org.springframework.retry.RetryPolicy; import org.springframework.retry.context.RetryContextSupport; -import org.springframework.util.ClassUtils; /** - * A policy, that is based on {@link BinaryExceptionClassifier}. - * Usually, binary classification is enough for retry purposes. If you need more flexible classification, use - * {@link ExceptionClassifierRetryPolicy}. + * A policy, that is based on {@link BinaryExceptionClassifier}. Usually, binary + * classification is enough for retry purposes. If you need more flexible classification, + * use {@link ExceptionClassifierRetryPolicy}. * * @author Aleksandr Shamukov */ @@ -34,7 +33,8 @@ public class BinaryExceptionClassifierRetryPolicy implements RetryPolicy { private final BinaryExceptionClassifier exceptionClassifier; - public BinaryExceptionClassifierRetryPolicy(BinaryExceptionClassifier exceptionClassifier) { + public BinaryExceptionClassifierRetryPolicy( + BinaryExceptionClassifier exceptionClassifier) { this.exceptionClassifier = exceptionClassifier; } @@ -62,4 +62,5 @@ public class BinaryExceptionClassifierRetryPolicy implements RetryPolicy { public RetryContext open(RetryContext parent) { return new RetryContextSupport(parent); } + } diff --git a/src/main/java/org/springframework/retry/policy/CircuitBreakerRetryPolicy.java b/src/main/java/org/springframework/retry/policy/CircuitBreakerRetryPolicy.java index 33ed067..09cf150 100644 --- a/src/main/java/org/springframework/retry/policy/CircuitBreakerRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/CircuitBreakerRetryPolicy.java @@ -39,7 +39,9 @@ public class CircuitBreakerRetryPolicy implements RetryPolicy { private static Log logger = LogFactory.getLog(CircuitBreakerRetryPolicy.class); private final RetryPolicy delegate; + private long resetTimeout = 20000; + private long openTimeout = 5000; public CircuitBreakerRetryPolicy() { @@ -53,7 +55,6 @@ public class CircuitBreakerRetryPolicy implements RetryPolicy { /** * Timeout for resetting circuit in milliseconds. After the circuit opens it will * re-close after this time has elapsed and the context will be restarted. - * * @param timeout the timeout to set in milliseconds */ public void setResetTimeout(long timeout) { @@ -64,7 +65,6 @@ public class CircuitBreakerRetryPolicy implements RetryPolicy { * Timeout for tripping the open circuit. If the delegate policy cannot retry and the * time elapsed since the context was started is less than this window, then the * circuit is opened. - * * @param timeout the timeout to set in milliseconds */ public void setOpenTimeout(long timeout) { @@ -104,11 +104,17 @@ public class CircuitBreakerRetryPolicy implements RetryPolicy { } static class CircuitBreakerRetryContext extends RetryContextSupport { + private volatile RetryContext context; + private final RetryPolicy policy; + private volatile long start = System.currentTimeMillis(); + private final long timeout; + private final long openWindow; + private final AtomicInteger shortCircuitCount = new AtomicInteger(); public CircuitBreakerRetryContext(RetryContext parent, RetryPolicy policy, diff --git a/src/main/java/org/springframework/retry/policy/CompositeRetryPolicy.java b/src/main/java/org/springframework/retry/policy/CompositeRetryPolicy.java index 271d51e..1062822 100644 --- a/src/main/java/org/springframework/retry/policy/CompositeRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/CompositeRetryPolicy.java @@ -25,8 +25,8 @@ import org.springframework.retry.RetryPolicy; import org.springframework.retry.context.RetryContextSupport; /** - * A {@link RetryPolicy} that composes a list of other policies and delegates - * calls to them in order. + * A {@link RetryPolicy} that composes a list of other policies and delegates calls to + * them in order. * * @author Dave Syer * @author Michael Minella @@ -36,11 +36,11 @@ import org.springframework.retry.context.RetryContextSupport; public class CompositeRetryPolicy implements RetryPolicy { RetryPolicy[] policies = new RetryPolicy[0]; + private boolean optimistic = false; /** * Setter for optimistic. - * * @param optimistic should this retry policy be optimistic */ public void setOptimistic(boolean optimistic) { @@ -49,18 +49,15 @@ public class CompositeRetryPolicy implements RetryPolicy { /** * Setter for policies. - * - * @param policies the {@link RetryPolicy} policies + * @param policies the {@link RetryPolicy} policies */ public void setPolicies(RetryPolicy[] policies) { this.policies = Arrays.asList(policies).toArray(new RetryPolicy[policies.length]); } /** - * Delegate to the policies that were in operation when the context was - * created. If any of them cannot retry then return false, otherwise return - * true. - * + * Delegate to the policies that were in operation when the context was created. If + * any of them cannot retry then return false, otherwise return true. * @param context the {@link RetryContext} * @see org.springframework.retry.RetryPolicy#canRetry(org.springframework.retry.RetryContext) */ @@ -71,7 +68,7 @@ public class CompositeRetryPolicy implements RetryPolicy { boolean retryable = true; - if(this.optimistic) { + if (this.optimistic) { retryable = false; for (int i = 0; i < contexts.length; i++) { if (policies[i].canRetry(contexts[i])) { @@ -91,9 +88,9 @@ public class CompositeRetryPolicy implements RetryPolicy { } /** - * Delegate to the policies that were in operation when the context was - * created. If any of them fails to close the exception is propagated (and - * those later in the chain are closed before re-throwing). + * Delegate to the policies that were in operation when the context was created. If + * any of them fails to close the exception is propagated (and those later in the + * chain are closed before re-throwing). * * @see org.springframework.retry.RetryPolicy#close(org.springframework.retry.RetryContext) * @param context the {@link RetryContext} @@ -119,8 +116,8 @@ public class CompositeRetryPolicy implements RetryPolicy { } /** - * Creates a new context that copies the existing policies and keeps a list - * of the contexts from each one. + * Creates a new context that copies the existing policies and keeps a list of the + * contexts from each one. * * @see org.springframework.retry.RetryPolicy#open(RetryContext) */ @@ -134,8 +131,7 @@ public class CompositeRetryPolicy implements RetryPolicy { } /** - * Delegate to the policies that were in operation when the context was - * created. + * Delegate to the policies that were in operation when the context was created. * * @see org.springframework.retry.RetryPolicy#close(org.springframework.retry.RetryContext) */ @@ -150,11 +146,13 @@ public class CompositeRetryPolicy implements RetryPolicy { } private static class CompositeRetryContext extends RetryContextSupport { + RetryContext[] contexts; RetryPolicy[] policies; - public CompositeRetryContext(RetryContext parent, List contexts, RetryPolicy[] policies) { + public CompositeRetryContext(RetryContext parent, List contexts, + RetryPolicy[] policies) { super(parent); this.contexts = contexts.toArray(new RetryContext[contexts.size()]); this.policies = policies; diff --git a/src/main/java/org/springframework/retry/policy/ExceptionClassifierRetryPolicy.java b/src/main/java/org/springframework/retry/policy/ExceptionClassifierRetryPolicy.java index 295525f..ce1c8c6 100644 --- a/src/main/java/org/springframework/retry/policy/ExceptionClassifierRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/ExceptionClassifierRetryPolicy.java @@ -28,8 +28,8 @@ import org.springframework.retry.context.RetryContextSupport; import org.springframework.util.Assert; /** - * A {@link RetryPolicy} that dynamically adapts to one of a set of injected - * policies according to the value of the latest exception. + * A {@link RetryPolicy} that dynamically adapts to one of a set of injected policies + * according to the value of the latest exception. * * @author Dave Syer * @@ -37,27 +37,28 @@ import org.springframework.util.Assert; @SuppressWarnings("serial") public class ExceptionClassifierRetryPolicy implements RetryPolicy { - private Classifier exceptionClassifier = new ClassifierSupport(new NeverRetryPolicy()); + private Classifier exceptionClassifier = new ClassifierSupport( + new NeverRetryPolicy()); /** - * Setter for policy map used to create a classifier. Either this property - * or the exception classifier directly should be set, but not both. - * - * @param policyMap a map of Throwable class to {@link RetryPolicy} that - * will be used to create a {@link Classifier} to locate a policy. + * Setter for policy map used to create a classifier. Either this property or the + * exception classifier directly should be set, but not both. + * @param policyMap a map of Throwable class to {@link RetryPolicy} that will be used + * to create a {@link Classifier} to locate a policy. */ public void setPolicyMap(Map, RetryPolicy> policyMap) { - this.exceptionClassifier = new SubclassClassifier(policyMap, new NeverRetryPolicy()); + this.exceptionClassifier = new SubclassClassifier( + policyMap, new NeverRetryPolicy()); } /** - * Setter for an exception classifier. The classifier is responsible for - * translating exceptions to concrete retry policies. Either this property - * or the policy map should be used, but not both. - * + * Setter for an exception classifier. The classifier is responsible for translating + * exceptions to concrete retry policies. Either this property or the policy map + * should be used, but not both. * @param exceptionClassifier ExceptionClassifier to use */ - public void setExceptionClassifier(Classifier exceptionClassifier) { + public void setExceptionClassifier( + Classifier exceptionClassifier) { this.exceptionClassifier = exceptionClassifier; } @@ -82,13 +83,14 @@ public class ExceptionClassifierRetryPolicy implements RetryPolicy { } /** - * Create an active context that proxies a retry policy by choosing a target - * from the policy map. + * Create an active context that proxies a retry policy by choosing a target from the + * policy map. * * @see org.springframework.retry.RetryPolicy#open(RetryContext) */ public RetryContext open(RetryContext parent) { - return new ExceptionClassifierRetryContext(parent, exceptionClassifier).open(parent); + return new ExceptionClassifierRetryContext(parent, exceptionClassifier) + .open(parent); } /** @@ -103,7 +105,8 @@ public class ExceptionClassifierRetryPolicy implements RetryPolicy { ((RetryContextSupport) context).registerThrowable(throwable); } - private static class ExceptionClassifierRetryContext extends RetryContextSupport implements RetryPolicy { + private static class ExceptionClassifierRetryContext extends RetryContextSupport + implements RetryPolicy { final private Classifier exceptionClassifier; @@ -138,7 +141,8 @@ public class ExceptionClassifierRetryPolicy implements RetryPolicy { public void registerThrowable(RetryContext context, Throwable throwable) { policy = exceptionClassifier.classify(throwable); - Assert.notNull(policy, "Could not locate policy for exception=[" + throwable + "]."); + Assert.notNull(policy, + "Could not locate policy for exception=[" + throwable + "]."); this.context = getContext(policy, context.getParent()); policy.registerThrowable(this.context, throwable); } diff --git a/src/main/java/org/springframework/retry/policy/ExpressionRetryPolicy.java b/src/main/java/org/springframework/retry/policy/ExpressionRetryPolicy.java index b46d5e6..56e9fcd 100644 --- a/src/main/java/org/springframework/retry/policy/ExpressionRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/ExpressionRetryPolicy.java @@ -29,8 +29,8 @@ import org.springframework.retry.RetryContext; import org.springframework.util.Assert; /** - * Subclass of {@link SimpleRetryPolicy} that delegates to super.canRetry() and, - * if true, further evaluates an expression against the last thrown exception. + * Subclass of {@link SimpleRetryPolicy} that delegates to super.canRetry() and, if true, + * further evaluates an expression against the last thrown exception. * * @author Gary Russell * @since 1.2 @@ -60,7 +60,8 @@ public class ExpressionRetryPolicy extends SimpleRetryPolicy implements BeanFact */ public ExpressionRetryPolicy(String expressionString) { Assert.notNull(expressionString, "'expressionString' cannot be null"); - this.expression = new SpelExpressionParser().parseExpression(expressionString, PARSER_CONTEXT); + this.expression = new SpelExpressionParser().parseExpression(expressionString, + PARSER_CONTEXT); } /** @@ -70,7 +71,8 @@ public class ExpressionRetryPolicy extends SimpleRetryPolicy implements BeanFact * @param traverseCauses true to examine causes * @param expression the expression */ - public ExpressionRetryPolicy(int maxAttempts, Map, Boolean> retryableExceptions, + public ExpressionRetryPolicy(int maxAttempts, + Map, Boolean> retryableExceptions, boolean traverseCauses, Expression expression) { super(maxAttempts, retryableExceptions, traverseCauses); Assert.notNull(expression, "'expression' cannot be null"); @@ -85,11 +87,13 @@ public class ExpressionRetryPolicy extends SimpleRetryPolicy implements BeanFact * @param expressionString the expression. * @param defaultValue the default action */ - public ExpressionRetryPolicy(int maxAttempts, Map, Boolean> retryableExceptions, + public ExpressionRetryPolicy(int maxAttempts, + Map, Boolean> retryableExceptions, boolean traverseCauses, String expressionString, boolean defaultValue) { super(maxAttempts, retryableExceptions, traverseCauses, defaultValue); Assert.notNull(expressionString, "'expressionString' cannot be null"); - this.expression = new SpelExpressionParser().parseExpression(expressionString, PARSER_CONTEXT); + this.expression = new SpelExpressionParser().parseExpression(expressionString, + PARSER_CONTEXT); } @Override @@ -109,8 +113,8 @@ public class ExpressionRetryPolicy extends SimpleRetryPolicy implements BeanFact return super.canRetry(context); } else { - return super.canRetry(context) - && this.expression.getValue(this.evaluationContext, lastThrowable, Boolean.class); + return super.canRetry(context) && this.expression + .getValue(this.evaluationContext, lastThrowable, Boolean.class); } } diff --git a/src/main/java/org/springframework/retry/policy/MapRetryContextCache.java b/src/main/java/org/springframework/retry/policy/MapRetryContextCache.java index b2a67fd..b49c032 100644 --- a/src/main/java/org/springframework/retry/policy/MapRetryContextCache.java +++ b/src/main/java/org/springframework/retry/policy/MapRetryContextCache.java @@ -22,21 +22,22 @@ import java.util.Map; import org.springframework.retry.RetryContext; /** - * Map-based implementation of {@link RetryContextCache}. The map backing the - * cache of contexts is synchronized. - * + * Map-based implementation of {@link RetryContextCache}. The map backing the cache of + * contexts is synchronized. + * * @author Dave Syer */ public class MapRetryContextCache implements RetryContextCache { /** - * Default value for maximum capacity of the cache. This is set to a - * reasonably low value (4096) to avoid users inadvertently filling the - * cache with item keys that are inconsistent. + * Default value for maximum capacity of the cache. This is set to a reasonably low + * value (4096) to avoid users inadvertently filling the cache with item keys that are + * inconsistent. */ public static final int DEFAULT_CAPACITY = 4096; - private Map map = Collections.synchronizedMap(new HashMap()); + private Map map = Collections + .synchronizedMap(new HashMap()); private int capacity; @@ -56,12 +57,10 @@ public class MapRetryContextCache implements RetryContextCache { } /** - * Public setter for the capacity. Prevents the cache from growing - * unboundedly if items that fail are misidentified and two references to an - * identical item actually do not have the same key. This can happen when - * users implement equals and hashCode based on mutable fields, for - * instance. - * + * Public setter for the capacity. Prevents the cache from growing unboundedly if + * items that fail are misidentified and two references to an identical item actually + * do not have the same key. This can happen when users implement equals and hashCode + * based on mutable fields, for instance. * @param capacity the capacity to set */ public void setCapacity(int capacity) { @@ -78,9 +77,10 @@ public class MapRetryContextCache implements RetryContextCache { public void put(Object key, RetryContext context) { if (map.size() >= capacity) { - throw new RetryCacheCapacityExceededException("Retry cache capacity limit breached. " - + "Do you need to re-consider the implementation of the key generator, " - + "or the equals and hashCode of the items that failed?"); + throw new RetryCacheCapacityExceededException( + "Retry cache capacity limit breached. " + + "Do you need to re-consider the implementation of the key generator, " + + "or the equals and hashCode of the items that failed?"); } map.put(key, context); } @@ -88,4 +88,5 @@ public class MapRetryContextCache implements RetryContextCache { public void remove(Object key) { map.remove(key); } + } diff --git a/src/main/java/org/springframework/retry/policy/MaxAttemptsRetryPolicy.java b/src/main/java/org/springframework/retry/policy/MaxAttemptsRetryPolicy.java index ac1241d..8a6f85d 100644 --- a/src/main/java/org/springframework/retry/policy/MaxAttemptsRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/MaxAttemptsRetryPolicy.java @@ -22,16 +22,16 @@ import org.springframework.retry.context.RetryContextSupport; import org.springframework.retry.support.RetryTemplate; /** - * Simple retry policy that is aware only about attempt count and retries a fixed number of times. - * The number of attempts includes the initial try. + * Simple retry policy that is aware only about attempt count and retries a fixed number + * of times. The number of attempts includes the initial try. *

- * It is not recommended to use it directly, because usually exception classification is strongly - * recommended (to not retry on OutOfMemoryError, for example). + * It is not recommended to use it directly, because usually exception classification is + * strongly recommended (to not retry on OutOfMemoryError, for example). *

* For daily usage see {@link RetryTemplate#newBuilder()} *

- * Volatility of maxAttempts allows concurrent modification and does not require safe publication - * of new instance after construction. + * Volatility of maxAttempts allows concurrent modification and does not require safe + * publication of new instance after construction. */ @SuppressWarnings("serial") public class MaxAttemptsRetryPolicy implements RetryPolicy { @@ -44,8 +44,8 @@ public class MaxAttemptsRetryPolicy implements RetryPolicy { private volatile int maxAttempts; /** - * Create a {@link MaxAttemptsRetryPolicy} with the default number of retry - * attempts, retrying all throwables. + * Create a {@link MaxAttemptsRetryPolicy} with the default number of retry attempts, + * retrying all throwables. */ public MaxAttemptsRetryPolicy() { this.maxAttempts = DEFAULT_MAX_ATTEMPTS; @@ -63,7 +63,6 @@ public class MaxAttemptsRetryPolicy implements RetryPolicy { * Set the number of attempts before retries are exhausted. Includes the initial * attempt before the retries begin so, generally, will be {@code >= 1}. For example * setting this property to 3 means 3 attempts total (initial + 2 retries). - * * @param maxAttempts the maximum number of attempts including the initial attempt. */ public void setMaxAttempts(int maxAttempts) { @@ -72,7 +71,6 @@ public class MaxAttemptsRetryPolicy implements RetryPolicy { /** * The maximum number of attempts before failure. - * * @return the maximum number of attempts */ public int getMaxAttempts() { @@ -83,9 +81,8 @@ public class MaxAttemptsRetryPolicy implements RetryPolicy { * Test for retryable operation based on the status. * * @see RetryPolicy#canRetry(RetryContext) - * - * @return true if the last exception was retryable and the number of - * attempts so far is less than the limit. + * @return true if the last exception was retryable and the number of attempts so far + * is less than the limit. */ @Override public boolean canRetry(RetryContext context) { @@ -107,9 +104,8 @@ public class MaxAttemptsRetryPolicy implements RetryPolicy { } /** - * 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. + * 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 RetryPolicy#open(RetryContext) */ @@ -117,4 +113,5 @@ public class MaxAttemptsRetryPolicy implements RetryPolicy { public RetryContext open(RetryContext parent) { return new RetryContextSupport(parent); } + } diff --git a/src/main/java/org/springframework/retry/policy/NeverRetryPolicy.java b/src/main/java/org/springframework/retry/policy/NeverRetryPolicy.java index 61e8944..d54b5cf 100644 --- a/src/main/java/org/springframework/retry/policy/NeverRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/NeverRetryPolicy.java @@ -21,20 +21,19 @@ import org.springframework.retry.RetryPolicy; import org.springframework.retry.context.RetryContextSupport; /** - * A {@link RetryPolicy} that allows the first attempt but never permits a - * retry. Also be used as a base class for other policies, e.g. for test - * purposes as a stub. - * + * A {@link RetryPolicy} that allows the first attempt but never permits a retry. Also be + * used as a base class for other policies, e.g. for test purposes as a stub. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class NeverRetryPolicy implements RetryPolicy { /** - * Returns false after the first exception. So there is always one try, and - * then the retry is prevented. - * + * Returns false after the first exception. So there is always one try, and then the + * retry is prevented. + * * @see org.springframework.retry.RetryPolicy#canRetry(org.springframework.retry.RetryContext) */ public boolean canRetry(RetryContext context) { @@ -43,7 +42,7 @@ public class NeverRetryPolicy implements RetryPolicy { /** * Do nothing. - * + * * @see org.springframework.retry.RetryPolicy#close(org.springframework.retry.RetryContext) */ public void close(RetryContext context) { @@ -51,9 +50,9 @@ public class NeverRetryPolicy implements RetryPolicy { } /** - * Return a context that can respond to early termination requests, but does - * nothing else. - * + * Return a context that can respond to early termination requests, but does nothing + * else. + * * @see org.springframework.retry.RetryPolicy#open(RetryContext) */ public RetryContext open(RetryContext parent) { @@ -71,17 +70,17 @@ public class NeverRetryPolicy implements RetryPolicy { } /** - * Special context object for {@link NeverRetryPolicy}. Implements a flag - * with a similar function to {@link RetryContext#isExhaustedOnly()}, but - * kept separate so that if subclasses of {@link NeverRetryPolicy} need to - * they can modify the behaviour of - * {@link NeverRetryPolicy#canRetry(RetryContext)} without affecting + * Special context object for {@link NeverRetryPolicy}. Implements a flag with a + * similar function to {@link RetryContext#isExhaustedOnly()}, but kept separate so + * that if subclasses of {@link NeverRetryPolicy} need to they can modify the + * behaviour of {@link NeverRetryPolicy#canRetry(RetryContext)} without affecting * {@link RetryContext#isExhaustedOnly()}. - * + * * @author Dave Syer - * + * */ private static class NeverRetryContext extends RetryContextSupport { + private boolean finished = false; public NeverRetryContext(RetryContext parent) { @@ -95,6 +94,7 @@ public class NeverRetryPolicy implements RetryPolicy { public void setFinished() { this.finished = true; } + } } diff --git a/src/main/java/org/springframework/retry/policy/RetryCacheCapacityExceededException.java b/src/main/java/org/springframework/retry/policy/RetryCacheCapacityExceededException.java index 3c28957..686f89e 100644 --- a/src/main/java/org/springframework/retry/policy/RetryCacheCapacityExceededException.java +++ b/src/main/java/org/springframework/retry/policy/RetryCacheCapacityExceededException.java @@ -18,22 +18,20 @@ package org.springframework.retry.policy; import org.springframework.retry.RetryException; /** - * Exception that indicates that a cache limit was exceeded. This is often a - * sign of badly or inconsistently implemented hashCode, equals in failed items. - * Items can then fail repeatedly and appear different to the cache, so they get - * added over and over again until a limit is reached and this exception is - * thrown. Consult the documentation of the {@link RetryContextCache} in use to - * determine how to increase the limit if appropriate. - * + * Exception that indicates that a cache limit was exceeded. This is often a sign of badly + * or inconsistently implemented hashCode, equals in failed items. Items can then fail + * repeatedly and appear different to the cache, so they get added over and over again + * until a limit is reached and this exception is thrown. Consult the documentation of the + * {@link RetryContextCache} in use to determine how to increase the limit if appropriate. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class RetryCacheCapacityExceededException extends RetryException { /** * Constructs a new instance with a message. - * * @param message the message sent when creating the exception */ public RetryCacheCapacityExceededException(String message) { @@ -42,7 +40,6 @@ public class RetryCacheCapacityExceededException extends RetryException { /** * Constructs a new instance with a message and nested exception. - * * @param msg the exception message. * @param nested the nested exception */ diff --git a/src/main/java/org/springframework/retry/policy/RetryContextCache.java b/src/main/java/org/springframework/retry/policy/RetryContextCache.java index 14b7f9e..4d66efc 100644 --- a/src/main/java/org/springframework/retry/policy/RetryContextCache.java +++ b/src/main/java/org/springframework/retry/policy/RetryContextCache.java @@ -23,11 +23,10 @@ import org.springframework.retry.RetryContext; * retrieving {@link RetryContext} instances. A null key should never be passed in by the * caller, but if it is then implementations are free to discard the context instead of * saving it (null key means "no information"). - * + * * @author Dave Syer - * * @see MapRetryContextCache - * + * */ public interface RetryContextCache { diff --git a/src/main/java/org/springframework/retry/policy/SimpleRetryPolicy.java b/src/main/java/org/springframework/retry/policy/SimpleRetryPolicy.java index e7f518b..32631c6 100644 --- a/src/main/java/org/springframework/retry/policy/SimpleRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/SimpleRetryPolicy.java @@ -25,9 +25,8 @@ import org.springframework.retry.context.RetryContextSupport; import org.springframework.util.ClassUtils; /** - * Simple retry policy that retries a fixed number of times for a set of named - * exceptions (and subclasses). The number of attempts includes the initial try, - * so e.g. + * Simple retry policy that retries a fixed number of times for a set of named exceptions + * (and subclasses). The number of attempts includes the initial try, so e.g. * *

  * retryTemplate = new RetryTemplate(new SimpleRetryPolicy(3));
@@ -36,16 +35,16 @@ import org.springframework.util.ClassUtils;
  *
  * will execute the callback at least once, and as many as 3 times.
  *
- * Since version 1.3 it is not necessary to use this class. The same behaviour
- * can be achieved by constructing a {@link CompositeRetryPolicy} with {@link MaxAttemptsRetryPolicy}
- * and {@link BinaryExceptionClassifierRetryPolicy} inside, that is actually performed by:
- * 
 {@code:
+ * Since version 1.3 it is not necessary to use this class. The same behaviour can be
+ * achieved by constructing a {@link CompositeRetryPolicy} with
+ * {@link MaxAttemptsRetryPolicy} and {@link BinaryExceptionClassifierRetryPolicy} inside,
+ * that is actually performed by: 
 {@code:
  * RetryTemplate.newBuilder()
  *                  .maxAttempts(3)
  *                  .retryOn(Exception.class)
  *                  .build();
- * }
- * or by {@link org.springframework.retry.support.RetryTemplate#newDefaultInstance()} + * }
or by + * {@link org.springframework.retry.support.RetryTemplate#newDefaultInstance()} * * @author Dave Syer * @author Rob Harrop @@ -62,74 +61,74 @@ public class SimpleRetryPolicy implements RetryPolicy { private volatile int maxAttempts; - private BinaryExceptionClassifier retryableClassifier = new BinaryExceptionClassifier(false); + private BinaryExceptionClassifier retryableClassifier = new BinaryExceptionClassifier( + false); /** - * Create a {@link SimpleRetryPolicy} with the default number of retry - * attempts, retrying all exceptions. + * Create a {@link SimpleRetryPolicy} with the default number of retry attempts, + * retrying all exceptions. */ public SimpleRetryPolicy() { this(DEFAULT_MAX_ATTEMPTS, BinaryExceptionClassifier.newDefaultClassifier()); } /** - * Create a {@link SimpleRetryPolicy} with the specified number of retry - * attempts, retrying all exceptions. + * Create a {@link SimpleRetryPolicy} with the specified number of retry attempts, + * retrying all exceptions. */ public SimpleRetryPolicy(int maxAttempts) { this(maxAttempts, BinaryExceptionClassifier.newDefaultClassifier()); } /** - * Create a {@link SimpleRetryPolicy} with the specified number of retry - * attempts. - * + * Create a {@link SimpleRetryPolicy} with the specified number of retry attempts. * @param maxAttempts the maximum number of attempts * @param retryableExceptions the map of exceptions that are retryable */ - public SimpleRetryPolicy(int maxAttempts, Map, Boolean> retryableExceptions) { + public SimpleRetryPolicy(int maxAttempts, + Map, Boolean> retryableExceptions) { this(maxAttempts, retryableExceptions, false); } /** - * Create a {@link SimpleRetryPolicy} with the specified number of retry - * attempts. If traverseCauses is true, the exception causes will be traversed until - * a match is found. - * + * Create a {@link SimpleRetryPolicy} with the specified number of retry attempts. If + * traverseCauses is true, the exception causes will be traversed until a match is + * found. * @param maxAttempts the maximum number of attempts * @param retryableExceptions the map of exceptions that are retryable based on the * map value (true/false). * @param traverseCauses is this clause traversable */ - public SimpleRetryPolicy(int maxAttempts, Map, Boolean> retryableExceptions, + public SimpleRetryPolicy(int maxAttempts, + Map, Boolean> retryableExceptions, boolean traverseCauses) { this(maxAttempts, retryableExceptions, traverseCauses, false); } /** - * Create a {@link SimpleRetryPolicy} with the specified number of retry - * attempts. If traverseCauses is true, the exception causes will be traversed until - * a match is found. The default value indicates whether to retry or not for exceptions - * (or super classes) are not found in the map. - * + * Create a {@link SimpleRetryPolicy} with the specified number of retry attempts. If + * traverseCauses is true, the exception causes will be traversed until a match is + * found. The default value indicates whether to retry or not for exceptions (or super + * classes) are not found in the map. * @param maxAttempts the maximum number of attempts * @param retryableExceptions the map of exceptions that are retryable based on the * map value (true/false). * @param traverseCauses is this clause traversable * @param defaultValue the default action. */ - public SimpleRetryPolicy(int maxAttempts, Map, Boolean> retryableExceptions, + public SimpleRetryPolicy(int maxAttempts, + Map, Boolean> retryableExceptions, boolean traverseCauses, boolean defaultValue) { super(); this.maxAttempts = maxAttempts; - this.retryableClassifier = new BinaryExceptionClassifier(retryableExceptions, defaultValue); + this.retryableClassifier = new BinaryExceptionClassifier(retryableExceptions, + defaultValue); this.retryableClassifier.setTraverseCauses(traverseCauses); } /** - * Create a {@link SimpleRetryPolicy} with the specified number of retry - * attempts and provided exception classifier. - * + * Create a {@link SimpleRetryPolicy} with the specified number of retry attempts and + * provided exception classifier. * @param maxAttempts the maximum number of attempts * @param classifier custom exception classifier */ @@ -143,7 +142,6 @@ public class SimpleRetryPolicy implements RetryPolicy { * Set the number of attempts before retries are exhausted. Includes the initial * attempt before the retries begin so, generally, will be {@code >= 1}. For example * setting this property to 3 means 3 attempts total (initial + 2 retries). - * * @param maxAttempts the maximum number of attempts including the initial attempt. */ public void setMaxAttempts(int maxAttempts) { @@ -152,7 +150,6 @@ public class SimpleRetryPolicy implements RetryPolicy { /** * The maximum number of attempts before failure. - * * @return the maximum number of attempts */ public int getMaxAttempts() { @@ -163,14 +160,14 @@ public class SimpleRetryPolicy implements RetryPolicy { * Test for retryable operation based on the status. * * @see org.springframework.retry.RetryPolicy#canRetry(org.springframework.retry.RetryContext) - * - * @return true if the last exception was retryable and the number of - * attempts so far is less than the limit. + * @return true if the last exception was retryable and the number of attempts so far + * is less than the limit. */ @Override public boolean canRetry(RetryContext context) { Throwable t = context.getLastThrowable(); - return (t == null || retryForException(t)) && context.getRetryCount() < maxAttempts; + return (t == null || retryForException(t)) + && context.getRetryCount() < maxAttempts; } /** @@ -192,9 +189,8 @@ public class SimpleRetryPolicy implements RetryPolicy { } /** - * 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. + * 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.retry.RetryPolicy#open(RetryContext) */ @@ -204,17 +200,17 @@ public class SimpleRetryPolicy implements RetryPolicy { } private static class SimpleRetryContext extends RetryContextSupport { + public SimpleRetryContext(RetryContext parent) { super(parent); } + } /** * Delegates to an exception classifier. - * * @param ex - * @return true if this exception or its ancestors have been registered as - * retryable. + * @return true if this exception or its ancestors have been registered as retryable. */ private boolean retryForException(Throwable ex) { return retryableClassifier.classify(ex); @@ -224,4 +220,5 @@ public class SimpleRetryPolicy implements RetryPolicy { public String toString() { return ClassUtils.getShortName(getClass()) + "[maxAttempts=" + maxAttempts + "]"; } + } diff --git a/src/main/java/org/springframework/retry/policy/SoftReferenceMapRetryContextCache.java b/src/main/java/org/springframework/retry/policy/SoftReferenceMapRetryContextCache.java index cfb54f6..48165e6 100644 --- a/src/main/java/org/springframework/retry/policy/SoftReferenceMapRetryContextCache.java +++ b/src/main/java/org/springframework/retry/policy/SoftReferenceMapRetryContextCache.java @@ -23,20 +23,19 @@ import java.util.Map; import org.springframework.retry.RetryContext; /** - * Map-based implementation of {@link RetryContextCache}. The map backing the - * cache of contexts is synchronized and its entries are soft-referenced, so may - * be garbage collected under pressure. - * + * Map-based implementation of {@link RetryContextCache}. The map backing the cache of + * contexts is synchronized and its entries are soft-referenced, so may be garbage + * collected under pressure. + * * @see MapRetryContextCache for non-soft referenced version - * * @author Dave Syer */ public class SoftReferenceMapRetryContextCache implements RetryContextCache { /** - * Default value for maximum capacity of the cache. This is set to a - * reasonably low value (4096) to avoid users inadvertently filling the - * cache with item keys that are inconsistent. + * Default value for maximum capacity of the cache. This is set to a reasonably low + * value (4096) to avoid users inadvertently filling the cache with item keys that are + * inconsistent. */ public static final int DEFAULT_CAPACITY = 4096; @@ -61,12 +60,10 @@ public class SoftReferenceMapRetryContextCache implements RetryContextCache { } /** - * Public setter for the capacity. Prevents the cache from growing - * unboundedly if items that fail are misidentified and two references to an - * identical item actually do not have the same key. This can happen when - * users implement equals and hashCode based on mutable fields, for - * instance. - * + * Public setter for the capacity. Prevents the cache from growing unboundedly if + * items that fail are misidentified and two references to an identical item actually + * do not have the same key. This can happen when users implement equals and hashCode + * based on mutable fields, for instance. * @param capacity the capacity to set */ public void setCapacity(int capacity) { @@ -90,9 +87,10 @@ public class SoftReferenceMapRetryContextCache implements RetryContextCache { public void put(Object key, RetryContext context) { if (map.size() >= capacity) { - throw new RetryCacheCapacityExceededException("Retry cache capacity limit breached. " - + "Do you need to re-consider the implementation of the key generator, " - + "or the equals and hashCode of the items that failed?"); + throw new RetryCacheCapacityExceededException( + "Retry cache capacity limit breached. " + + "Do you need to re-consider the implementation of the key generator, " + + "or the equals and hashCode of the items that failed?"); } map.put(key, new SoftReference(context)); } @@ -100,4 +98,5 @@ public class SoftReferenceMapRetryContextCache implements RetryContextCache { public void remove(Object key) { map.remove(key); } + } diff --git a/src/main/java/org/springframework/retry/policy/TimeoutRetryPolicy.java b/src/main/java/org/springframework/retry/policy/TimeoutRetryPolicy.java index cdaeaa5..71fb4a4 100644 --- a/src/main/java/org/springframework/retry/policy/TimeoutRetryPolicy.java +++ b/src/main/java/org/springframework/retry/policy/TimeoutRetryPolicy.java @@ -21,11 +21,11 @@ import org.springframework.retry.RetryPolicy; import org.springframework.retry.context.RetryContextSupport; /** - * A {@link RetryPolicy} that allows a retry only if it hasn't timed out. The - * clock is started on a call to {@link #open(RetryContext)}. - * + * A {@link RetryPolicy} that allows a retry only if it hasn't timed out. The clock is + * started on a call to {@link #open(RetryContext)}. + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class TimeoutRetryPolicy implements RetryPolicy { @@ -44,10 +44,9 @@ public class TimeoutRetryPolicy implements RetryPolicy { public void setTimeout(long timeout) { this.timeout = timeout; } - + /** * The value of the timeout. - * * @return the timeout in milliseconds */ public long getTimeout() { @@ -55,9 +54,9 @@ public class TimeoutRetryPolicy implements RetryPolicy { } /** - * Only permits a retry if the timeout has not expired. Does not check the - * exception at all. - * + * Only permits a retry if the timeout has not expired. Does not check the exception + * at all. + * * @see org.springframework.retry.RetryPolicy#canRetry(org.springframework.retry.RetryContext) */ public boolean canRetry(RetryContext context) { @@ -77,6 +76,7 @@ public class TimeoutRetryPolicy implements RetryPolicy { } private static class TimeoutRetryContext extends RetryContextSupport { + private long timeout; private long start; @@ -90,6 +90,7 @@ public class TimeoutRetryPolicy implements RetryPolicy { public boolean isAlive() { return (System.currentTimeMillis() - start) <= timeout; } + } } diff --git a/src/main/java/org/springframework/retry/stats/DefaultRetryStatistics.java b/src/main/java/org/springframework/retry/stats/DefaultRetryStatistics.java index 3617161..949b9da 100644 --- a/src/main/java/org/springframework/retry/stats/DefaultRetryStatistics.java +++ b/src/main/java/org/springframework/retry/stats/DefaultRetryStatistics.java @@ -26,13 +26,19 @@ import org.springframework.retry.RetryStatistics; * */ @SuppressWarnings("serial") -public class DefaultRetryStatistics extends AttributeAccessorSupport implements RetryStatistics, MutableRetryStatistics { +public class DefaultRetryStatistics extends AttributeAccessorSupport + implements RetryStatistics, MutableRetryStatistics { private String name; + private AtomicInteger startedCount = new AtomicInteger(); + private AtomicInteger completeCount = new AtomicInteger(); + private AtomicInteger recoveryCount = new AtomicInteger(); + private AtomicInteger errorCount = new AtomicInteger(); + private AtomicInteger abortCount = new AtomicInteger(); DefaultRetryStatistics() { diff --git a/src/main/java/org/springframework/retry/stats/DefaultRetryStatisticsFactory.java b/src/main/java/org/springframework/retry/stats/DefaultRetryStatisticsFactory.java index 0b4e928..8dedb9d 100644 --- a/src/main/java/org/springframework/retry/stats/DefaultRetryStatisticsFactory.java +++ b/src/main/java/org/springframework/retry/stats/DefaultRetryStatisticsFactory.java @@ -23,7 +23,7 @@ package org.springframework.retry.stats; public class DefaultRetryStatisticsFactory implements RetryStatisticsFactory { private long window = 15000; - + /** * Window in milliseconds for exponential decay factor in rolling averages. * @param window the window to set @@ -34,7 +34,8 @@ public class DefaultRetryStatisticsFactory implements RetryStatisticsFactory { @Override public MutableRetryStatistics create(String name) { - ExponentialAverageRetryStatistics stats = new ExponentialAverageRetryStatistics(name); + ExponentialAverageRetryStatistics stats = new ExponentialAverageRetryStatistics( + name); stats.setWindow(window); return stats; } diff --git a/src/main/java/org/springframework/retry/stats/DefaultStatisticsRepository.java b/src/main/java/org/springframework/retry/stats/DefaultStatisticsRepository.java index 1a5cc86..e44911d 100644 --- a/src/main/java/org/springframework/retry/stats/DefaultStatisticsRepository.java +++ b/src/main/java/org/springframework/retry/stats/DefaultStatisticsRepository.java @@ -29,6 +29,7 @@ import org.springframework.retry.RetryStatistics; public class DefaultStatisticsRepository implements StatisticsRepository { private ConcurrentMap map = new ConcurrentHashMap(); + private RetryStatisticsFactory factory = new DefaultRetryStatisticsFactory(); public void setRetryStatisticsFactory(RetryStatisticsFactory factory) { diff --git a/src/main/java/org/springframework/retry/stats/ExponentialAverageRetryStatistics.java b/src/main/java/org/springframework/retry/stats/ExponentialAverageRetryStatistics.java index 4a1e1df..1eeaaaf 100644 --- a/src/main/java/org/springframework/retry/stats/ExponentialAverageRetryStatistics.java +++ b/src/main/java/org/springframework/retry/stats/ExponentialAverageRetryStatistics.java @@ -26,15 +26,15 @@ public class ExponentialAverageRetryStatistics extends DefaultRetryStatistics { private long window = 15000; private ExponentialAverage started; - + private ExponentialAverage error; - + private ExponentialAverage complete; - + private ExponentialAverage recovery; - + private ExponentialAverage abort; - + public ExponentialAverageRetryStatistics(String name) { super(name); init(); @@ -50,7 +50,6 @@ public class ExponentialAverageRetryStatistics extends DefaultRetryStatistics { /** * Window in milliseconds for exponential decay factor in rolling average. - * * @param window the window to set */ public void setWindow(long window) { @@ -65,32 +64,32 @@ public class ExponentialAverageRetryStatistics extends DefaultRetryStatistics { public int getRollingErrorCount() { return (int) Math.round(error.getValue()); } - + public int getRollingAbortCount() { return (int) Math.round(abort.getValue()); } - + public int getRollingRecoveryCount() { return (int) Math.round(recovery.getValue()); } - + public int getRollingCompleteCount() { return (int) Math.round(complete.getValue()); } - + public double getRollingErrorRate() { - if (Math.round(started.getValue())==0) { + if (Math.round(started.getValue()) == 0) { return 0.; } return (abort.getValue() + recovery.getValue()) / started.getValue(); } - + @Override public void incrementStartedCount() { super.incrementStartedCount(); started.increment(); } - + @Override public void incrementCompleteCount() { super.incrementCompleteCount(); @@ -118,9 +117,9 @@ public class ExponentialAverageRetryStatistics extends DefaultRetryStatistics { private class ExponentialAverage { private final double alpha; - + private volatile long lastTime = System.currentTimeMillis(); - + private volatile double value = 0; public ExponentialAverage(long window) { @@ -129,13 +128,13 @@ public class ExponentialAverageRetryStatistics extends DefaultRetryStatistics { public synchronized void increment() { long time = System.currentTimeMillis(); - value = value * Math.exp(-alpha*(time - lastTime)) + 1; + value = value * Math.exp(-alpha * (time - lastTime)) + 1; lastTime = time; } - + public double getValue() { long time = System.currentTimeMillis(); - return value * Math.exp(-alpha*(time - lastTime)); + return value * Math.exp(-alpha * (time - lastTime)); } } diff --git a/src/main/java/org/springframework/retry/stats/RetryStatisticsFactory.java b/src/main/java/org/springframework/retry/stats/RetryStatisticsFactory.java index d1e33d9..8781fb0 100644 --- a/src/main/java/org/springframework/retry/stats/RetryStatisticsFactory.java +++ b/src/main/java/org/springframework/retry/stats/RetryStatisticsFactory.java @@ -21,7 +21,7 @@ package org.springframework.retry.stats; * */ public interface RetryStatisticsFactory { - + MutableRetryStatistics create(String name); } diff --git a/src/main/java/org/springframework/retry/stats/StatisticsListener.java b/src/main/java/org/springframework/retry/stats/StatisticsListener.java index 4221dce..34cc82d 100644 --- a/src/main/java/org/springframework/retry/stats/StatisticsListener.java +++ b/src/main/java/org/springframework/retry/stats/StatisticsListener.java @@ -105,4 +105,5 @@ public class StatisticsListener extends RetryListenerSupport { private String getName(RetryContext context) { return (String) context.getAttribute(RetryContext.NAME); } + } diff --git a/src/main/java/org/springframework/retry/stats/StatisticsRepository.java b/src/main/java/org/springframework/retry/stats/StatisticsRepository.java index d5037ef..36a8399 100644 --- a/src/main/java/org/springframework/retry/stats/StatisticsRepository.java +++ b/src/main/java/org/springframework/retry/stats/StatisticsRepository.java @@ -25,11 +25,11 @@ import org.springframework.retry.RetryStatistics; public interface StatisticsRepository { RetryStatistics findOne(String name); - + Iterable findAll(); void addStarted(String name); - + void addError(String name); void addRecovery(String name); diff --git a/src/main/java/org/springframework/retry/support/DefaultRetryState.java b/src/main/java/org/springframework/retry/support/DefaultRetryState.java index 14e2daa..f6dac81 100644 --- a/src/main/java/org/springframework/retry/support/DefaultRetryState.java +++ b/src/main/java/org/springframework/retry/support/DefaultRetryState.java @@ -22,9 +22,8 @@ import org.springframework.retry.RetryOperations; import org.springframework.retry.RetryState; /** - * * @author Dave Syer - * + * */ public class DefaultRetryState implements RetryState { @@ -35,21 +34,18 @@ public class DefaultRetryState implements RetryState { final private Classifier rollbackClassifier; /** - * Create a {@link DefaultRetryState} representing the state for a new retry - * attempt. - * + * 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 - * (could not have previously failed) - * @param rollbackClassifier the rollback classifier to set. The rollback - * classifier answers true if the exception provided should cause a - * rollback. + * @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 (could not + * have previously failed) + * @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 rollbackClassifier) { + public DefaultRetryState(Object key, boolean forceRefresh, + Classifier rollbackClassifier) { this.key = key; this.forceRefresh = forceRefresh; this.rollbackClassifier = rollbackClassifier; @@ -61,7 +57,8 @@ public class DefaultRetryState implements RetryState { * @param key the key * @param rollbackClassifier the rollback {@link Classifier} */ - public DefaultRetryState(Object key, Classifier rollbackClassifier) { + public DefaultRetryState(Object key, + Classifier rollbackClassifier) { this(key, false, rollbackClassifier); } @@ -76,9 +73,7 @@ public class DefaultRetryState implements RetryState { } /** - * Defaults the force refresh flag (to false) and the rollback classifier - * (to null). - * + * Defaults the force refresh flag (to false) and the rollback classifier (to null). * @param key the key to use * @see DefaultRetryState#DefaultRetryState(Object, boolean, Classifier) */ @@ -88,7 +83,7 @@ public class DefaultRetryState implements RetryState { /* * (non-Javadoc) - * + * * @see org.springframework.batch.retry.IRetryState#getKey() */ public Object getKey() { @@ -97,7 +92,7 @@ public class DefaultRetryState implements RetryState { /* * (non-Javadoc) - * + * * @see org.springframework.batch.retry.IRetryState#isForceRefresh() */ public boolean isForceRefresh() { @@ -106,10 +101,8 @@ public class DefaultRetryState implements RetryState { /* * (non-Javadoc) - * - * @see - * org.springframework.batch.retry.RetryState#rollbackFor(java.lang.Throwable - * ) + * + * @see org.springframework.batch.retry.RetryState#rollbackFor(java.lang.Throwable ) */ public boolean rollbackFor(Throwable exception) { if (rollbackClassifier == null) { @@ -120,6 +113,8 @@ public class DefaultRetryState implements RetryState { @Override public String toString() { - return String.format("[%s: key=%s, forceRefresh=%b]", getClass().getSimpleName(), key, forceRefresh); + return String.format("[%s: key=%s, forceRefresh=%b]", getClass().getSimpleName(), + key, forceRefresh); } + } diff --git a/src/main/java/org/springframework/retry/support/RetrySimulation.java b/src/main/java/org/springframework/retry/support/RetrySimulation.java index 0651b19..2d8bff2 100644 --- a/src/main/java/org/springframework/retry/support/RetrySimulation.java +++ b/src/main/java/org/springframework/retry/support/RetrySimulation.java @@ -42,7 +42,8 @@ public class RetrySimulation { } /** - * @return Returns a list of all the unique sleep values which were executed within all simulations. + * @return Returns a list of all the unique sleep values which were executed within + * all simulations. */ public List getPercentiles() { List res = new ArrayList(); @@ -77,6 +78,7 @@ public class RetrySimulation { } public static class SleepSequence { + private final List sleeps; private final long longestSleep; @@ -111,5 +113,7 @@ public class RetrySimulation { public String toString() { return "totalSleep=" + totalSleep + ": " + sleeps.toString(); } + } + } diff --git a/src/main/java/org/springframework/retry/support/RetrySimulator.java b/src/main/java/org/springframework/retry/support/RetrySimulator.java index 0d969fe..cfc4ba9 100644 --- a/src/main/java/org/springframework/retry/support/RetrySimulator.java +++ b/src/main/java/org/springframework/retry/support/RetrySimulator.java @@ -28,94 +28,102 @@ import org.springframework.retry.backoff.SleepingBackOffPolicy; /** * A {@link RetrySimulator} is a tool for exercising retry + backoff operations. * - * When calibrating a set of retry + backoff pairs, it is useful to know the behaviour - * of the retry for various scenarios. + * When calibrating a set of retry + backoff pairs, it is useful to know the behaviour of + * the retry for various scenarios. * - * Things you may want to know: - * - Does a 'maxInterval' of 5000 ms in my backoff even matter? - * (This is often the case when retry counts are low -- so why set the max interval - * at something that cannot be achieved?) - * - What are the typical sleep durations for threads in a retry - * - What was the longest sleep duration for any retry sequence + * Things you may want to know: - Does a 'maxInterval' of 5000 ms in my backoff even + * matter? (This is often the case when retry counts are low -- so why set the max + * interval at something that cannot be achieved?) - What are the typical sleep durations + * for threads in a retry - What was the longest sleep duration for any retry sequence * - * The simulator provides this information by executing a retry + backoff pair until failure - * (that is all retries are exhausted). The information about each retry is provided - * as part of the {@link RetrySimulation}. + * The simulator provides this information by executing a retry + backoff pair until + * failure (that is all retries are exhausted). The information about each retry is + * provided as part of the {@link RetrySimulation}. * * Note that the impetus for this class was to expose the timings which are possible with - * {@link org.springframework.retry.backoff.ExponentialRandomBackOffPolicy}, which provides - * random values and must be looked at over a series of trials. + * {@link org.springframework.retry.backoff.ExponentialRandomBackOffPolicy}, which + * provides random values and must be looked at over a series of trials. * * @author Jon Travis */ public class RetrySimulator { private final SleepingBackOffPolicy backOffPolicy; - private final RetryPolicy retryPolicy; - public RetrySimulator(SleepingBackOffPolicy backOffPolicy, RetryPolicy retryPolicy) { - this.backOffPolicy = backOffPolicy; - this.retryPolicy = retryPolicy; - } + private final RetryPolicy retryPolicy; - /** - * Execute the simulator for a give # of iterations. - * - * @param numSimulations Number of simulations to run - * @return the outcome of all simulations - */ - public RetrySimulation executeSimulation(int numSimulations) { - RetrySimulation simulation = new RetrySimulation(); + public RetrySimulator(SleepingBackOffPolicy backOffPolicy, + RetryPolicy retryPolicy) { + this.backOffPolicy = backOffPolicy; + this.retryPolicy = retryPolicy; + } - for (int i=0; i executeSingleSimulation() { - StealingSleeper stealingSleeper = new StealingSleeper(); - SleepingBackOffPolicy stealingBackoff = backOffPolicy.withSleeper(stealingSleeper); + for (int i = 0; i < numSimulations; i++) { + simulation.addSequence(executeSingleSimulation()); + } + return simulation; + } - RetryTemplate template = new RetryTemplate(); - template.setBackOffPolicy(stealingBackoff); - template.setRetryPolicy(retryPolicy); + /** + * Execute a single simulation + * @return The sleeps which occurred within the single simulation. + */ + public List executeSingleSimulation() { + StealingSleeper stealingSleeper = new StealingSleeper(); + SleepingBackOffPolicy stealingBackoff = backOffPolicy + .withSleeper(stealingSleeper); - try { - template.execute(new FailingRetryCallback()); - } catch(FailingRetryException e) { + RetryTemplate template = new RetryTemplate(); + template.setBackOffPolicy(stealingBackoff); + template.setRetryPolicy(retryPolicy); - } catch(Throwable e) { - throw new RuntimeException("Unexpected exception", e); - } + try { + template.execute(new FailingRetryCallback()); + } + catch (FailingRetryException e) { - return stealingSleeper.getSleeps(); - } + } + catch (Throwable e) { + throw new RuntimeException("Unexpected exception", e); + } - static class FailingRetryCallback implements RetryCallback { - public Object doWithRetry(RetryContext context) throws Exception { - throw new FailingRetryException(); - } - } + return stealingSleeper.getSleeps(); + } - @SuppressWarnings("serial") + static class FailingRetryCallback implements RetryCallback { + + public Object doWithRetry(RetryContext context) throws Exception { + throw new FailingRetryException(); + } + + } + + @SuppressWarnings("serial") static class FailingRetryException extends Exception { - } - @SuppressWarnings("serial") + } + + @SuppressWarnings("serial") static class StealingSleeper implements Sleeper { - private final List sleeps = new ArrayList(); - public void sleep(long backOffPeriod) throws InterruptedException { - sleeps.add(backOffPeriod); - } + private final List sleeps = new ArrayList(); + + public void sleep(long backOffPeriod) throws InterruptedException { + sleeps.add(backOffPeriod); + } + + public List getSleeps() { + return sleeps; + } + + } - public List getSleeps() { - return sleeps; - } - } } diff --git a/src/main/java/org/springframework/retry/support/RetrySynchronizationManager.java b/src/main/java/org/springframework/retry/support/RetrySynchronizationManager.java index 1254f69..bc80d1a 100644 --- a/src/main/java/org/springframework/retry/support/RetrySynchronizationManager.java +++ b/src/main/java/org/springframework/retry/support/RetrySynchronizationManager.java @@ -21,27 +21,26 @@ import org.springframework.retry.RetryContext; import org.springframework.retry.RetryOperations; /** - * Global variable support for retry clients. Normally it is not necessary for - * clients to be aware of the surrounding environment because a - * {@link RetryCallback} can always use the context it is passed by the - * enclosing {@link RetryOperations}. But occasionally it might be helpful to - * have lower level access to the ongoing {@link RetryContext} so we provide a - * global accessor here. The mutator methods ({@link #clear()} and + * Global variable support for retry clients. Normally it is not necessary for clients to + * be aware of the surrounding environment because a {@link RetryCallback} can always use + * the context it is passed by the enclosing {@link RetryOperations}. But occasionally it + * might be helpful to have lower level access to the ongoing {@link RetryContext} so we + * provide a global accessor here. The mutator methods ({@link #clear()} and * {@link #register(RetryContext)} should not be used except internally by * {@link RetryOperations} implementations. - * + * * @author Dave Syer - * + * */ public final class RetrySynchronizationManager { - private RetrySynchronizationManager() {} + private RetrySynchronizationManager() { + } private static final ThreadLocal context = new ThreadLocal(); /** * Public accessor for the locally enclosing {@link RetryContext}. - * * @return the current retry context, or null if there isn't one */ public static RetryContext getContext() { @@ -50,10 +49,9 @@ public final class RetrySynchronizationManager { } /** - * Method for registering a context - should only be used by - * {@link RetryOperations} implementations to ensure that - * {@link #getContext()} always returns the correct value. - * + * Method for registering a context - should only be used by {@link RetryOperations} + * implementations to ensure that {@link #getContext()} always returns the correct + * value. * @param context the new context to register * @return the old context if there was one */ @@ -66,7 +64,6 @@ public final class RetrySynchronizationManager { /** * Clear the current context at the end of a batch - should only be used by * {@link RetryOperations} implementations. - * * @return the old value if there was one. */ public static RetryContext clear() { diff --git a/src/main/java/org/springframework/retry/support/RetryTemplate.java b/src/main/java/org/springframework/retry/support/RetryTemplate.java index ee3b6c5..feeaafb 100644 --- a/src/main/java/org/springframework/retry/support/RetryTemplate.java +++ b/src/main/java/org/springframework/retry/support/RetryTemplate.java @@ -57,14 +57,12 @@ import org.springframework.retry.policy.SimpleRetryPolicy; * properties. The {@link org.springframework.retry.backoff.BackOffPolicy} controls how * long the pause is between each individual retry attempt. *

- * A new instance can be fluently configured via {@link #newBuilder}, e.g: - *

 {@code
+ * A new instance can be fluently configured via {@link #newBuilder}, e.g: 
 {@code
  * RetryTemplate.newBuilder()
  *                 .maxAttempts(10)
  *                 .fixedBackoff(1000)
  *                 .build();
- * }
- * See {@link RetryTemplateBuilder} for more examples and details. + * }
See {@link RetryTemplateBuilder} for more examples and details. *

* This class is thread-safe and suitable for concurrent access when executing operations * and when performing configuration changes. As such, it is possible to change the number @@ -99,11 +97,10 @@ public class RetryTemplate implements RetryOperations { private boolean throwLastExceptionOnExhausted; /** - * Main entry point to configure RetryTemplate using fluent API. - * See {@link RetryTemplateBuilder} for usage examples and details. - * - * @return a new instance of RetryTemplateBuilder with preset default behaviour, that can be overwritten during - * manual configuration + * Main entry point to configure RetryTemplate using fluent API. See + * {@link RetryTemplateBuilder} for usage examples and details. + * @return a new instance of RetryTemplateBuilder with preset default behaviour, that + * can be overwritten during manual configuration * @since 1.3 */ public static RetryTemplateBuilder newBuilder() { @@ -111,9 +108,8 @@ public class RetryTemplate implements RetryOperations { } /** - * Creates a new default instance. The properties of default instance are described in {@link RetryTemplateBuilder} - * documentation. - * + * Creates a new default instance. The properties of default instance are described in + * {@link RetryTemplateBuilder} documentation. * @return a new instance of RetryTemplate with default behaviour * @since 1.3 */ @@ -130,7 +126,6 @@ public class RetryTemplate implements RetryOperations { /** * Public setter for the {@link RetryContextCache}. - * * @param retryContextCache the {@link RetryContextCache} to set. */ public void setRetryContextCache(RetryContextCache retryContextCache) { @@ -140,7 +135,6 @@ public class RetryTemplate implements RetryOperations { /** * Setter for listeners. The listeners are executed before and after a retry block * (i.e. before and after all the attempts), and on an error (every attempt). - * * @param listeners the {@link RetryListener}s * @see RetryListener */ @@ -151,7 +145,6 @@ public class RetryTemplate implements RetryOperations { /** * Register an additional listener. - * * @param listener the {@link RetryListener} * @see #setListeners(RetryListener[]) */ @@ -164,7 +157,6 @@ public class RetryTemplate implements RetryOperations { /** * Setter for {@link BackOffPolicy}. - * * @param backOffPolicy the {@link BackOffPolicy} */ public void setBackOffPolicy(BackOffPolicy backOffPolicy) { @@ -173,7 +165,6 @@ public class RetryTemplate implements RetryOperations { /** * Setter for {@link RetryPolicy}. - * * @param retryPolicy the {@link RetryPolicy} */ public void setRetryPolicy(RetryPolicy retryPolicy) { @@ -187,7 +178,6 @@ public class RetryTemplate implements RetryOperations { * * @see RetryOperations#execute(RetryCallback) * @param retryCallback the {@link RetryCallback} - * * @throws TerminatedRetryException if the retry has been manually terminated by a * listener. */ @@ -399,7 +389,6 @@ public class RetryTemplate implements RetryOperations { * Decide whether to proceed with the ongoing retry attempt. This method is called * before the {@link RetryCallback} is executed, but after the backoff and open * interceptors. - * * @param retryPolicy the policy to apply * @param context the current retry context * @return true if we can continue with the attempt @@ -411,7 +400,6 @@ public class RetryTemplate implements RetryOperations { /** * Clean up the cache if necessary and close the context provided (if the flag * indicates that processing was successful). - * * @param retryPolicy the {@link RetryPolicy} * @param context the {@link RetryContext} * @param state the {@link RetryState} @@ -459,10 +447,8 @@ public class RetryTemplate implements RetryOperations { /** * Delegate to the {@link RetryPolicy} having checked in the cache for an existing * value if the state is not null. - * * @param state a {@link RetryState} * @param retryPolicy a {@link RetryPolicy} to delegate the context creation - * * @return a retry context, either a new one or the one used last time the same state * was encountered */ @@ -524,7 +510,6 @@ public class RetryTemplate implements RetryOperations { * Actions to take after final attempt has failed. If there is state clean up the * cache. If there is a recovery callback, execute that and return its result. * Otherwise throw an exception. - * * @param recoveryCallback the callback for recovery (might be null) * @param context the current retry context * @param state the {@link RetryState} @@ -570,7 +555,6 @@ public class RetryTemplate implements RetryOperations { * Extension point for subclasses to decide on behaviour after catching an exception * in a {@link RetryCallback}. Normal stateless behaviour is not to rethrow, and if * there is state we rethrow. - * * @param retryPolicy the retry policy * @param context the current context * @param state the current retryState diff --git a/src/main/java/org/springframework/retry/support/RetryTemplateBuilder.java b/src/main/java/org/springframework/retry/support/RetryTemplateBuilder.java index 456c0b5..467f538 100644 --- a/src/main/java/org/springframework/retry/support/RetryTemplateBuilder.java +++ b/src/main/java/org/springframework/retry/support/RetryTemplateBuilder.java @@ -1,6 +1,5 @@ package org.springframework.retry.support; - import java.util.ArrayList; import java.util.List; @@ -22,12 +21,11 @@ import org.springframework.retry.policy.TimeoutRetryPolicy; import org.springframework.util.Assert; /** - * Fluent API to configure new instance of RetryTemplate. - * For detailed description of each builder method - see it's doc. + * Fluent API to configure new instance of RetryTemplate. For detailed description of each + * builder method - see it's doc. * *

- * Examples: - *

{@code
+ * Examples: 
{@code
  * RetryTemplate.newBuilder()
  *      .maxAttempts(10)
  *      .exponentialBackoff(100, 2, 10000)
@@ -50,15 +48,15 @@ import org.springframework.util.Assert;
  * 

* The builder provides the following defaults: *

    - *
  • retry policy: max attempts = 3 (initial + 2 retries)
  • - *
  • backoff policy: no backoff (retry immediately)
  • - *
  • exception classification: retry only on {@link Exception} and it's subclasses, - * without traversing of causes
  • + *
  • retry policy: max attempts = 3 (initial + 2 retries)
  • + *
  • backoff policy: no backoff (retry immediately)
  • + *
  • exception classification: retry only on {@link Exception} and it's subclasses, + * without traversing of causes
  • *
* *

- * The builder supports only widely used properties of {@link RetryTemplate}. More specific - * properties can be configured directly (after building). + * The builder supports only widely used properties of {@link RetryTemplate}. More + * specific properties can be configured directly (after building). * *

* Not thread safe. Building should be performed in a single thread. Also, there is no @@ -72,353 +70,329 @@ import org.springframework.util.Assert; */ public class RetryTemplateBuilder { - private RetryPolicy baseRetryPolicy; - private BackOffPolicy backOffPolicy; - private List listeners; - private BinaryExceptionClassifierBuilder classifierBuilder; + private RetryPolicy baseRetryPolicy; - /* ---------------- Configure retry policy -------------- */ + private BackOffPolicy backOffPolicy; - /** - * Limits maximum number of attempts to provided value. - *

- * Invocation of this method does not discard default exception classification rule, - * that is "retry only on {@link Exception} and it's subclasses". - * - * @param maxAttempts includes initial attempt and all retries. E.g: maxAttempts = 3 means - * one initial attempt and two retries. - * @see MaxAttemptsRetryPolicy - */ - public RetryTemplateBuilder maxAttempts(int maxAttempts) { - Assert.isTrue( maxAttempts > 0, "Number of attempts should be positive"); - Assert.isNull(baseRetryPolicy, "You have already selected another retry policy"); - baseRetryPolicy = new MaxAttemptsRetryPolicy(maxAttempts); - return this; - } + private List listeners; - /** - * Allows retry if there is no more than {@code timeout} millis since first attempt. - *

- * Invocation of this method does not discard default exception classification rule, - * that is "retry only on {@link Exception} and it's subclasses". - * - * @param timeout whole execution timeout in milliseconds - * @see TimeoutRetryPolicy - */ - public RetryTemplateBuilder withinMillis(long timeout) { - Assert.isTrue(timeout > 0, "Timeout should be positive"); - Assert.isNull(baseRetryPolicy, "You have already selected another retry policy"); - TimeoutRetryPolicy timeoutRetryPolicy = new TimeoutRetryPolicy(); - timeoutRetryPolicy.setTimeout(timeout); - this.baseRetryPolicy = timeoutRetryPolicy; - return this; - } + private BinaryExceptionClassifierBuilder classifierBuilder; - /** - * Allows infinite retry, do not limit attempts by number or time. - *

- * Invocation of this method does not discard default exception classification rule, - * that is "retry only on {@link Exception} and it's subclasses". - * - * @see TimeoutRetryPolicy - */ - public RetryTemplateBuilder infiniteRetry() { - Assert.isNull(baseRetryPolicy, "You have already selected another retry policy"); - baseRetryPolicy = new AlwaysRetryPolicy(); - return this; - } + /* ---------------- Configure retry policy -------------- */ - /** - * If flexibility of this builder is not enough for you, you can provide your own - * {@link RetryPolicy} via this method. - *

- * Invocation of this method does not discard default exception classification rule, - * that is "retry only on {@link Exception} and it's subclasses". - * - * @param policy will be directly set to resulting {@link RetryTemplate} - */ - public RetryTemplateBuilder customPolicy(RetryPolicy policy) { - Assert.notNull(policy, "Policy should not be null"); - Assert.isNull(baseRetryPolicy, "You have already selected another retry policy"); - baseRetryPolicy = policy; - return this; - } + /** + * Limits maximum number of attempts to provided value. + *

+ * Invocation of this method does not discard default exception classification rule, + * that is "retry only on {@link Exception} and it's subclasses". + * @param maxAttempts includes initial attempt and all retries. E.g: maxAttempts = 3 + * means one initial attempt and two retries. + * @see MaxAttemptsRetryPolicy + */ + public RetryTemplateBuilder maxAttempts(int maxAttempts) { + Assert.isTrue(maxAttempts > 0, "Number of attempts should be positive"); + Assert.isNull(baseRetryPolicy, "You have already selected another retry policy"); + baseRetryPolicy = new MaxAttemptsRetryPolicy(maxAttempts); + return this; + } + /** + * Allows retry if there is no more than {@code timeout} millis since first attempt. + *

+ * Invocation of this method does not discard default exception classification rule, + * that is "retry only on {@link Exception} and it's subclasses". + * @param timeout whole execution timeout in milliseconds + * @see TimeoutRetryPolicy + */ + public RetryTemplateBuilder withinMillis(long timeout) { + Assert.isTrue(timeout > 0, "Timeout should be positive"); + Assert.isNull(baseRetryPolicy, "You have already selected another retry policy"); + TimeoutRetryPolicy timeoutRetryPolicy = new TimeoutRetryPolicy(); + timeoutRetryPolicy.setTimeout(timeout); + this.baseRetryPolicy = timeoutRetryPolicy; + return this; + } - /* ---------------- Configure backoff policy -------------- */ + /** + * Allows infinite retry, do not limit attempts by number or time. + *

+ * Invocation of this method does not discard default exception classification rule, + * that is "retry only on {@link Exception} and it's subclasses". + * + * @see TimeoutRetryPolicy + */ + public RetryTemplateBuilder infiniteRetry() { + Assert.isNull(baseRetryPolicy, "You have already selected another retry policy"); + baseRetryPolicy = new AlwaysRetryPolicy(); + return this; + } - /** - * Use exponential backoff policy. - * The formula of backoff period: - *

- * {@code currentInterval = Math.min(initialInterval * Math.pow(multiplier, retryNum), maxInterval)} - *

- * (for first attempt retryNum = 0) - * - * @param initialInterval in milliseconds - * @param multiplier see the formula above - * @param maxInterval in milliseconds - * @see ExponentialBackOffPolicy - */ - public RetryTemplateBuilder exponentialBackoff(long initialInterval, double multiplier, long maxInterval) { - return exponentialBackoff(initialInterval, multiplier, maxInterval, false); - } + /** + * If flexibility of this builder is not enough for you, you can provide your own + * {@link RetryPolicy} via this method. + *

+ * Invocation of this method does not discard default exception classification rule, + * that is "retry only on {@link Exception} and it's subclasses". + * @param policy will be directly set to resulting {@link RetryTemplate} + */ + public RetryTemplateBuilder customPolicy(RetryPolicy policy) { + Assert.notNull(policy, "Policy should not be null"); + Assert.isNull(baseRetryPolicy, "You have already selected another retry policy"); + baseRetryPolicy = policy; + return this; + } - /** - * Use exponential backoff policy. - * The formula of backoff period (without randomness): - *

- * {@code currentInterval = Math.min(initialInterval * Math.pow(multiplier, retryNum), maxInterval)} - *

- * (for first attempt retryNum = 0) - * - * @param initialInterval in milliseconds - * @param multiplier see the formula above - * @param maxInterval in milliseconds - * @param withRandom adds some randomness to backoff intervals. For details, see - * {@link ExponentialRandomBackOffPolicy} - * @see ExponentialBackOffPolicy - * @see ExponentialRandomBackOffPolicy - */ - public RetryTemplateBuilder exponentialBackoff(long initialInterval, double multiplier, long maxInterval, - boolean withRandom) { - Assert.isNull(backOffPolicy, "You have already selected backoff policy"); - Assert.isTrue(initialInterval >= 1, "Initial interval should be >= 1"); - Assert.isTrue(multiplier > 1, "Multiplier should be > 1"); - Assert.isTrue(maxInterval > initialInterval, - "Max interval should be > than initial interval"); - ExponentialBackOffPolicy policy = withRandom - ? new ExponentialRandomBackOffPolicy() - : new ExponentialBackOffPolicy(); - policy.setInitialInterval(initialInterval); - policy.setMultiplier(multiplier); - policy.setMaxInterval(maxInterval); - backOffPolicy = policy; - return this; - } + /* ---------------- Configure backoff policy -------------- */ - /** - * Perform each retry after fixed amount of time. - * - * @param interval fixed interval in milliseconds - * @see FixedBackOffPolicy - */ - public RetryTemplateBuilder fixedBackoff(long interval) { - Assert.isNull(backOffPolicy, "You have already selected backoff policy"); - Assert.isTrue(interval >= 1, "Interval should be >= 1"); - FixedBackOffPolicy policy = new FixedBackOffPolicy(); - policy.setBackOffPeriod(interval); - backOffPolicy = policy; - return this; - } + /** + * Use exponential backoff policy. The formula of backoff period: + *

+ * {@code currentInterval = Math.min(initialInterval * Math.pow(multiplier, retryNum), maxInterval)} + *

+ * (for first attempt retryNum = 0) + * @param initialInterval in milliseconds + * @param multiplier see the formula above + * @param maxInterval in milliseconds + * @see ExponentialBackOffPolicy + */ + public RetryTemplateBuilder exponentialBackoff(long initialInterval, + double multiplier, long maxInterval) { + return exponentialBackoff(initialInterval, multiplier, maxInterval, false); + } - /** - * Use {@link UniformRandomBackOffPolicy}, see it's doc for details. - * - * @param minInterval in milliseconds - * @param maxInterval in milliseconds - * @see UniformRandomBackOffPolicy - */ - public RetryTemplateBuilder uniformRandomBackoff(long minInterval, long maxInterval) { - Assert.isNull(backOffPolicy, "You have already selected backoff policy"); - Assert.isTrue(minInterval >= 1, "Min interval should be >= 1"); - Assert.isTrue(maxInterval >= 1, "Max interval should be >= 1"); - Assert.isTrue(maxInterval > minInterval, - "Max interval should be > than min interval"); - UniformRandomBackOffPolicy policy = new UniformRandomBackOffPolicy(); - policy.setMinBackOffPeriod(minInterval); - policy.setMaxBackOffPeriod(maxInterval); - backOffPolicy = policy; - return this; - } + /** + * Use exponential backoff policy. The formula of backoff period (without randomness): + *

+ * {@code currentInterval = Math.min(initialInterval * Math.pow(multiplier, retryNum), maxInterval)} + *

+ * (for first attempt retryNum = 0) + * @param initialInterval in milliseconds + * @param multiplier see the formula above + * @param maxInterval in milliseconds + * @param withRandom adds some randomness to backoff intervals. For details, see + * {@link ExponentialRandomBackOffPolicy} + * @see ExponentialBackOffPolicy + * @see ExponentialRandomBackOffPolicy + */ + public RetryTemplateBuilder exponentialBackoff(long initialInterval, + double multiplier, long maxInterval, boolean withRandom) { + Assert.isNull(backOffPolicy, "You have already selected backoff policy"); + Assert.isTrue(initialInterval >= 1, "Initial interval should be >= 1"); + Assert.isTrue(multiplier > 1, "Multiplier should be > 1"); + Assert.isTrue(maxInterval > initialInterval, + "Max interval should be > than initial interval"); + ExponentialBackOffPolicy policy = withRandom + ? new ExponentialRandomBackOffPolicy() : new ExponentialBackOffPolicy(); + policy.setInitialInterval(initialInterval); + policy.setMultiplier(multiplier); + policy.setMaxInterval(maxInterval); + backOffPolicy = policy; + return this; + } - /** - * Do not pause between attempts, retry immediately. - * - * @see NoBackOffPolicy - */ - public RetryTemplateBuilder noBackoff() { - Assert.isNull(backOffPolicy, "You have already selected backoff policy"); - backOffPolicy = new NoBackOffPolicy(); - return this; - } + /** + * Perform each retry after fixed amount of time. + * @param interval fixed interval in milliseconds + * @see FixedBackOffPolicy + */ + public RetryTemplateBuilder fixedBackoff(long interval) { + Assert.isNull(backOffPolicy, "You have already selected backoff policy"); + Assert.isTrue(interval >= 1, "Interval should be >= 1"); + FixedBackOffPolicy policy = new FixedBackOffPolicy(); + policy.setBackOffPeriod(interval); + backOffPolicy = policy; + return this; + } - /** - * You can provide your own {@link BackOffPolicy} via this method. - * - * @param backOffPolicy will be directly set to resulting {@link RetryTemplate} - */ - public RetryTemplateBuilder customBackoff(BackOffPolicy backOffPolicy) { - Assert.isNull(this.backOffPolicy, "You have already selected backoff policy"); - Assert.notNull(backOffPolicy, "You should provide non null custom policy"); - this.backOffPolicy = backOffPolicy; - return this; - } + /** + * Use {@link UniformRandomBackOffPolicy}, see it's doc for details. + * @param minInterval in milliseconds + * @param maxInterval in milliseconds + * @see UniformRandomBackOffPolicy + */ + public RetryTemplateBuilder uniformRandomBackoff(long minInterval, long maxInterval) { + Assert.isNull(backOffPolicy, "You have already selected backoff policy"); + Assert.isTrue(minInterval >= 1, "Min interval should be >= 1"); + Assert.isTrue(maxInterval >= 1, "Max interval should be >= 1"); + Assert.isTrue(maxInterval > minInterval, + "Max interval should be > than min interval"); + UniformRandomBackOffPolicy policy = new UniformRandomBackOffPolicy(); + policy.setMinBackOffPeriod(minInterval); + policy.setMaxBackOffPeriod(maxInterval); + backOffPolicy = policy; + return this; + } + /** + * Do not pause between attempts, retry immediately. + * + * @see NoBackOffPolicy + */ + public RetryTemplateBuilder noBackoff() { + Assert.isNull(backOffPolicy, "You have already selected backoff policy"); + backOffPolicy = new NoBackOffPolicy(); + return this; + } - /* ---------------- Configure exception classifier -------------- */ + /** + * You can provide your own {@link BackOffPolicy} via this method. + * @param backOffPolicy will be directly set to resulting {@link RetryTemplate} + */ + public RetryTemplateBuilder customBackoff(BackOffPolicy backOffPolicy) { + Assert.isNull(this.backOffPolicy, "You have already selected backoff policy"); + Assert.notNull(backOffPolicy, "You should provide non null custom policy"); + this.backOffPolicy = backOffPolicy; + return this; + } - /** - * Add a throwable to the while list of retryable exceptions. - *

- * Warn: touching this method drops default {@code retryOn(Exception.class)} - * and you should configure whole classifier from scratch. - *

- * You should select the way you want to configure exception classifier: - * white list or black list. If you choose white list - use this method, - * if black - use {@link #notRetryOn(Class)} - * - * @param throwable to be retryable (with it's subclasses) - * @see BinaryExceptionClassifierBuilder#retryOn - * @see BinaryExceptionClassifier - */ - public RetryTemplateBuilder retryOn(Class throwable) { - classifierBuilder().retryOn(throwable); - return this; - } + /* ---------------- Configure exception classifier -------------- */ + /** + * Add a throwable to the while list of retryable exceptions. + *

+ * Warn: touching this method drops default {@code retryOn(Exception.class)} and you + * should configure whole classifier from scratch. + *

+ * You should select the way you want to configure exception classifier: white list or + * black list. If you choose white list - use this method, if black - use + * {@link #notRetryOn(Class)} + * @param throwable to be retryable (with it's subclasses) + * @see BinaryExceptionClassifierBuilder#retryOn + * @see BinaryExceptionClassifier + */ + public RetryTemplateBuilder retryOn(Class throwable) { + classifierBuilder().retryOn(throwable); + return this; + } - /** - * Add a throwable to the black list of retryable exceptions. - *

- * Warn: touching this method drops default {@code retryOn(Exception.class)} - * and you should configure whole classifier from scratch. - *

- * You should select the way you want to configure exception classifier: - * white list or black list. If you choose black list - use this method, - * if white - use {@link #retryOn(Class)} - * - * @param throwable to be not retryable (with it's subclasses) - * @see BinaryExceptionClassifierBuilder#notRetryOn - * @see BinaryExceptionClassifier - */ - public RetryTemplateBuilder notRetryOn(Class throwable) { - classifierBuilder().notRetryOn(throwable); - return this; - } + /** + * Add a throwable to the black list of retryable exceptions. + *

+ * Warn: touching this method drops default {@code retryOn(Exception.class)} and you + * should configure whole classifier from scratch. + *

+ * You should select the way you want to configure exception classifier: white list or + * black list. If you choose black list - use this method, if white - use + * {@link #retryOn(Class)} + * @param throwable to be not retryable (with it's subclasses) + * @see BinaryExceptionClassifierBuilder#notRetryOn + * @see BinaryExceptionClassifier + */ + public RetryTemplateBuilder notRetryOn(Class throwable) { + classifierBuilder().notRetryOn(throwable); + return this; + } - /** - * Suppose throwing a {@code new MyLogicException(new IOException())}. - * This template will not retry on it: - *

{@code
-     * RetryTemplate.newBuilder()
-     *          .retryOn(IOException.class)
-     *          .build()
-     * }
- * but this will retry: - *
{@code
-     * RetryTemplate.newBuilder()
-     *          .retryOn(IOException.class)
-     *          .traversingCauses()
-     *          .build()
-     * }
- * - * @see BinaryExceptionClassifier - */ - public RetryTemplateBuilder traversingCauses() { - classifierBuilder().traversingCauses(); - return this; - } + /** + * Suppose throwing a {@code new MyLogicException(new IOException())}. This template + * will not retry on it:
{@code
+	 * RetryTemplate.newBuilder()
+	 *          .retryOn(IOException.class)
+	 *          .build()
+	 * }
but this will retry:
{@code
+	 * RetryTemplate.newBuilder()
+	 *          .retryOn(IOException.class)
+	 *          .traversingCauses()
+	 *          .build()
+	 * }
+ * + * @see BinaryExceptionClassifier + */ + public RetryTemplateBuilder traversingCauses() { + classifierBuilder().traversingCauses(); + return this; + } + /* ---------------- Add listeners -------------- */ - /* ---------------- Add listeners -------------- */ + /** + * Appends provided {@code listener} to {@link RetryTemplate}'s listener list. + * @param listener to be appended + * @see RetryTemplate + * @see RetryListener + */ + public RetryTemplateBuilder withListener(RetryListener listener) { + Assert.notNull(listener, "Listener should not be null"); + listenersList().add(listener); + return this; + } - /** - * Appends provided {@code listener} to {@link RetryTemplate}'s listener list. - * - * @param listener to be appended - * @see RetryTemplate - * @see RetryListener - */ - public RetryTemplateBuilder withListener(RetryListener listener) { - Assert.notNull(listener, "Listener should not be null"); - listenersList().add(listener); - return this; - } + /** + * Appends all provided {@code listeners} to {@link RetryTemplate}'s listener list. + * @param listeners to be appended + * @see RetryTemplate + * @see RetryListener + */ + public RetryTemplateBuilder withListeners(List listeners) { + for (final RetryListener listener : listeners) { + Assert.notNull(listener, "Listener should not be null"); + } + listenersList().addAll(listeners); + return this; + } - /** - * Appends all provided {@code listeners} to {@link RetryTemplate}'s listener list. - * - * @param listeners to be appended - * @see RetryTemplate - * @see RetryListener - */ - public RetryTemplateBuilder withListeners(List listeners) { - for (final RetryListener listener : listeners) { - Assert.notNull(listener, "Listener should not be null"); - } - listenersList().addAll(listeners); - return this; - } + /* ---------------- Building -------------- */ + /** + * Finish configuration and build resulting {@link RetryTemplate}. For default + * behaviour and concurrency note see class-level doc of {@link RetryTemplateBuilder}. + * + * @implNote The {@code retryPolicy} of the returned {@link RetryTemplate} is always + * an instance of {@link CompositeRetryPolicy}, that consists of one base policy, and + * of {@link BinaryExceptionClassifierRetryPolicy}. The motivation is: whatever base + * policy we use, exception classification is extremely recommended. + * @return new instance of {@link RetryTemplate} + */ + public RetryTemplate build() { + RetryTemplate retryTemplate = new RetryTemplate(); - /* ---------------- Building -------------- */ + // Exception classifier - /** - * Finish configuration and build resulting {@link RetryTemplate}. - * For default behaviour and concurrency note see class-level doc of {@link RetryTemplateBuilder}. - * - * @implNote - * The {@code retryPolicy} of the returned {@link RetryTemplate} is always - * an instance of {@link CompositeRetryPolicy}, that consists of one base - * policy, and of {@link BinaryExceptionClassifierRetryPolicy}. - * The motivation is: whatever base policy we use, exception classification - * is extremely recommended. - * - * @return new instance of {@link RetryTemplate} - */ - public RetryTemplate build() { - RetryTemplate retryTemplate = new RetryTemplate(); + BinaryExceptionClassifier exceptionClassifier = classifierBuilder != null + ? classifierBuilder.build() + : BinaryExceptionClassifier.newDefaultClassifier(); - // Exception classifier + // Retry policy - BinaryExceptionClassifier exceptionClassifier = classifierBuilder != null - ? classifierBuilder.build() - : BinaryExceptionClassifier.newDefaultClassifier(); + if (baseRetryPolicy == null) { + baseRetryPolicy = new MaxAttemptsRetryPolicy(); + } - // Retry policy + CompositeRetryPolicy finalPolicy = new CompositeRetryPolicy(); + finalPolicy.setPolicies(new RetryPolicy[] { baseRetryPolicy, + new BinaryExceptionClassifierRetryPolicy(exceptionClassifier) }); + retryTemplate.setRetryPolicy(finalPolicy); - if (baseRetryPolicy == null) { - baseRetryPolicy = new MaxAttemptsRetryPolicy(); - } + // Backoff policy - CompositeRetryPolicy finalPolicy = new CompositeRetryPolicy(); - finalPolicy.setPolicies(new RetryPolicy[] { - baseRetryPolicy, - new BinaryExceptionClassifierRetryPolicy(exceptionClassifier) - }); - retryTemplate.setRetryPolicy(finalPolicy); + if (backOffPolicy == null) { + backOffPolicy = new NoBackOffPolicy(); + } + retryTemplate.setBackOffPolicy(backOffPolicy); - // Backoff policy + // Listeners - if (backOffPolicy == null) { - backOffPolicy = new NoBackOffPolicy(); - } - retryTemplate.setBackOffPolicy(backOffPolicy); + if (listeners != null) { + retryTemplate.setListeners(listeners.toArray(new RetryListener[0])); + } - // Listeners + return retryTemplate; + } - if (listeners != null) { - retryTemplate.setListeners(listeners.toArray(new RetryListener[0])); - } + /* ---------------- Private utils -------------- */ - return retryTemplate; - } + private BinaryExceptionClassifierBuilder classifierBuilder() { + if (classifierBuilder == null) { + classifierBuilder = new BinaryExceptionClassifierBuilder(); + } + return classifierBuilder; + } + private List listenersList() { + if (listeners == null) { + listeners = new ArrayList(); + } + return listeners; + } - /* ---------------- Private utils -------------- */ - - private BinaryExceptionClassifierBuilder classifierBuilder() { - if (classifierBuilder == null) { - classifierBuilder = new BinaryExceptionClassifierBuilder(); - } - return classifierBuilder; - } - - private List listenersList() { - if (listeners == null) { - listeners = new ArrayList(); - } - return listeners; - } } diff --git a/src/test/java/org/springframework/classify/BinaryExceptionClassifierBuilderTest.java b/src/test/java/org/springframework/classify/BinaryExceptionClassifierBuilderTest.java index a167422..b3276b4 100644 --- a/src/test/java/org/springframework/classify/BinaryExceptionClassifierBuilderTest.java +++ b/src/test/java/org/springframework/classify/BinaryExceptionClassifierBuilderTest.java @@ -26,67 +26,59 @@ import org.junit.Test; import org.springframework.retry.support.RetryTemplate; /** - * @author Aleksandr Shamukov + * @author Aleksandr Shamukov */ public class BinaryExceptionClassifierBuilderTest { - @Test - public void testWhiteList() { - RetryTemplate.newBuilder() - .infiniteRetry() - .retryOn(IOException.class) - .uniformRandomBackoff(1000, 3000) - .build(); + @Test + public void testWhiteList() { + RetryTemplate.newBuilder().infiniteRetry().retryOn(IOException.class) + .uniformRandomBackoff(1000, 3000).build(); - BinaryExceptionClassifier classifier = BinaryExceptionClassifier.newBuilder() - .retryOn(IOException.class) - .retryOn(TimeoutException.class) - .build(); + BinaryExceptionClassifier classifier = BinaryExceptionClassifier.newBuilder() + .retryOn(IOException.class).retryOn(TimeoutException.class).build(); - Assert.assertTrue(classifier.classify(new IOException())); - // should not retry due to traverseCauses=fasle - Assert.assertFalse(classifier.classify(new RuntimeException(new IOException()))); - Assert.assertTrue(classifier.classify(new StreamCorruptedException())); - Assert.assertFalse(classifier.classify(new OutOfMemoryError())); - } + Assert.assertTrue(classifier.classify(new IOException())); + // should not retry due to traverseCauses=fasle + Assert.assertFalse(classifier.classify(new RuntimeException(new IOException()))); + Assert.assertTrue(classifier.classify(new StreamCorruptedException())); + Assert.assertFalse(classifier.classify(new OutOfMemoryError())); + } - @Test - public void testWhiteListWithTraverseCauses() { - BinaryExceptionClassifier classifier = BinaryExceptionClassifier.newBuilder() - .retryOn(IOException.class) - .retryOn(TimeoutException.class) - .traversingCauses() - .build(); + @Test + public void testWhiteListWithTraverseCauses() { + BinaryExceptionClassifier classifier = BinaryExceptionClassifier.newBuilder() + .retryOn(IOException.class).retryOn(TimeoutException.class) + .traversingCauses().build(); - Assert.assertTrue(classifier.classify(new IOException())); - // should retry due to traverseCauses=true - Assert.assertTrue(classifier.classify(new RuntimeException(new IOException()))); - Assert.assertTrue(classifier.classify(new StreamCorruptedException())); - // should retry due to FileNotFoundException is a subclass of TimeoutException - Assert.assertTrue(classifier.classify(new FileNotFoundException())); - Assert.assertFalse(classifier.classify(new RuntimeException())); - } + Assert.assertTrue(classifier.classify(new IOException())); + // should retry due to traverseCauses=true + Assert.assertTrue(classifier.classify(new RuntimeException(new IOException()))); + Assert.assertTrue(classifier.classify(new StreamCorruptedException())); + // should retry due to FileNotFoundException is a subclass of TimeoutException + Assert.assertTrue(classifier.classify(new FileNotFoundException())); + Assert.assertFalse(classifier.classify(new RuntimeException())); + } - @Test - public void testBlackList() { - BinaryExceptionClassifier classifier = BinaryExceptionClassifier.newBuilder() - .notRetryOn(Error.class) - .notRetryOn(InterruptedException.class) - .traversingCauses() - .build(); + @Test + public void testBlackList() { + BinaryExceptionClassifier classifier = BinaryExceptionClassifier.newBuilder() + .notRetryOn(Error.class).notRetryOn(InterruptedException.class) + .traversingCauses().build(); - // should not retry due to OutOfMemoryError is a subclass of Error - Assert.assertFalse(classifier.classify(new OutOfMemoryError())); - Assert.assertFalse(classifier.classify(new InterruptedException())); - Assert.assertTrue(classifier.classify(new Throwable())); - // should retry due to traverseCauses=true - Assert.assertFalse(classifier.classify(new RuntimeException(new InterruptedException()))); - } + // should not retry due to OutOfMemoryError is a subclass of Error + Assert.assertFalse(classifier.classify(new OutOfMemoryError())); + Assert.assertFalse(classifier.classify(new InterruptedException())); + Assert.assertTrue(classifier.classify(new Throwable())); + // should retry due to traverseCauses=true + Assert.assertFalse( + classifier.classify(new RuntimeException(new InterruptedException()))); + } + + @Test(expected = IllegalArgumentException.class) + public void testFailOnNotationMix() { + BinaryExceptionClassifier.newBuilder().retryOn(IOException.class) + .notRetryOn(OutOfMemoryError.class); + } - @Test(expected = IllegalArgumentException.class) - public void testFailOnNotationMix() { - BinaryExceptionClassifier.newBuilder() - .retryOn(IOException.class) - .notRetryOn(OutOfMemoryError.class); - } } diff --git a/src/test/java/org/springframework/classify/BinaryExceptionClassifierTests.java b/src/test/java/org/springframework/classify/BinaryExceptionClassifierTests.java index 8070753..0d6ae7e 100644 --- a/src/test/java/org/springframework/classify/BinaryExceptionClassifierTests.java +++ b/src/test/java/org/springframework/classify/BinaryExceptionClassifierTests.java @@ -56,26 +56,31 @@ public class BinaryExceptionClassifierTests { @Test public void testClassifyExactMatch() { Collection> set = Collections - .> singleton(IllegalStateException.class); - assertTrue(new BinaryExceptionClassifier(set).classify(new IllegalStateException("Foo"))); + .>singleton(IllegalStateException.class); + assertTrue(new BinaryExceptionClassifier(set) + .classify(new IllegalStateException("Foo"))); } @Test public void testClassifyExactMatchInCause() { Collection> set = Collections - .> singleton(IllegalStateException.class); - BinaryExceptionClassifier binaryExceptionClassifier = new BinaryExceptionClassifier(set); + .>singleton(IllegalStateException.class); + BinaryExceptionClassifier binaryExceptionClassifier = new BinaryExceptionClassifier( + set); binaryExceptionClassifier.setTraverseCauses(true); - assertTrue(binaryExceptionClassifier.classify(new RuntimeException(new IllegalStateException("Foo")))); + assertTrue(binaryExceptionClassifier + .classify(new RuntimeException(new IllegalStateException("Foo")))); } @Test public void testClassifySubclassMatchInCause() { Collection> set = Collections - .> singleton(IllegalStateException.class); - BinaryExceptionClassifier binaryExceptionClassifier = new BinaryExceptionClassifier(set); + .>singleton(IllegalStateException.class); + BinaryExceptionClassifier binaryExceptionClassifier = new BinaryExceptionClassifier( + set); binaryExceptionClassifier.setTraverseCauses(true); - assertTrue(binaryExceptionClassifier.classify(new RuntimeException(new FooException("Foo")))); + assertTrue(binaryExceptionClassifier + .classify(new RuntimeException(new FooException("Foo")))); } @Test @@ -83,33 +88,38 @@ public class BinaryExceptionClassifierTests { Map, Boolean> map = new HashMap, Boolean>(); map.put(IllegalStateException.class, true); map.put(BarException.class, false); - BinaryExceptionClassifier binaryExceptionClassifier = new BinaryExceptionClassifier(map, true); + BinaryExceptionClassifier binaryExceptionClassifier = new BinaryExceptionClassifier( + map, true); binaryExceptionClassifier.setTraverseCauses(true); - assertTrue(binaryExceptionClassifier.classify(new RuntimeException(new FooException("Foo", new BarException())))); - assertTrue(((Map) new DirectFieldAccessor(binaryExceptionClassifier).getPropertyValue("classified")) - .containsKey(FooException.class)); + assertTrue(binaryExceptionClassifier.classify( + new RuntimeException(new FooException("Foo", new BarException())))); + assertTrue(((Map) new DirectFieldAccessor(binaryExceptionClassifier) + .getPropertyValue("classified")).containsKey(FooException.class)); } @Test public void testTypesProvidedInConstructor() { classifier = new BinaryExceptionClassifier(Collections - .> singleton(IllegalStateException.class)); + .>singleton(IllegalStateException.class)); assertTrue(classifier.classify(new IllegalStateException("Foo"))); } @Test public void testTypesProvidedInConstructorWithNonDefault() { classifier = new BinaryExceptionClassifier(Collections - .> singleton(IllegalStateException.class), false); + .>singleton(IllegalStateException.class), + false); assertFalse(classifier.classify(new IllegalStateException("Foo"))); } @Test public void testTypesProvidedInConstructorWithNonDefaultInCause() { classifier = new BinaryExceptionClassifier(Collections - .> singleton(IllegalStateException.class), false); + .>singleton(IllegalStateException.class), + false); classifier.setTraverseCauses(true); - assertFalse(classifier.classify(new RuntimeException(new RuntimeException(new IllegalStateException("Foo"))))); + assertFalse(classifier.classify(new RuntimeException( + new RuntimeException(new IllegalStateException("Foo"))))); } @SuppressWarnings("serial") @@ -133,4 +143,5 @@ public class BinaryExceptionClassifierTests { } } + } diff --git a/src/test/java/org/springframework/classify/ClassifierAdapterTests.java b/src/test/java/org/springframework/classify/ClassifierAdapterTests.java index b402e1d..ed9fd81 100644 --- a/src/test/java/org/springframework/classify/ClassifierAdapterTests.java +++ b/src/test/java/org/springframework/classify/ClassifierAdapterTests.java @@ -23,7 +23,7 @@ import static org.junit.Assert.assertEquals; /** * @author Dave Syer - * + * */ public class ClassifierAdapterTests { @@ -68,9 +68,11 @@ public class ClassifierAdapterTests { public Integer getValue(String key) { return Integer.parseInt(key); } + @SuppressWarnings("unused") public void doNothing(String key) { } + @SuppressWarnings("unused") public String doNothing(String key, int value) { return "foo"; @@ -102,7 +104,7 @@ public class ClassifierAdapterTests { assertEquals(23, adapter.classify("23").intValue()); } - @Test(expected=IllegalArgumentException.class) + @Test(expected = IllegalArgumentException.class) public void testClassifyWithWrongType() { adapter.setDelegate(new Object() { @Classifier @@ -116,11 +118,12 @@ public class ClassifierAdapterTests { @SuppressWarnings("serial") @Test public void testClassifyWithClassifier() { - adapter.setDelegate(new org.springframework.classify.Classifier() { - public Integer classify(String classifiable) { - return Integer.valueOf(classifiable); - } - }); + adapter.setDelegate( + new org.springframework.classify.Classifier() { + public Integer classify(String classifiable) { + return Integer.valueOf(classifiable); + } + }); assertEquals(23, adapter.classify("23").intValue()); } diff --git a/src/test/java/org/springframework/classify/ClassifierSupportTests.java b/src/test/java/org/springframework/classify/ClassifierSupportTests.java index 1b6eb28..76a6d51 100644 --- a/src/test/java/org/springframework/classify/ClassifierSupportTests.java +++ b/src/test/java/org/springframework/classify/ClassifierSupportTests.java @@ -24,14 +24,17 @@ public class ClassifierSupportTests { @Test public void testClassifyNullIsDefault() { - ClassifierSupport classifier = new ClassifierSupport("foo"); + ClassifierSupport classifier = new ClassifierSupport( + "foo"); assertEquals(classifier.classify(null), "foo"); } @Test public void testClassifyRandomException() { - ClassifierSupport classifier = new ClassifierSupport("foo"); - assertEquals(classifier.classify(new IllegalStateException("Foo")), classifier.classify(null)); + ClassifierSupport classifier = new ClassifierSupport( + "foo"); + assertEquals(classifier.classify(new IllegalStateException("Foo")), + classifier.classify(null)); } } diff --git a/src/test/java/org/springframework/classify/PatternMatchingClassifierTests.java b/src/test/java/org/springframework/classify/PatternMatchingClassifierTests.java index c254660..5c21149 100644 --- a/src/test/java/org/springframework/classify/PatternMatchingClassifierTests.java +++ b/src/test/java/org/springframework/classify/PatternMatchingClassifierTests.java @@ -26,7 +26,7 @@ import org.springframework.classify.PatternMatchingClassifier; /** * @author Dave Syer - * + * */ public class PatternMatchingClassifierTests { @@ -52,7 +52,7 @@ public class PatternMatchingClassifierTests { public void testCreateFromMap() { classifier = new PatternMatchingClassifier(map); assertEquals("bar", classifier.classify("foo")); - assertEquals("spam", classifier.classify("bucket")); + assertEquals("spam", classifier.classify("bucket")); } } \ No newline at end of file diff --git a/src/test/java/org/springframework/classify/SubclassExceptionClassifierTests.java b/src/test/java/org/springframework/classify/SubclassExceptionClassifierTests.java index a1ac1b6..752a2ef 100644 --- a/src/test/java/org/springframework/classify/SubclassExceptionClassifierTests.java +++ b/src/test/java/org/springframework/classify/SubclassExceptionClassifierTests.java @@ -55,23 +55,27 @@ public class SubclassExceptionClassifierTests { @Test public void testClassifyExactMatch() { - classifier.setTypeMap(Collections., String> singletonMap( - IllegalStateException.class, "foo")); + classifier + .setTypeMap(Collections., String>singletonMap( + IllegalStateException.class, "foo")); assertEquals("foo", classifier.classify(new IllegalStateException("Foo"))); } @Test public void testClassifySubclassMatch() { - classifier.setTypeMap(Collections., String> singletonMap(RuntimeException.class, - "foo")); + classifier + .setTypeMap(Collections., String>singletonMap( + RuntimeException.class, "foo")); assertEquals("foo", classifier.classify(new IllegalStateException("Foo"))); } @Test public void testClassifySuperclassDoesNotMatch() { - classifier.setTypeMap(Collections., String> singletonMap( - IllegalStateException.class, "foo")); - assertEquals(classifier.getDefault(), classifier.classify(new RuntimeException("Foo"))); + classifier + .setTypeMap(Collections., String>singletonMap( + IllegalStateException.class, "foo")); + assertEquals(classifier.getDefault(), + classifier.classify(new RuntimeException("Foo"))); } @SuppressWarnings("serial") @@ -108,4 +112,5 @@ public class SubclassExceptionClassifierTests { public static class SubConnectException extends ConnectException { } + } diff --git a/src/test/java/org/springframework/retry/AbstractExceptionTests.java b/src/test/java/org/springframework/retry/AbstractExceptionTests.java index 5b16eb7..8cc44f5 100644 --- a/src/test/java/org/springframework/retry/AbstractExceptionTests.java +++ b/src/test/java/org/springframework/retry/AbstractExceptionTests.java @@ -37,4 +37,5 @@ public abstract class AbstractExceptionTests { public abstract Exception getException(String msg) throws Exception; public abstract Exception getException(String msg, Throwable t) throws Exception; + } diff --git a/src/test/java/org/springframework/retry/AnyThrowTests.java b/src/test/java/org/springframework/retry/AnyThrowTests.java index db5245c..4a70b03 100644 --- a/src/test/java/org/springframework/retry/AnyThrowTests.java +++ b/src/test/java/org/springframework/retry/AnyThrowTests.java @@ -25,10 +25,10 @@ import org.junit.rules.ExpectedException; * */ public class AnyThrowTests { - + @Rule public ExpectedException expected = ExpectedException.none(); - + @Test public void testRuntimeException() throws Throwable { expected.expect(RuntimeException.class); @@ -46,7 +46,7 @@ public class AnyThrowTests { expected.expect(Exception.class); AnyThrow.throwAny(new Exception("planned")); } - + private static class AnyThrow { private static void throwUnchecked(Throwable e) { @@ -55,8 +55,9 @@ public class AnyThrowTests { @SuppressWarnings("unchecked") private static void throwAny(Throwable e) throws E { - throw (E)e; + throw (E) e; } + } - + } diff --git a/src/test/java/org/springframework/retry/BackOffInterruptedExceptionTests.java b/src/test/java/org/springframework/retry/BackOffInterruptedExceptionTests.java index 9910393..58e2af3 100644 --- a/src/test/java/org/springframework/retry/BackOffInterruptedExceptionTests.java +++ b/src/test/java/org/springframework/retry/BackOffInterruptedExceptionTests.java @@ -31,4 +31,5 @@ public class BackOffInterruptedExceptionTests extends AbstractExceptionTests { public void testNothing() throws Exception { // fool coverage tools... } + } diff --git a/src/test/java/org/springframework/retry/ExhaustedRetryExceptionTests.java b/src/test/java/org/springframework/retry/ExhaustedRetryExceptionTests.java index 8674f9d..d077d1d 100644 --- a/src/test/java/org/springframework/retry/ExhaustedRetryExceptionTests.java +++ b/src/test/java/org/springframework/retry/ExhaustedRetryExceptionTests.java @@ -31,4 +31,5 @@ public class ExhaustedRetryExceptionTests extends AbstractExceptionTests { public void testNothing() throws Exception { // fool coverage tools... } + } diff --git a/src/test/java/org/springframework/retry/ResourcelessTransactionManager.java b/src/test/java/org/springframework/retry/ResourcelessTransactionManager.java index 88949c3..be5e852 100644 --- a/src/test/java/org/springframework/retry/ResourcelessTransactionManager.java +++ b/src/test/java/org/springframework/retry/ResourcelessTransactionManager.java @@ -11,12 +11,14 @@ import org.springframework.transaction.support.TransactionSynchronizationManager @SuppressWarnings("serial") public class ResourcelessTransactionManager extends AbstractPlatformTransactionManager { - protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException { + protected void doBegin(Object transaction, TransactionDefinition definition) + throws TransactionException { ((ResourcelessTransaction) transaction).begin(); } protected void doCommit(DefaultTransactionStatus status) throws TransactionException { - logger.debug("Committing resourceless transaction on [" + status.getTransaction() + "]"); + logger.debug("Committing resourceless transaction on [" + status.getTransaction() + + "]"); } protected Object doGetTransaction() throws TransactionException { @@ -28,32 +30,39 @@ public class ResourcelessTransactionManager extends AbstractPlatformTransactionM } else { @SuppressWarnings("unchecked") - Stack stack = (Stack) TransactionSynchronizationManager.getResource(this); + Stack stack = (Stack) TransactionSynchronizationManager + .getResource(this); resources = stack; } resources.push(transaction); return transaction; } - protected void doRollback(DefaultTransactionStatus status) throws TransactionException { - logger.debug("Rolling back resourceless transaction on [" + status.getTransaction() + "]"); + protected void doRollback(DefaultTransactionStatus status) + throws TransactionException { + logger.debug("Rolling back resourceless transaction on [" + + status.getTransaction() + "]"); } - protected boolean isExistingTransaction(Object transaction) throws TransactionException { + protected boolean isExistingTransaction(Object transaction) + throws TransactionException { if (TransactionSynchronizationManager.hasResource(this)) { @SuppressWarnings("unchecked") - Stack stack = (Stack) TransactionSynchronizationManager.getResource(this); + Stack stack = (Stack) TransactionSynchronizationManager + .getResource(this); return stack.size() > 1; } return ((ResourcelessTransaction) transaction).isActive(); } - protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException { + protected void doSetRollbackOnly(DefaultTransactionStatus status) + throws TransactionException { } protected void doCleanupAfterCompletion(Object transaction) { @SuppressWarnings("unchecked") - Stack list = (Stack) TransactionSynchronizationManager.getResource(this); + Stack list = (Stack) TransactionSynchronizationManager + .getResource(this); Stack resources = list; resources.clear(); TransactionSynchronizationManager.unbindResource(this); diff --git a/src/test/java/org/springframework/retry/RetryExceptionTests.java b/src/test/java/org/springframework/retry/RetryExceptionTests.java index eb1827f..96ddf51 100644 --- a/src/test/java/org/springframework/retry/RetryExceptionTests.java +++ b/src/test/java/org/springframework/retry/RetryExceptionTests.java @@ -31,4 +31,5 @@ public class RetryExceptionTests extends AbstractExceptionTests { public void testNothing() throws Exception { // fool coverage tools... } + } diff --git a/src/test/java/org/springframework/retry/TerminatedRetryExceptionTests.java b/src/test/java/org/springframework/retry/TerminatedRetryExceptionTests.java index d5745c0..d1fa1c2 100644 --- a/src/test/java/org/springframework/retry/TerminatedRetryExceptionTests.java +++ b/src/test/java/org/springframework/retry/TerminatedRetryExceptionTests.java @@ -31,4 +31,5 @@ public class TerminatedRetryExceptionTests extends AbstractExceptionTests { public void testNothing() throws Exception { // fool coverage tools... } + } diff --git a/src/test/java/org/springframework/retry/annotation/CircuitBreakerTests.java b/src/test/java/org/springframework/retry/annotation/CircuitBreakerTests.java index 5fba21f..536ca43 100644 --- a/src/test/java/org/springframework/retry/annotation/CircuitBreakerTests.java +++ b/src/test/java/org/springframework/retry/annotation/CircuitBreakerTests.java @@ -56,21 +56,24 @@ public class CircuitBreakerTests { } catch (Exception e) { } - assertFalse((Boolean)service.getContext().getAttribute(CircuitBreakerRetryPolicy.CIRCUIT_OPEN)); + assertFalse((Boolean) service.getContext() + .getAttribute(CircuitBreakerRetryPolicy.CIRCUIT_OPEN)); try { service.service(); fail("Expected exception"); } catch (Exception e) { } - assertFalse((Boolean)service.getContext().getAttribute(CircuitBreakerRetryPolicy.CIRCUIT_OPEN)); + assertFalse((Boolean) service.getContext() + .getAttribute(CircuitBreakerRetryPolicy.CIRCUIT_OPEN)); try { service.service(); fail("Expected exception"); } catch (Exception e) { } - assertTrue((Boolean)service.getContext().getAttribute(CircuitBreakerRetryPolicy.CIRCUIT_OPEN)); + assertTrue((Boolean) service.getContext() + .getAttribute(CircuitBreakerRetryPolicy.CIRCUIT_OPEN)); assertEquals(3, service.getCount()); try { service.service(); @@ -84,17 +87,21 @@ public class CircuitBreakerTests { assertEquals(4, service.getCount()); Advised advised = (Advised) service; Advisor advisor = advised.getAdvisors()[0]; - Map delegates = (Map) new DirectFieldAccessor(advisor).getPropertyValue("advice.delegates"); + Map delegates = (Map) new DirectFieldAccessor(advisor) + .getPropertyValue("advice.delegates"); assertTrue(delegates.size() == 1); Map methodMap = (Map) delegates.values().iterator().next(); MethodInterceptor interceptor = (MethodInterceptor) methodMap .get(Service.class.getDeclaredMethod("expressionService")); DirectFieldAccessor accessor = new DirectFieldAccessor(interceptor); - assertEquals(8, accessor.getPropertyValue("retryOperations.retryPolicy.delegate.maxAttempts")) ; - assertEquals(19000L, accessor.getPropertyValue("retryOperations.retryPolicy.openTimeout")) ; - assertEquals(20000L, accessor.getPropertyValue("retryOperations.retryPolicy.resetTimeout")) ; - assertEquals("#root instanceof RuntimeExpression", - accessor.getPropertyValue("retryOperations.retryPolicy.delegate.expression.expression")); + assertEquals(8, accessor + .getPropertyValue("retryOperations.retryPolicy.delegate.maxAttempts")); + assertEquals(19000L, + accessor.getPropertyValue("retryOperations.retryPolicy.openTimeout")); + assertEquals(20000L, + accessor.getPropertyValue("retryOperations.retryPolicy.resetTimeout")); + assertEquals("#root instanceof RuntimeExpression", accessor.getPropertyValue( + "retryOperations.retryPolicy.delegate.expression.expression")); context.close(); } @@ -123,15 +130,11 @@ public class CircuitBreakerTests { } } - @CircuitBreaker(maxAttemptsExpression = "#{2 * ${foo:4}}", - openTimeoutExpression = "#{${bar:19}000}", - resetTimeoutExpression = "#{${baz:20}000}", - exceptionExpression = "#{#root instanceof RuntimeExpression}") + @CircuitBreaker(maxAttemptsExpression = "#{2 * ${foo:4}}", openTimeoutExpression = "#{${bar:19}000}", resetTimeoutExpression = "#{${baz:20}000}", exceptionExpression = "#{#root instanceof RuntimeExpression}") public void expressionService() { this.count++; } - public RetryContext getContext() { return this.context; } diff --git a/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java b/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java index e68d5da..98643d8 100644 --- a/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java +++ b/src/test/java/org/springframework/retry/annotation/EnableRetryTests.java @@ -190,7 +190,8 @@ public class EnableRetryTests { @Test public void testImplementation() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TestConfiguration.class); + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( + TestConfiguration.class); NotAnnotatedInterface service = context.getBean(NotAnnotatedInterface.class); service.service1(); service.service2(); @@ -198,7 +199,6 @@ public class EnableRetryTests { context.close(); } - @Test public void testExpression() throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( @@ -243,7 +243,7 @@ public class EnableRetryTests { return target; } try { - return target(((Advised)target).getTargetSource().getTarget()); + return target(((Advised) target).getTargetSource().getTarget()); } catch (Exception e) { throw new IllegalStateException(e); @@ -469,6 +469,7 @@ public class EnableRetryTests { protected static class ExcludesOnlyService { private int count = 0; + private RuntimeException exceptionToThrow; @Retryable(exclude = IllegalStateException.class) @@ -485,6 +486,7 @@ public class EnableRetryTests { public void setExceptionToThrow(RuntimeException exceptionToThrow) { this.exceptionToThrow = exceptionToThrow; } + } protected static class StatefulService { @@ -636,5 +638,4 @@ public class EnableRetryTests { } - } diff --git a/src/test/java/org/springframework/retry/annotation/EnableRetryWithBackoffTests.java b/src/test/java/org/springframework/retry/annotation/EnableRetryWithBackoffTests.java index a9c86bd..ba70463 100644 --- a/src/test/java/org/springframework/retry/annotation/EnableRetryWithBackoffTests.java +++ b/src/test/java/org/springframework/retry/annotation/EnableRetryWithBackoffTests.java @@ -42,8 +42,8 @@ public class EnableRetryWithBackoffTests { TestConfiguration.class); Service service = context.getBean(Service.class); service.service(); - assertEquals("[1000, 1000]", context.getBean(PeriodSleeper.class) - .getPeriods().toString()); + assertEquals("[1000, 1000]", + context.getBean(PeriodSleeper.class).getPeriods().toString()); assertEquals(3, service.getCount()); context.close(); } @@ -67,8 +67,8 @@ public class EnableRetryWithBackoffTests { ExponentialService service = context.getBean(ExponentialService.class); service.service(); assertEquals(3, service.getCount()); - assertEquals("[1000, 1100]", context.getBean(PeriodSleeper.class) - .getPeriods().toString()); + assertEquals("[1000, 1100]", + context.getBean(PeriodSleeper.class).getPeriods().toString()); context.close(); } @@ -81,11 +81,11 @@ public class EnableRetryWithBackoffTests { service.service(1); assertEquals(3, service.getCount()); List periods = context.getBean(PeriodSleeper.class).getPeriods(); - assertNotEquals("[1000, 1100]", context.getBean(PeriodSleeper.class) - .getPeriods().toString()); + assertNotEquals("[1000, 1100]", + context.getBean(PeriodSleeper.class).getPeriods().toString()); assertTrue("Wrong periods: " + periods, periods.get(0) > 1000); - assertTrue("Wrong periods: " + periods, periods.get(1) > 1100 - && periods.get(1) < 1210); + assertTrue("Wrong periods: " + periods, + periods.get(1) > 1100 && periods.get(1) < 1210); context.close(); } @@ -204,4 +204,5 @@ public class EnableRetryWithBackoffTests { } } + } diff --git a/src/test/java/org/springframework/retry/annotation/EnableRetryWithListenersTests.java b/src/test/java/org/springframework/retry/annotation/EnableRetryWithListenersTests.java index b140249..9e808f2 100644 --- a/src/test/java/org/springframework/retry/annotation/EnableRetryWithListenersTests.java +++ b/src/test/java/org/springframework/retry/annotation/EnableRetryWithListenersTests.java @@ -47,7 +47,8 @@ public class EnableRetryWithListenersTests { public void overrideListener() { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( TestConfigurationMultipleListeners.class); - ServiceWithOverriddenListener service = context.getBean(ServiceWithOverriddenListener.class); + ServiceWithOverriddenListener service = context + .getBean(ServiceWithOverriddenListener.class); service.service(); assertEquals(1, context.getBean(TestConfigurationMultipleListeners.class).count1); assertEquals(0, context.getBean(TestConfigurationMultipleListeners.class).count2); @@ -83,6 +84,7 @@ public class EnableRetryWithListenersTests { protected static class TestConfigurationMultipleListeners { private int count1 = 0; + private int count2 = 0; @Bean @@ -95,7 +97,7 @@ public class EnableRetryWithListenersTests { return new RetryListenerSupport() { @Override public void close(RetryContext context, - RetryCallback callback, Throwable throwable) { + RetryCallback callback, Throwable throwable) { count1++; } }; @@ -106,7 +108,7 @@ public class EnableRetryWithListenersTests { return new RetryListenerSupport() { @Override public void close(RetryContext context, - RetryCallback callback, Throwable throwable) { + RetryCallback callback, Throwable throwable) { count2++; } }; diff --git a/src/test/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandlerTests.java b/src/test/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandlerTests.java index 3c764e3..8509ff9 100644 --- a/src/test/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandlerTests.java +++ b/src/test/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandlerTests.java @@ -39,10 +39,10 @@ public class RecoverAnnotationRecoveryHandlerTests { @Test public void defaultRecoverMethod() { RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( - new DefaultRecover(), ReflectionUtils.findMethod(DefaultRecover.class, - "foo", String.class)); - assertEquals(1, - handler.recover(new Object[] { "Dave" }, new RuntimeException("Planned"))); + new DefaultRecover(), + ReflectionUtils.findMethod(DefaultRecover.class, "foo", String.class)); + assertEquals(1, handler.recover(new Object[] { "Dave" }, + new RuntimeException("Planned"))); } @Test @@ -50,8 +50,8 @@ public class RecoverAnnotationRecoveryHandlerTests { RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( new FewerArgs(), ReflectionUtils.findMethod(FewerArgs.class, "foo", String.class, int.class)); - assertEquals(1, - handler.recover(new Object[] { "Dave" }, new RuntimeException("Planned"))); + assertEquals(1, handler.recover(new Object[] { "Dave" }, + new RuntimeException("Planned"))); } @Test @@ -66,8 +66,8 @@ public class RecoverAnnotationRecoveryHandlerTests { @Test public void noMatch() { RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( - new SpecificException(), ReflectionUtils.findMethod( - SpecificException.class, "foo", String.class)); + new SpecificException(), + ReflectionUtils.findMethod(SpecificException.class, "foo", String.class)); expected.expect(ExhaustedRetryException.class); handler.recover(new Object[] { "Dave" }, new Error("Planned")); } @@ -75,60 +75,60 @@ public class RecoverAnnotationRecoveryHandlerTests { @Test public void specificRecoverMethod() { RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( - new SpecificRecover(), ReflectionUtils.findMethod(SpecificRecover.class, - "foo", String.class)); - assertEquals(2, - handler.recover(new Object[] { "Dave" }, new RuntimeException("Planned"))); + new SpecificRecover(), + ReflectionUtils.findMethod(SpecificRecover.class, "foo", String.class)); + assertEquals(2, handler.recover(new Object[] { "Dave" }, + new RuntimeException("Planned"))); } @Test - public void inAccessibleRecoverMethods (){ - Method foo = ReflectionUtils.findMethod(InAccessibleRecover.class, - "foo", String.class); + public void inAccessibleRecoverMethods() { + Method foo = ReflectionUtils.findMethod(InAccessibleRecover.class, "foo", + String.class); RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( new InAccessibleRecover(), foo); - assertEquals(1, - handler.recover(new Object[] { "Dave" }, new RuntimeException("Planned"))); + assertEquals(1, handler.recover(new Object[] { "Dave" }, + new RuntimeException("Planned"))); } @Test public void specificReturnTypeRecoverMethod() { RecoverAnnotationRecoveryHandler fooHandler = new RecoverAnnotationRecoveryHandler( - new InheritanceReturnTypeRecover(), ReflectionUtils.findMethod(InheritanceReturnTypeRecover.class, - "foo", String.class)); - assertEquals(1, - fooHandler.recover(new Object[] { "Aldo" }, new RuntimeException("Planned"))); - assertEquals(2, - fooHandler.recover(new Object[] { "Aldo" }, new IllegalStateException("Planned"))); + new InheritanceReturnTypeRecover(), ReflectionUtils.findMethod( + InheritanceReturnTypeRecover.class, "foo", String.class)); + assertEquals(1, fooHandler.recover(new Object[] { "Aldo" }, + new RuntimeException("Planned"))); + assertEquals(2, fooHandler.recover(new Object[] { "Aldo" }, + new IllegalStateException("Planned"))); } @Test public void parentReturnTypeRecoverMethod() { RecoverAnnotationRecoveryHandler barHandler = new RecoverAnnotationRecoveryHandler( - new InheritanceReturnTypeRecover(), ReflectionUtils.findMethod(InheritanceReturnTypeRecover.class, - "bar", String.class)); - assertEquals(3, - barHandler.recover(new Object[] { "Aldo" }, new RuntimeException("Planned"))); + new InheritanceReturnTypeRecover(), ReflectionUtils.findMethod( + InheritanceReturnTypeRecover.class, "bar", String.class)); + assertEquals(3, barHandler.recover(new Object[] { "Aldo" }, + new RuntimeException("Planned"))); } @Test - public void multipleQualifyingRecoverMethods(){ - Method foo = ReflectionUtils.findMethod(MultipleQualifyingRecovers.class, - "foo", String.class); + public void multipleQualifyingRecoverMethods() { + Method foo = ReflectionUtils.findMethod(MultipleQualifyingRecovers.class, "foo", + String.class); RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( new MultipleQualifyingRecovers(), foo); - assertEquals(1, - handler.recover(new Object[] { "Randell" }, new RuntimeException("Planned"))); + assertEquals(1, handler.recover(new Object[] { "Randell" }, + new RuntimeException("Planned"))); } @Test - public void multipleQualifyingRecoverMethodsWithNull(){ - Method foo = ReflectionUtils.findMethod(MultipleQualifyingRecovers.class, - "foo", String.class); + public void multipleQualifyingRecoverMethodsWithNull() { + Method foo = ReflectionUtils.findMethod(MultipleQualifyingRecovers.class, "foo", + String.class); RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( new MultipleQualifyingRecovers(), foo); assertEquals(1, @@ -137,40 +137,41 @@ public class RecoverAnnotationRecoveryHandlerTests { } @Test - public void multipleQualifyingRecoverMethodsReOrdered(){ + public void multipleQualifyingRecoverMethodsReOrdered() { Method foo = ReflectionUtils.findMethod(MultipleQualifyingRecoversReOrdered.class, "foo", String.class); RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( new MultipleQualifyingRecoversReOrdered(), foo); - assertEquals(3, - handler.recover(new Object[] { "Randell" }, new RuntimeException("Planned"))); + assertEquals(3, handler.recover(new Object[] { "Randell" }, + new RuntimeException("Planned"))); } - - @Test - public void multipleQualifyingRecoverMethodsExtendsThrowable(){ - Method foo = ReflectionUtils.findMethod(MultipleQualifyingRecoversExtendsThrowable.class, - "foo", String.class); + + @Test + public void multipleQualifyingRecoverMethodsExtendsThrowable() { + Method foo = ReflectionUtils.findMethod( + MultipleQualifyingRecoversExtendsThrowable.class, "foo", String.class); RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( new MultipleQualifyingRecoversExtendsThrowable(), foo); - assertEquals(2, - handler.recover(new Object[] { "Kevin" }, new IllegalArgumentException("Planned"))); - assertEquals(3, - handler.recover(new Object[] { "Kevin" }, new UnsupportedOperationException("Planned"))); + assertEquals(2, handler.recover(new Object[] { "Kevin" }, + new IllegalArgumentException("Planned"))); + assertEquals(3, handler.recover(new Object[] { "Kevin" }, + new UnsupportedOperationException("Planned"))); } private static class InAccessibleRecover { @Retryable - private int foo (String n) { + private int foo(String n) { throw new RuntimeException("error trying to foo('" + n + "')"); } @Recover - private int bar(String n){ - return 1 ; + private int bar(String n) { + return 1; } + } protected static class DefaultRecover { @@ -184,9 +185,11 @@ public class RecoverAnnotationRecoveryHandlerTests { public int bar(String name) { return 1; } + } protected static class NoArgs { + private Throwable cause; @Retryable @@ -201,9 +204,11 @@ public class RecoverAnnotationRecoveryHandlerTests { public Throwable getCause() { return cause; } + } protected static class SpecificRecover { + @Retryable public int foo(String name) { return 0; @@ -222,6 +227,7 @@ public class RecoverAnnotationRecoveryHandlerTests { } protected static class FewerArgs { + @Retryable public int foo(String name, int value) { return 0; @@ -235,6 +241,7 @@ public class RecoverAnnotationRecoveryHandlerTests { } protected static class SpecificException { + @Retryable public int foo(String name) { return 0; @@ -323,8 +330,8 @@ public class RecoverAnnotationRecoveryHandlerTests { } } - - protected static class MultipleQualifyingRecoversExtendsThrowable { + + protected static class MultipleQualifyingRecoversExtendsThrowable { @Retryable public int foo(String name) { @@ -335,8 +342,8 @@ public class RecoverAnnotationRecoveryHandlerTests { public int fooRecover(IllegalArgumentException e, String name) { return 1; } - - @Recover + + @Recover public int barRecover(IllegalArgumentException e, String name) { return 2; } diff --git a/src/test/java/org/springframework/retry/backoff/DummySleeper.java b/src/test/java/org/springframework/retry/backoff/DummySleeper.java index f796000..159943f 100644 --- a/src/test/java/org/springframework/retry/backoff/DummySleeper.java +++ b/src/test/java/org/springframework/retry/backoff/DummySleeper.java @@ -21,9 +21,9 @@ import java.util.List; /** * Simple {@link Sleeper} implementation that just waits on a local Object. - * + * * @author Dave Syer - * + * */ @SuppressWarnings("serial") public class DummySleeper implements Sleeper { @@ -35,21 +35,22 @@ public class DummySleeper implements Sleeper { * @return the lastBackOff */ public long getLastBackOff() { - return backOffs.get(backOffs.size()-1).longValue(); + return backOffs.get(backOffs.size() - 1).longValue(); } - + public long[] getBackOffs() { long[] result = new long[backOffs.size()]; int i = 0; for (Iterator iterator = backOffs.iterator(); iterator.hasNext();) { Long value = iterator.next(); - result[i++] =value.longValue(); + result[i++] = value.longValue(); } - return result ; + return result; } /* * (non-Javadoc) + * * @see org.springframework.batch.retry.backoff.Sleeper#sleep(long) */ public void sleep(long backOffPeriod) throws InterruptedException { diff --git a/src/test/java/org/springframework/retry/backoff/ExponentialBackOffPolicyTests.java b/src/test/java/org/springframework/retry/backoff/ExponentialBackOffPolicyTests.java index b70a99b..6db7088 100644 --- a/src/test/java/org/springframework/retry/backoff/ExponentialBackOffPolicyTests.java +++ b/src/test/java/org/springframework/retry/backoff/ExponentialBackOffPolicyTests.java @@ -63,7 +63,8 @@ public class ExponentialBackOffPolicyTests { strategy.setSleeper(sleeper); BackOffContext context = strategy.start(null); strategy.backOff(context); - assertEquals(ExponentialBackOffPolicy.DEFAULT_INITIAL_INTERVAL, sleeper.getLastBackOff()); + assertEquals(ExponentialBackOffPolicy.DEFAULT_INITIAL_INTERVAL, + sleeper.getLastBackOff()); } @Test diff --git a/src/test/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicyTests.java b/src/test/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicyTests.java index 891d317..dc8082a 100644 --- a/src/test/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicyTests.java +++ b/src/test/java/org/springframework/retry/backoff/ExponentialRandomBackOffPolicyTests.java @@ -32,53 +32,60 @@ import org.springframework.retry.support.RetrySimulator; * */ public class ExponentialRandomBackOffPolicyTests { - static final int NUM_TRIALS = 10000; - static final int MAX_RETRIES = 6; - private ExponentialBackOffPolicy makeBackoffPolicy() { - ExponentialBackOffPolicy policy = new ExponentialRandomBackOffPolicy(); - policy.setInitialInterval(50); - policy.setMultiplier(2.0); - policy.setMaxInterval(3000); - return policy; - } + static final int NUM_TRIALS = 10000; + static final int MAX_RETRIES = 6; - private SimpleRetryPolicy makeRetryPolicy() { - SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); - retryPolicy.setMaxAttempts(MAX_RETRIES); - return retryPolicy; - } + private ExponentialBackOffPolicy makeBackoffPolicy() { + ExponentialBackOffPolicy policy = new ExponentialRandomBackOffPolicy(); + policy.setInitialInterval(50); + policy.setMultiplier(2.0); + policy.setMaxInterval(3000); + return policy; + } + + private SimpleRetryPolicy makeRetryPolicy() { + SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(); + retryPolicy.setMaxAttempts(MAX_RETRIES); + return retryPolicy; + } @Test - public void testSingleBackoff() throws Exception { - ExponentialBackOffPolicy backOffPolicy = makeBackoffPolicy(); - RetrySimulator simulator = new RetrySimulator(backOffPolicy, makeRetryPolicy()); - RetrySimulation simulation = simulator.executeSimulation(1); + public void testSingleBackoff() throws Exception { + ExponentialBackOffPolicy backOffPolicy = makeBackoffPolicy(); + RetrySimulator simulator = new RetrySimulator(backOffPolicy, makeRetryPolicy()); + RetrySimulation simulation = simulator.executeSimulation(1); - List sleeps = simulation.getLongestTotalSleepSequence().getSleeps(); - System.out.println("Single trial of " + backOffPolicy + ": sleeps=" + sleeps); - assertEquals(MAX_RETRIES - 1, sleeps.size()); - long initialInterval = backOffPolicy.getInitialInterval(); - for (int i=0; i sleeps = simulation.getLongestTotalSleepSequence().getSleeps(); + System.out.println("Single trial of " + backOffPolicy + ": sleeps=" + sleeps); + assertEquals(MAX_RETRIES - 1, sleeps.size()); + long initialInterval = backOffPolicy.getInitialInterval(); + for (int i = 0; i < sleeps.size(); i++) { + long expectedMaxValue = 2 * (long) (initialInterval + initialInterval + * Math.max(1, Math.pow(backOffPolicy.getMultiplier(), i))); + assertTrue( + "Found a sleep [" + sleeps.get(i) + + "] which exceeds our max expected value of " + + expectedMaxValue + " at interval " + i, + sleeps.get(i) < expectedMaxValue); + } + } @Test public void testMultiBackOff() throws Exception { - ExponentialBackOffPolicy backOffPolicy = makeBackoffPolicy(); - RetrySimulator simulator = new RetrySimulator(backOffPolicy, makeRetryPolicy()); - RetrySimulation simulation = simulator.executeSimulation(NUM_TRIALS); + ExponentialBackOffPolicy backOffPolicy = makeBackoffPolicy(); + RetrySimulator simulator = new RetrySimulator(backOffPolicy, makeRetryPolicy()); + RetrySimulation simulation = simulator.executeSimulation(NUM_TRIALS); - System.out.println("Ran " + NUM_TRIALS + " backoff trials. Each trial retried " + MAX_RETRIES + " times"); - System.out.println("Policy: " + backOffPolicy); - System.out.println("All generated backoffs:"); - System.out.println(" " + simulation.getPercentiles()); + System.out.println("Ran " + NUM_TRIALS + " backoff trials. Each trial retried " + + MAX_RETRIES + " times"); + System.out.println("Policy: " + backOffPolicy); + System.out.println("All generated backoffs:"); + System.out.println(" " + simulation.getPercentiles()); - System.out.println("Backoff frequencies:"); - System.out.print(" " + simulation.getPercentiles()); + System.out.println("Backoff frequencies:"); + System.out.print(" " + simulation.getPercentiles()); } + } diff --git a/src/test/java/org/springframework/retry/backoff/ThreadWaitSleeperTests.java b/src/test/java/org/springframework/retry/backoff/ThreadWaitSleeperTests.java index 3dba38c..a3d03e6 100644 --- a/src/test/java/org/springframework/retry/backoff/ThreadWaitSleeperTests.java +++ b/src/test/java/org/springframework/retry/backoff/ThreadWaitSleeperTests.java @@ -39,8 +39,8 @@ public class ThreadWaitSleeperTests { private void assertEqualsApprox(long desired, long actual, long variance) { long lower = desired - variance; long upper = desired + 2 * variance; - assertTrue("Expected value to be between '" + lower + "' and '" + upper + "' but was '" + actual + "'", - lower <= actual); + assertTrue("Expected value to be between '" + lower + "' and '" + upper + + "' but was '" + actual + "'", lower <= actual); } } diff --git a/src/test/java/org/springframework/retry/interceptor/RetryInterceptorBuilderTests.java b/src/test/java/org/springframework/retry/interceptor/RetryInterceptorBuilderTests.java index f553879..c4f6599 100644 --- a/src/test/java/org/springframework/retry/interceptor/RetryInterceptorBuilderTests.java +++ b/src/test/java/org/springframework/retry/interceptor/RetryInterceptorBuilderTests.java @@ -44,74 +44,76 @@ public class RetryInterceptorBuilderTests { @Test public void testBasic() { - StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder.stateful().build(); - assertEquals(3, TestUtils.getPropertyValue(interceptor, "retryOperations.retryPolicy.maxAttempts")); + StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder + .stateful().build(); + assertEquals(3, TestUtils.getPropertyValue(interceptor, + "retryOperations.retryPolicy.maxAttempts")); } @Test public void testWithCustomRetryTemplate() { RetryOperations retryOperations = new RetryTemplate(); - StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder.stateful() - .retryOperations(retryOperations) - .build(); - assertEquals(3, TestUtils.getPropertyValue(interceptor, "retryOperations.retryPolicy.maxAttempts")); - assertSame(retryOperations, TestUtils.getPropertyValue(interceptor, "retryOperations")); + StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder + .stateful().retryOperations(retryOperations).build(); + assertEquals(3, TestUtils.getPropertyValue(interceptor, + "retryOperations.retryPolicy.maxAttempts")); + assertSame(retryOperations, + TestUtils.getPropertyValue(interceptor, "retryOperations")); } @Test public void testWithMoreAttempts() { - StatefulRetryOperationsInterceptor interceptor = - RetryInterceptorBuilder.stateful() - .maxAttempts(5) - .build(); - assertEquals(5, TestUtils.getPropertyValue(interceptor, "retryOperations.retryPolicy.maxAttempts")); + StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder + .stateful().maxAttempts(5).build(); + assertEquals(5, TestUtils.getPropertyValue(interceptor, + "retryOperations.retryPolicy.maxAttempts")); } @Test public void testWithCustomizedBackOffMoreAttempts() { - StatefulRetryOperationsInterceptor interceptor = - RetryInterceptorBuilder.stateful() - .maxAttempts(5) - .backOffOptions(1, 2, 10) - .build(); + StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder + .stateful().maxAttempts(5).backOffOptions(1, 2, 10).build(); - assertEquals(5, TestUtils.getPropertyValue(interceptor, "retryOperations.retryPolicy.maxAttempts")); - assertEquals(1L, TestUtils.getPropertyValue(interceptor, "retryOperations.backOffPolicy.initialInterval")); - assertEquals(2.0, TestUtils.getPropertyValue(interceptor, "retryOperations.backOffPolicy.multiplier")); - assertEquals(10L, TestUtils.getPropertyValue(interceptor, "retryOperations.backOffPolicy.maxInterval")); + assertEquals(5, TestUtils.getPropertyValue(interceptor, + "retryOperations.retryPolicy.maxAttempts")); + assertEquals(1L, TestUtils.getPropertyValue(interceptor, + "retryOperations.backOffPolicy.initialInterval")); + assertEquals(2.0, TestUtils.getPropertyValue(interceptor, + "retryOperations.backOffPolicy.multiplier")); + assertEquals(10L, TestUtils.getPropertyValue(interceptor, + "retryOperations.backOffPolicy.maxInterval")); } @Test public void testWithCustomBackOffPolicy() { - StatefulRetryOperationsInterceptor interceptor = - RetryInterceptorBuilder.stateful() - .maxAttempts(5) - .backOffPolicy(new FixedBackOffPolicy()) - .build(); + StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder + .stateful().maxAttempts(5).backOffPolicy(new FixedBackOffPolicy()) + .build(); - assertEquals(5, TestUtils.getPropertyValue(interceptor, "retryOperations.retryPolicy.maxAttempts")); - assertEquals(1000L, TestUtils.getPropertyValue(interceptor, "retryOperations.backOffPolicy.backOffPeriod")); + assertEquals(5, TestUtils.getPropertyValue(interceptor, + "retryOperations.retryPolicy.maxAttempts")); + assertEquals(1000L, TestUtils.getPropertyValue(interceptor, + "retryOperations.backOffPolicy.backOffPeriod")); } @Test public void testWithCustomNewMessageIdentifier() throws Exception { final CountDownLatch latch = new CountDownLatch(1); - StatefulRetryOperationsInterceptor interceptor = - RetryInterceptorBuilder.stateful() - .maxAttempts(5) - .newMethodArgumentsIdentifier(new NewMethodArgumentsIdentifier() { + StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder + .stateful().maxAttempts(5) + .newMethodArgumentsIdentifier(new NewMethodArgumentsIdentifier() { - @Override - public boolean isNew(Object[] args) { - latch.countDown(); - return false; - } - }) - .backOffPolicy(new FixedBackOffPolicy()) - .build(); + @Override + public boolean isNew(Object[] args) { + latch.countDown(); + return false; + } + }).backOffPolicy(new FixedBackOffPolicy()).build(); - assertEquals(5, TestUtils.getPropertyValue(interceptor, "retryOperations.retryPolicy.maxAttempts")); - assertEquals(1000L, TestUtils.getPropertyValue(interceptor, "retryOperations.backOffPolicy.backOffPeriod")); + assertEquals(5, TestUtils.getPropertyValue(interceptor, + "retryOperations.retryPolicy.maxAttempts")); + assertEquals(1000L, TestUtils.getPropertyValue(interceptor, + "retryOperations.backOffPolicy.backOffPeriod")); final AtomicInteger count = new AtomicInteger(); Foo delegate = createDelegate(interceptor, count); Object message = ""; @@ -127,28 +129,32 @@ public class RetryInterceptorBuilderTests { @Test public void testWitCustomRetryPolicyTraverseCause() { - StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder.stateful() - .retryPolicy(new SimpleRetryPolicy(15, Collections - ., Boolean> singletonMap(Exception.class, true), true)) + StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder + .stateful() + .retryPolicy(new SimpleRetryPolicy(15, + Collections., Boolean>singletonMap( + Exception.class, true), + true)) .build(); - assertEquals(15, TestUtils.getPropertyValue(interceptor, "retryOperations.retryPolicy.maxAttempts")); + assertEquals(15, TestUtils.getPropertyValue(interceptor, + "retryOperations.retryPolicy.maxAttempts")); } @Test public void testWithCustomKeyGenerator() throws Exception { final CountDownLatch latch = new CountDownLatch(1); - StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder.stateful() - .keyGenerator(new MethodArgumentsKeyGenerator() { + StatefulRetryOperationsInterceptor interceptor = RetryInterceptorBuilder + .stateful().keyGenerator(new MethodArgumentsKeyGenerator() { @Override public Object getKey(Object[] item) { latch.countDown(); return "foo"; } - }) - .build(); + }).build(); - assertEquals(3, TestUtils.getPropertyValue(interceptor, "retryOperations.retryPolicy.maxAttempts")); + assertEquals(3, TestUtils.getPropertyValue(interceptor, + "retryOperations.retryPolicy.maxAttempts")); final AtomicInteger count = new AtomicInteger(); Foo delegate = createDelegate(interceptor, count); Object message = ""; @@ -184,6 +190,7 @@ public class RetryInterceptorBuilderTests { static interface Foo { void onMessage(String s, Object message); + } } diff --git a/src/test/java/org/springframework/retry/interceptor/RetryOperationsInterceptorTests.java b/src/test/java/org/springframework/retry/interceptor/RetryOperationsInterceptorTests.java index 139cdc5..94d20ac 100644 --- a/src/test/java/org/springframework/retry/interceptor/RetryOperationsInterceptorTests.java +++ b/src/test/java/org/springframework/retry/interceptor/RetryOperationsInterceptorTests.java @@ -71,7 +71,8 @@ public class RetryOperationsInterceptorTests { }); interceptor.setRetryOperations(retryTemplate); target = new ServiceImpl(); - service = (Service) ProxyFactory.getProxy(Service.class, new SingletonTargetSource(target)); + service = (Service) ProxyFactory.getProxy(Service.class, + new SingletonTargetSource(target)); count = 0; transactionCount = 0; } @@ -193,9 +194,11 @@ public class RetryOperationsInterceptorTests { } public static interface Service { + void service() throws Exception; void doTansactional() throws Exception; + } public static class ServiceImpl implements Service { @@ -228,4 +231,5 @@ public class RetryOperationsInterceptorTests { } } + } diff --git a/src/test/java/org/springframework/retry/interceptor/StatefulRetryOperationsInterceptorTests.java b/src/test/java/org/springframework/retry/interceptor/StatefulRetryOperationsInterceptorTests.java index fdbbf84..522a655 100644 --- a/src/test/java/org/springframework/retry/interceptor/StatefulRetryOperationsInterceptorTests.java +++ b/src/test/java/org/springframework/retry/interceptor/StatefulRetryOperationsInterceptorTests.java @@ -263,8 +263,10 @@ public class StatefulRetryOperationsInterceptorTests { MethodInvocation invocation = mock(MethodInvocation.class); when(invocation.getArguments()).thenReturn(new Object[] { new Object() }); this.interceptor.invoke(invocation); - ArgumentCaptor captor = ArgumentCaptor.forClass(DefaultRetryState.class); - verify(template).execute(any(RetryCallback.class), any(RecoveryCallback.class), captor.capture()); + ArgumentCaptor captor = ArgumentCaptor + .forClass(DefaultRetryState.class); + verify(template).execute(any(RetryCallback.class), any(RecoveryCallback.class), + captor.capture()); assertNull(captor.getValue().getKey()); } @@ -285,8 +287,10 @@ public class StatefulRetryOperationsInterceptorTests { MethodInvocation invocation = mock(MethodInvocation.class); when(invocation.getArguments()).thenReturn(new Object[] { new Object() }); this.interceptor.invoke(invocation); - ArgumentCaptor captor = ArgumentCaptor.forClass(DefaultRetryState.class); - verify(template).execute(any(RetryCallback.class), any(RecoveryCallback.class), captor.capture()); + ArgumentCaptor captor = ArgumentCaptor + .forClass(DefaultRetryState.class); + verify(template).execute(any(RetryCallback.class), any(RecoveryCallback.class), + captor.capture()); assertEquals("bar", captor.getValue().getKey()); } @@ -318,7 +322,9 @@ public class StatefulRetryOperationsInterceptorTests { } public static interface Service { + void service(String in) throws Exception; + } public static class ServiceImpl implements Service { @@ -334,7 +340,9 @@ public class StatefulRetryOperationsInterceptorTests { } public static interface Transformer { + Collection transform(String in) throws Exception; + } public static class TransformerImpl implements Transformer { @@ -349,4 +357,5 @@ public class StatefulRetryOperationsInterceptorTests { } } + } diff --git a/src/test/java/org/springframework/retry/listener/RetryListenerTests.java b/src/test/java/org/springframework/retry/listener/RetryListenerTests.java index 5e5f230..a479f6f 100644 --- a/src/test/java/org/springframework/retry/listener/RetryListenerTests.java +++ b/src/test/java/org/springframework/retry/listener/RetryListenerTests.java @@ -42,13 +42,15 @@ public class RetryListenerTests { @Test public void testOpenInterceptors() throws Throwable { template.setListeners(new RetryListener[] { new RetryListenerSupport() { - public boolean open(RetryContext context, RetryCallback callback) { + public boolean open(RetryContext context, + RetryCallback callback) { count++; list.add("1:" + count); return true; } }, new RetryListenerSupport() { - public boolean open(RetryContext context, RetryCallback callback) { + public boolean open(RetryContext context, + RetryCallback callback) { count++; list.add("2:" + count); return true; @@ -67,7 +69,8 @@ public class RetryListenerTests { @Test public void testOpenCanVetoRetry() throws Throwable { template.registerListener(new RetryListenerSupport() { - public boolean open(RetryContext context, RetryCallback callback) { + public boolean open(RetryContext context, + RetryCallback callback) { list.add("1"); return false; } @@ -92,12 +95,14 @@ public class RetryListenerTests { @Test public void testCloseInterceptors() throws Throwable { template.setListeners(new RetryListener[] { new RetryListenerSupport() { - public void close(RetryContext context, RetryCallback callback, Throwable t) { + public void close(RetryContext context, + RetryCallback callback, Throwable t) { count++; list.add("1:" + count); } }, new RetryListenerSupport() { - public void close(RetryContext context, RetryCallback callback, Throwable t) { + public void close(RetryContext context, + RetryCallback callback, Throwable t) { count++; list.add("2:" + count); } @@ -117,11 +122,13 @@ public class RetryListenerTests { public void testOnError() throws Throwable { template.setRetryPolicy(new NeverRetryPolicy()); template.setListeners(new RetryListener[] { new RetryListenerSupport() { - public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { list.add("1"); } }, new RetryListenerSupport() { - public void onError(RetryContext context, RetryCallback callback, Throwable throwable) { + public void onError(RetryContext context, + RetryCallback callback, Throwable throwable) { list.add("2"); } } }); @@ -148,7 +155,8 @@ public class RetryListenerTests { @Test public void testCloseInterceptorsAfterRetry() throws Throwable { template.registerListener(new RetryListenerSupport() { - public void close(RetryContext context, RetryCallback callback, Throwable t) { + public void close(RetryContext context, + RetryCallback callback, Throwable t) { list.add("" + count); // The last attempt should have been successful: assertNull(t); @@ -167,4 +175,5 @@ public class RetryListenerTests { // We succeeded on the second try: assertEquals("2", list.get(0)); } + } diff --git a/src/test/java/org/springframework/retry/policy/AlwaysRetryPolicyTests.java b/src/test/java/org/springframework/retry/policy/AlwaysRetryPolicyTests.java index 6bf4d0d..1839521 100644 --- a/src/test/java/org/springframework/retry/policy/AlwaysRetryPolicyTests.java +++ b/src/test/java/org/springframework/retry/policy/AlwaysRetryPolicyTests.java @@ -59,4 +59,5 @@ public class AlwaysRetryPolicyTests { assertNotSame(child, context); assertSame(context, child.getParent()); } + } diff --git a/src/test/java/org/springframework/retry/policy/CircuitBreakerRetryTemplateTests.java b/src/test/java/org/springframework/retry/policy/CircuitBreakerRetryTemplateTests.java index 79fbc6e..719777c 100644 --- a/src/test/java/org/springframework/retry/policy/CircuitBreakerRetryTemplateTests.java +++ b/src/test/java/org/springframework/retry/policy/CircuitBreakerRetryTemplateTests.java @@ -37,10 +37,15 @@ import org.springframework.retry.support.RetryTemplate; public class CircuitBreakerRetryTemplateTests { private static final String RECOVERED = "RECOVERED"; + private static final String RESULT = "RESULT"; + private RetryTemplate retryTemplate; + private RecoveryCallback recovery; + private MockRetryCallback callback; + private DefaultRetryState state; @Before @@ -79,13 +84,15 @@ public class CircuitBreakerRetryTemplateTests { this.retryTemplate.setThrowLastExceptionOnExhausted(true); try { this.retryTemplate.execute(this.callback, this.state); - } catch (Exception e) { + } + catch (Exception e) { assertEquals(this.callback.exceptionToThrow, e); assertEquals(1, this.callback.getAttempts()); } try { this.retryTemplate.execute(this.callback, this.state); - } catch (Exception e) { + } + catch (Exception e) { assertEquals(this.callback.exceptionToThrow, e); // circuit is now open so no more attempts assertEquals(1, this.callback.getAttempts()); @@ -184,6 +191,7 @@ public class CircuitBreakerRetryTemplateTests { public void setExceptionToThrow(Exception exceptionToThrow) { this.exceptionToThrow = exceptionToThrow; } + } } diff --git a/src/test/java/org/springframework/retry/policy/CompositeRetryPolicyTests.java b/src/test/java/org/springframework/retry/policy/CompositeRetryPolicyTests.java index b546859..4e08b99 100644 --- a/src/test/java/org/springframework/retry/policy/CompositeRetryPolicyTests.java +++ b/src/test/java/org/springframework/retry/policy/CompositeRetryPolicyTests.java @@ -44,7 +44,8 @@ public class CompositeRetryPolicyTests { @Test public void testTrivialPolicies() throws Exception { CompositeRetryPolicy policy = new CompositeRetryPolicy(); - policy.setPolicies(new RetryPolicy[] { new MockRetryPolicySupport(), new MockRetryPolicySupport() }); + policy.setPolicies(new RetryPolicy[] { new MockRetryPolicySupport(), + new MockRetryPolicySupport() }); RetryContext context = policy.open(null); assertNotNull(context); assertTrue(policy.canRetry(context)); @@ -54,11 +55,12 @@ public class CompositeRetryPolicyTests { @Test public void testNonTrivialPolicies() throws Exception { CompositeRetryPolicy policy = new CompositeRetryPolicy(); - policy.setPolicies(new RetryPolicy[] { new MockRetryPolicySupport(), new MockRetryPolicySupport() { - public boolean canRetry(RetryContext context) { - return false; - } - } }); + policy.setPolicies(new RetryPolicy[] { new MockRetryPolicySupport(), + new MockRetryPolicySupport() { + public boolean canRetry(RetryContext context) { + return false; + } + } }); RetryContext context = policy.open(null); assertNotNull(context); assertFalse(policy.canRetry(context)); @@ -68,17 +70,19 @@ public class CompositeRetryPolicyTests { @Test public void testNonTrivialPoliciesWithThrowable() throws Exception { CompositeRetryPolicy policy = new CompositeRetryPolicy(); - policy.setPolicies(new RetryPolicy[] { new MockRetryPolicySupport(), new MockRetryPolicySupport() { - boolean errorRegistered = false; + policy.setPolicies(new RetryPolicy[] { new MockRetryPolicySupport(), + new MockRetryPolicySupport() { + boolean errorRegistered = false; - public boolean canRetry(RetryContext context) { - return !errorRegistered; - } + public boolean canRetry(RetryContext context) { + return !errorRegistered; + } - public void registerThrowable(RetryContext context, Throwable throwable) { - errorRegistered = true; - } - } }); + public void registerThrowable(RetryContext context, + Throwable throwable) { + errorRegistered = true; + } + } }); RetryContext context = policy.open(null); assertNotNull(context); assertTrue(policy.canRetry(context)); @@ -126,7 +130,8 @@ public class CompositeRetryPolicyTests { try { policy.close(context); fail("Expected RuntimeException"); - } catch (RuntimeException e) { + } + catch (RuntimeException e) { assertEquals("Pah!", e.getMessage()); } assertEquals(2, list.size()); @@ -135,7 +140,8 @@ public class CompositeRetryPolicyTests { @Test public void testRetryCount() throws Exception { CompositeRetryPolicy policy = new CompositeRetryPolicy(); - policy.setPolicies(new RetryPolicy[] { new MockRetryPolicySupport(), new MockRetryPolicySupport() }); + policy.setPolicies(new RetryPolicy[] { new MockRetryPolicySupport(), + new MockRetryPolicySupport() }); RetryContext context = policy.open(null); assertNotNull(context); policy.registerThrowable(context, null); @@ -168,4 +174,5 @@ public class CompositeRetryPolicyTests { assertNotNull(context); assertTrue(policy.canRetry(context)); } + } diff --git a/src/test/java/org/springframework/retry/policy/ExceptionClassifierRetryPolicyTests.java b/src/test/java/org/springframework/retry/policy/ExceptionClassifierRetryPolicyTests.java index 6dc1624..729a148 100644 --- a/src/test/java/org/springframework/retry/policy/ExceptionClassifierRetryPolicyTests.java +++ b/src/test/java/org/springframework/retry/policy/ExceptionClassifierRetryPolicyTests.java @@ -43,8 +43,9 @@ public class ExceptionClassifierRetryPolicyTests { @Test public void testTrivialPolicies() throws Exception { - policy.setPolicyMap(Collections., RetryPolicy> singletonMap(Exception.class, - new MockRetryPolicySupport())); + policy.setPolicyMap( + Collections., RetryPolicy>singletonMap( + Exception.class, new MockRetryPolicySupport())); RetryContext context = policy.open(null); assertNotNull(context); assertTrue(policy.canRetry(context)); @@ -59,8 +60,9 @@ public class ExceptionClassifierRetryPolicyTests { @Test public void testNullContext() throws Exception { - policy.setPolicyMap(Collections., RetryPolicy> singletonMap(Exception.class, - new NeverRetryPolicy())); + policy.setPolicyMap( + Collections., RetryPolicy>singletonMap( + Exception.class, new NeverRetryPolicy())); RetryContext context = policy.open(null); assertNotNull(context); diff --git a/src/test/java/org/springframework/retry/policy/FatalExceptionRetryPolicyTests.java b/src/test/java/org/springframework/retry/policy/FatalExceptionRetryPolicyTests.java index ae5b5a3..0a6ce32 100644 --- a/src/test/java/org/springframework/retry/policy/FatalExceptionRetryPolicyTests.java +++ b/src/test/java/org/springframework/retry/policy/FatalExceptionRetryPolicyTests.java @@ -87,14 +87,16 @@ public class FatalExceptionRetryPolicyTests { Object result = null; try { - retryTemplate.execute(callback, recoveryCallback, new DefaultRetryState("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 DefaultRetryState("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); @@ -115,6 +117,7 @@ public class FatalExceptionRetryPolicyTests { public void setExceptionToThrow(Exception exceptionToThrow) { this.exceptionToThrow = exceptionToThrow; } + } } diff --git a/src/test/java/org/springframework/retry/policy/MapRetryContextCacheTests.java b/src/test/java/org/springframework/retry/policy/MapRetryContextCacheTests.java index 99548d3..fccb85f 100644 --- a/src/test/java/org/springframework/retry/policy/MapRetryContextCacheTests.java +++ b/src/test/java/org/springframework/retry/policy/MapRetryContextCacheTests.java @@ -26,7 +26,7 @@ import org.springframework.retry.context.RetryContextSupport; public class MapRetryContextCacheTests { MapRetryContextCache cache = new MapRetryContextCache(); - + @Test public void testPut() { RetryContextSupport context = new RetryContextSupport(null); @@ -34,7 +34,7 @@ public class MapRetryContextCacheTests { assertEquals(context, cache.get("foo")); } - @Test(expected=RetryCacheCapacityExceededException.class) + @Test(expected = RetryCacheCapacityExceededException.class) public void testPutOverLimit() { RetryContextSupport context = new RetryContextSupport(null); cache.setCapacity(1); diff --git a/src/test/java/org/springframework/retry/policy/RetryContextSerializationTests.java b/src/test/java/org/springframework/retry/policy/RetryContextSerializationTests.java index e244445..9519105 100644 --- a/src/test/java/org/springframework/retry/policy/RetryContextSerializationTests.java +++ b/src/test/java/org/springframework/retry/policy/RetryContextSerializationTests.java @@ -56,21 +56,27 @@ public class RetryContextSerializationTests { @Parameters(name = "{index}: {0}") public static List policies() { List result = new ArrayList(); - ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true); + ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider( + true); scanner.addIncludeFilter(new AssignableTypeFilter(RetryPolicy.class)); scanner.addExcludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*Test.*"))); scanner.addExcludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*Mock.*"))); - Set candidates = scanner.findCandidateComponents("org.springframework.retry.policy"); + Set candidates = scanner + .findCandidateComponents("org.springframework.retry.policy"); 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(), e); + result.add(new Object[] { BeanUtils.instantiate(ClassUtils + .resolveClassName(beanDefinition.getBeanClassName(), null)) }); + } + catch (Exception e) { + logger.warn( + "Cannot create instance of " + beanDefinition.getBeanClassName(), + e); } } ExceptionClassifierRetryPolicy extra = new ExceptionClassifierRetryPolicy(); - extra.setExceptionClassifier(new SubclassClassifier(new AlwaysRetryPolicy())); + extra.setExceptionClassifier( + new SubclassClassifier(new AlwaysRetryPolicy())); result.add(new Object[] { extra }); return result; } @@ -86,12 +92,15 @@ public class RetryContextSerializationTests { policy.registerThrowable(context, new RuntimeException()); assertEquals(1, context.getRetryCount()); assertEquals(1, - ((RetryContext) SerializationUtils.deserialize(SerializationUtils.serialize(context))).getRetryCount()); + ((RetryContext) SerializationUtils + .deserialize(SerializationUtils.serialize(context))) + .getRetryCount()); } @Test public void testSerializationCycleForPolicy() { - assertTrue(SerializationUtils.deserialize(SerializationUtils.serialize(policy)) instanceof RetryPolicy); + assertTrue(SerializationUtils.deserialize( + SerializationUtils.serialize(policy)) instanceof RetryPolicy); } } diff --git a/src/test/java/org/springframework/retry/policy/SerializedMapRetryContextCache.java b/src/test/java/org/springframework/retry/policy/SerializedMapRetryContextCache.java index a028494..761028c 100644 --- a/src/test/java/org/springframework/retry/policy/SerializedMapRetryContextCache.java +++ b/src/test/java/org/springframework/retry/policy/SerializedMapRetryContextCache.java @@ -23,9 +23,11 @@ import org.springframework.retry.RetryContext; import org.springframework.util.SerializationUtils; public class SerializedMapRetryContextCache implements RetryContextCache { + private static final int DEFAULT_CAPACITY = 4096; - private Map map = Collections.synchronizedMap(new HashMap()); + private Map map = Collections + .synchronizedMap(new HashMap()); @Override public boolean containsKey(Object key) { @@ -53,4 +55,5 @@ public class SerializedMapRetryContextCache implements RetryContextCache { public void remove(Object key) { map.remove(key); } + } diff --git a/src/test/java/org/springframework/retry/policy/SimpleRetryPolicyTests.java b/src/test/java/org/springframework/retry/policy/SimpleRetryPolicyTests.java index 8b037b6..d7aefd2 100644 --- a/src/test/java/org/springframework/retry/policy/SimpleRetryPolicyTests.java +++ b/src/test/java/org/springframework/retry/policy/SimpleRetryPolicyTests.java @@ -44,8 +44,8 @@ public class SimpleRetryPolicyTests { public void testEmptyExceptionsNeverRetry() throws Exception { // We can't retry any exceptions... - SimpleRetryPolicy policy = new SimpleRetryPolicy(3, Collections - ., Boolean> emptyMap()); + SimpleRetryPolicy policy = new SimpleRetryPolicy(3, + Collections., Boolean>emptyMap()); RetryContext context = policy.open(null); // ...so we can't retry this one... @@ -57,8 +57,10 @@ public class SimpleRetryPolicyTests { public void testWithExceptionDefaultAlwaysRetry() throws Exception { // We retry any exceptions except... - SimpleRetryPolicy policy = new SimpleRetryPolicy(3, Collections - ., Boolean> singletonMap(IllegalStateException.class, false), true, true); + SimpleRetryPolicy policy = new SimpleRetryPolicy(3, + Collections., Boolean>singletonMap( + IllegalStateException.class, false), + true, true); RetryContext context = policy.open(null); // ...so we can't retry this one... diff --git a/src/test/java/org/springframework/retry/policy/SoftReferenceMapRetryContextCacheTests.java b/src/test/java/org/springframework/retry/policy/SoftReferenceMapRetryContextCacheTests.java index 8d85c8b..04265e4 100644 --- a/src/test/java/org/springframework/retry/policy/SoftReferenceMapRetryContextCacheTests.java +++ b/src/test/java/org/springframework/retry/policy/SoftReferenceMapRetryContextCacheTests.java @@ -26,7 +26,7 @@ import org.springframework.retry.context.RetryContextSupport; public class SoftReferenceMapRetryContextCacheTests { SoftReferenceMapRetryContextCache cache = new SoftReferenceMapRetryContextCache(); - + @Test public void testPut() { RetryContextSupport context = new RetryContextSupport(null); @@ -34,7 +34,7 @@ public class SoftReferenceMapRetryContextCacheTests { assertEquals(context, cache.get("foo")); } - @Test(expected=RetryCacheCapacityExceededException.class) + @Test(expected = RetryCacheCapacityExceededException.class) public void testPutOverLimit() { RetryContextSupport context = new RetryContextSupport(null); cache.setCapacity(1); diff --git a/src/test/java/org/springframework/retry/policy/StatefulRetryIntegrationTests.java b/src/test/java/org/springframework/retry/policy/StatefulRetryIntegrationTests.java index 4b9e73c..315255a 100644 --- a/src/test/java/org/springframework/retry/policy/StatefulRetryIntegrationTests.java +++ b/src/test/java/org/springframework/retry/policy/StatefulRetryIntegrationTests.java @@ -38,7 +38,7 @@ import org.springframework.retry.support.RetryTemplate; /** * @author Dave Syer * @author Gary Russell - * + * */ public class StatefulRetryIntegrationTests { @@ -118,7 +118,8 @@ public class StatefulRetryIntegrationTests { } @Test - public void testExternalRetryWithSuccessOnRetryAndSerializedContext() throws Throwable { + public void testExternalRetryWithSuccessOnRetryAndSerializedContext() + throws Throwable { MockRetryCallback callback = new MockRetryCallback(); RetryState retryState = new DefaultRetryState("foo"); @@ -212,13 +213,15 @@ public class StatefulRetryIntegrationTests { /** * @author Dave Syer - * + * */ private static final class MockRetryCallback implements RetryCallback { + int attempts = 0; + RetryContext context; - + public String doWithRetry(RetryContext context) throws Exception { attempts++; this.context = context; @@ -227,6 +230,7 @@ public class StatefulRetryIntegrationTests { } return "bar"; } + } } diff --git a/src/test/java/org/springframework/retry/stats/CircuitBreakerInterceptorStatisticsTests.java b/src/test/java/org/springframework/retry/stats/CircuitBreakerInterceptorStatisticsTests.java index 8eae3aa..0db46dd 100644 --- a/src/test/java/org/springframework/retry/stats/CircuitBreakerInterceptorStatisticsTests.java +++ b/src/test/java/org/springframework/retry/stats/CircuitBreakerInterceptorStatisticsTests.java @@ -38,9 +38,13 @@ import org.springframework.retry.support.RetrySynchronizationManager; public class CircuitBreakerInterceptorStatisticsTests { private static final String RECOVERED = "RECOVERED"; + private static final String RESULT = "RESULT"; + private Service callback; + private StatisticsRepository repository; + private AnnotationConfigApplicationContext context; @Before @@ -90,6 +94,7 @@ public class CircuitBreakerInterceptorStatisticsTests { public Service service() { return new Service(); } + } protected static class Service { @@ -133,6 +138,7 @@ public class CircuitBreakerInterceptorStatisticsTests { public void setExceptionToThrow(Exception exceptionToThrow) { this.exceptionToThrow = exceptionToThrow; } + } } diff --git a/src/test/java/org/springframework/retry/stats/CircuitBreakerStatisticsTests.java b/src/test/java/org/springframework/retry/stats/CircuitBreakerStatisticsTests.java index e32c43f..56148e8 100644 --- a/src/test/java/org/springframework/retry/stats/CircuitBreakerStatisticsTests.java +++ b/src/test/java/org/springframework/retry/stats/CircuitBreakerStatisticsTests.java @@ -43,14 +43,21 @@ import static org.junit.Assert.fail; public class CircuitBreakerStatisticsTests { private static final String RECOVERED = "RECOVERED"; + private static final String RESULT = "RESULT"; + private RetryTemplate retryTemplate; + private RecoveryCallback recovery; + private MockRetryCallback callback; + private DefaultRetryState state; private StatisticsRepository repository = new DefaultStatisticsRepository(); + private StatisticsListener listener = new StatisticsListener(repository); + private RetryContextCache cache; @Before @@ -184,6 +191,7 @@ public class CircuitBreakerStatisticsTests { public void setExceptionToThrow(Exception exceptionToThrow) { this.exceptionToThrow = exceptionToThrow; } + } } diff --git a/src/test/java/org/springframework/retry/stats/ExponentialAverageRetryStatisticsTests.java b/src/test/java/org/springframework/retry/stats/ExponentialAverageRetryStatisticsTests.java index 9f4cbca..23f3e6f 100644 --- a/src/test/java/org/springframework/retry/stats/ExponentialAverageRetryStatisticsTests.java +++ b/src/test/java/org/springframework/retry/stats/ExponentialAverageRetryStatisticsTests.java @@ -43,7 +43,8 @@ public class ExponentialAverageRetryStatisticsTests { @Test public void attributes() throws Exception { - stats.setAttribute("foo", "bar");; + stats.setAttribute("foo", "bar"); + ; assertEquals("bar", stats.getAttribute("foo")); assertTrue(Arrays.asList(stats.attributeNames()).contains("foo")); } diff --git a/src/test/java/org/springframework/retry/stats/StatisticsListenerTests.java b/src/test/java/org/springframework/retry/stats/StatisticsListenerTests.java index f442f1a..63a1a3b 100644 --- a/src/test/java/org/springframework/retry/stats/StatisticsListenerTests.java +++ b/src/test/java/org/springframework/retry/stats/StatisticsListenerTests.java @@ -37,6 +37,7 @@ import org.springframework.retry.support.RetryTemplate; public class StatisticsListenerTests { private StatisticsRepository repository = new DefaultStatisticsRepository(); + private StatisticsListener listener = new StatisticsListener(repository); @Test @@ -117,7 +118,7 @@ public class StatisticsListenerTests { MockRetryCallback callback = new MockRetryCallback(); callback.setAttemptsBeforeSuccess(x + 1); retryTemplate.setRetryPolicy(new SimpleRetryPolicy(x)); - for (int i = 0; i < x+1; i++) { + for (int i = 0; i < x + 1; i++) { try { retryTemplate.execute(callback, state); } @@ -168,7 +169,7 @@ public class StatisticsListenerTests { MockRetryCallback callback = new MockRetryCallback(); callback.setAttemptsBeforeSuccess(x + 1); retryTemplate.setRetryPolicy(new SimpleRetryPolicy(x)); - for (int i = 0; i < x+1; i++) { + for (int i = 0; i < x + 1; i++) { try { retryTemplate.execute(callback, new RecoveryCallback() { @Override diff --git a/src/test/java/org/springframework/retry/support/DefaultRetryStateTests.java b/src/test/java/org/springframework/retry/support/DefaultRetryStateTests.java index ad8aa90..9c32afa 100644 --- a/src/test/java/org/springframework/retry/support/DefaultRetryStateTests.java +++ b/src/test/java/org/springframework/retry/support/DefaultRetryStateTests.java @@ -24,7 +24,7 @@ import org.springframework.classify.Classifier; /** * @author Dave Syer - * + * */ public class DefaultRetryStateTests { @@ -35,11 +35,12 @@ public class DefaultRetryStateTests { @SuppressWarnings("serial") @Test public void testDefaultRetryStateObjectBooleanClassifierOfQsuperThrowableBoolean() { - DefaultRetryState state = new DefaultRetryState("foo", true, new Classifier() { - public Boolean classify(Throwable classifiable) { - return false; - } - }); + 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)); @@ -52,11 +53,12 @@ public class DefaultRetryStateTests { @SuppressWarnings("serial") @Test public void testDefaultRetryStateObjectClassifierOfQsuperThrowableBoolean() { - DefaultRetryState state = new DefaultRetryState("foo", new Classifier() { - public Boolean classify(Throwable classifiable) { - return false; - } - }); + 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)); diff --git a/src/test/java/org/springframework/retry/support/RetrySimulationTests.java b/src/test/java/org/springframework/retry/support/RetrySimulationTests.java index 7731814..a0ac824 100644 --- a/src/test/java/org/springframework/retry/support/RetrySimulationTests.java +++ b/src/test/java/org/springframework/retry/support/RetrySimulationTests.java @@ -39,12 +39,15 @@ public class RetrySimulationTests { RetrySimulator simulator = new RetrySimulator(backOffPolicy, retryPolicy); RetrySimulation simulation = simulator.executeSimulation(1000); System.out.println(backOffPolicy); - System.out.println("Longest sequence " + simulation.getLongestTotalSleepSequence()); + System.out.println( + "Longest sequence " + simulation.getLongestTotalSleepSequence()); System.out.println("Percentiles: " + simulation.getPercentiles()); - assertEquals(asList(400l, 400l, 400l, 400l), simulation.getLongestTotalSleepSequence().getSleeps()); - assertEquals(asList(400d, 400d, 400d, 400d, 400d, 400d, 400d, 400d, 400d), simulation.getPercentiles()); - assertEquals(400d, simulation.getPercentile(0.5),0.1); + assertEquals(asList(400l, 400l, 400l, 400l), + simulation.getLongestTotalSleepSequence().getSleeps()); + assertEquals(asList(400d, 400d, 400d, 400d, 400d, 400d, 400d, 400d, 400d), + simulation.getPercentiles()); + assertEquals(400d, simulation.getPercentile(0.5), 0.1); } @Test @@ -60,11 +63,14 @@ public class RetrySimulationTests { RetrySimulator simulator = new RetrySimulator(backOffPolicy, retryPolicy); RetrySimulation simulation = simulator.executeSimulation(1000); System.out.println(backOffPolicy); - System.out.println("Longest sequence " + simulation.getLongestTotalSleepSequence()); + System.out.println( + "Longest sequence " + simulation.getLongestTotalSleepSequence()); System.out.println("Percentiles: " + simulation.getPercentiles()); - assertEquals(asList(100l, 200l, 400l, 800l), simulation.getLongestTotalSleepSequence().getSleeps()); - assertEquals(asList(100d, 100d, 200d, 200d, 300d, 400d, 400d, 800d, 800d), simulation.getPercentiles()); + assertEquals(asList(100l, 200l, 400l, 800l), + simulation.getLongestTotalSleepSequence().getSleeps()); + assertEquals(asList(100d, 100d, 200d, 200d, 300d, 400d, 400d, 800d, 800d), + simulation.getPercentiles()); assertEquals(300d, simulation.getPercentile(0.5f), 0.1); } @@ -81,9 +87,11 @@ public class RetrySimulationTests { RetrySimulator simulator = new RetrySimulator(backOffPolicy, retryPolicy); RetrySimulation simulation = simulator.executeSimulation(10000); System.out.println(backOffPolicy); - System.out.println("Longest sequence " + simulation.getLongestTotalSleepSequence()); + System.out.println( + "Longest sequence " + simulation.getLongestTotalSleepSequence()); System.out.println("Percentiles: " + simulation.getPercentiles()); assertTrue(simulation.getPercentiles().size() > 4); } + } diff --git a/src/test/java/org/springframework/retry/support/RetrySynchronizationManagerTests.java b/src/test/java/org/springframework/retry/support/RetrySynchronizationManagerTests.java index 4d7f543..29a2afd 100644 --- a/src/test/java/org/springframework/retry/support/RetrySynchronizationManagerTests.java +++ b/src/test/java/org/springframework/retry/support/RetrySynchronizationManagerTests.java @@ -99,4 +99,5 @@ public class RetrySynchronizationManagerTests { } return result; } + } diff --git a/src/test/java/org/springframework/retry/support/RetryTemplateBuilderTest.java b/src/test/java/org/springframework/retry/support/RetryTemplateBuilderTest.java index 79b64bc..c480bb0 100644 --- a/src/test/java/org/springframework/retry/support/RetryTemplateBuilderTest.java +++ b/src/test/java/org/springframework/retry/support/RetryTemplateBuilderTest.java @@ -45,228 +45,214 @@ import static org.mockito.Mockito.mock; import static org.springframework.retry.util.test.TestUtils.getPropertyValue; /** - * The goal of the builder is to build proper instance. - * So, this test inspects instance structure instead behaviour. - * Writing more integrative test is also encouraged. - * Accessing of private fields is performed via {@link TestUtils#getPropertyValue} - * to follow project's style. + * The goal of the builder is to build proper instance. So, this test inspects instance + * structure instead behaviour. Writing more integrative test is also encouraged. + * Accessing of private fields is performed via {@link TestUtils#getPropertyValue} to + * follow project's style. * * @author Aleksandr Shamukov */ public class RetryTemplateBuilderTest { - /* ---------------- Mixed tests -------------- */ + /* ---------------- Mixed tests -------------- */ - @Test - public void testDefaultBehavior() { - RetryTemplate template = RetryTemplate.newBuilder().build(); + @Test + public void testDefaultBehavior() { + RetryTemplate template = RetryTemplate.newBuilder().build(); - PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); - assertDefaultClassifier(policyTuple); - Assert.assertTrue(policyTuple.baseRetryPolicy instanceof MaxAttemptsRetryPolicy); - assertDefaultClassifier(policyTuple); + PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); + assertDefaultClassifier(policyTuple); + Assert.assertTrue(policyTuple.baseRetryPolicy instanceof MaxAttemptsRetryPolicy); + assertDefaultClassifier(policyTuple); - Assert.assertFalse(getPropertyValue(template, "throwLastExceptionOnExhausted", Boolean.class)); - Assert.assertTrue(getPropertyValue(template, "retryContextCache") instanceof MapRetryContextCache); - Assert.assertEquals(0, getPropertyValue(template, "listeners", RetryListener[].class).length); + Assert.assertFalse(getPropertyValue(template, "throwLastExceptionOnExhausted", + Boolean.class)); + Assert.assertTrue(getPropertyValue(template, + "retryContextCache") instanceof MapRetryContextCache); + Assert.assertEquals(0, + getPropertyValue(template, "listeners", RetryListener[].class).length); - Assert.assertTrue(getPropertyValue(template, "backOffPolicy") instanceof NoBackOffPolicy); - } + Assert.assertTrue( + getPropertyValue(template, "backOffPolicy") instanceof NoBackOffPolicy); + } - @Test - public void testBasicCustomization() { - RetryContextCache customCache = mock(SoftReferenceMapRetryContextCache.class); - RetryListener listener1 = mock(RetryListener.class); - RetryListener listener2 = mock(RetryListener.class); + @Test + public void testBasicCustomization() { + RetryContextCache customCache = mock(SoftReferenceMapRetryContextCache.class); + RetryListener listener1 = mock(RetryListener.class); + RetryListener listener2 = mock(RetryListener.class); - RetryTemplate template = RetryTemplate.newBuilder() - .maxAttempts(10) - .exponentialBackoff(99, 1.5, 1717) - .retryOn(IOException.class) - .traversingCauses() - .withListener(listener1) - .withListeners(Collections.singletonList(listener2)) - .build(); + RetryTemplate template = RetryTemplate.newBuilder().maxAttempts(10) + .exponentialBackoff(99, 1.5, 1717).retryOn(IOException.class) + .traversingCauses().withListener(listener1) + .withListeners(Collections.singletonList(listener2)).build(); - PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); + PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); - BinaryExceptionClassifier classifier = - policyTuple.exceptionClassifierRetryPolicy.getExceptionClassifier(); - Assert.assertTrue(classifier.classify(new FileNotFoundException())); - Assert.assertFalse(classifier.classify(new RuntimeException())); - Assert.assertFalse(classifier.classify(new OutOfMemoryError())); + BinaryExceptionClassifier classifier = policyTuple.exceptionClassifierRetryPolicy + .getExceptionClassifier(); + Assert.assertTrue(classifier.classify(new FileNotFoundException())); + Assert.assertFalse(classifier.classify(new RuntimeException())); + Assert.assertFalse(classifier.classify(new OutOfMemoryError())); - Assert.assertTrue(policyTuple.baseRetryPolicy instanceof MaxAttemptsRetryPolicy); - Assert.assertEquals( - 10, - ((MaxAttemptsRetryPolicy)policyTuple.baseRetryPolicy).getMaxAttempts() - ); + Assert.assertTrue(policyTuple.baseRetryPolicy instanceof MaxAttemptsRetryPolicy); + Assert.assertEquals(10, + ((MaxAttemptsRetryPolicy) policyTuple.baseRetryPolicy).getMaxAttempts()); - List listeners = Arrays.asList(getPropertyValue(template, "listeners", RetryListener[].class)); - Assert.assertEquals(2, listeners.size()); - Assert.assertTrue(listeners.contains(listener1)); - Assert.assertTrue(listeners.contains(listener2)); + List listeners = Arrays + .asList(getPropertyValue(template, "listeners", RetryListener[].class)); + Assert.assertEquals(2, listeners.size()); + Assert.assertTrue(listeners.contains(listener1)); + Assert.assertTrue(listeners.contains(listener2)); - Assert.assertTrue(getPropertyValue(template, "backOffPolicy") instanceof ExponentialBackOffPolicy); - } + Assert.assertTrue(getPropertyValue(template, + "backOffPolicy") instanceof ExponentialBackOffPolicy); + } + /* ---------------- Retry policy -------------- */ - /* ---------------- Retry policy -------------- */ + @Test(expected = IllegalArgumentException.class) + public void testFailOnRetryPoliciesConflict() { + RetryTemplate.newBuilder().maxAttempts(3).withinMillis(1000).build(); + } - @Test(expected = IllegalArgumentException.class) - public void testFailOnRetryPoliciesConflict() { - RetryTemplate.newBuilder() - .maxAttempts(3) - .withinMillis(1000) - .build(); - } + @Test + public void testTimeoutPolicy() { + RetryTemplate template = RetryTemplate.newBuilder().withinMillis(10000).build(); - @Test - public void testTimeoutPolicy() { - RetryTemplate template = RetryTemplate.newBuilder() - .withinMillis(10000) - .build(); + PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); + assertDefaultClassifier(policyTuple); - PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); - assertDefaultClassifier(policyTuple); + Assert.assertTrue(policyTuple.baseRetryPolicy instanceof TimeoutRetryPolicy); + Assert.assertEquals(10000, + ((TimeoutRetryPolicy) policyTuple.baseRetryPolicy).getTimeout()); + } - Assert.assertTrue(policyTuple.baseRetryPolicy instanceof TimeoutRetryPolicy); - Assert.assertEquals(10000, ((TimeoutRetryPolicy)policyTuple.baseRetryPolicy).getTimeout()); - } + @Test + public void testInfiniteRetry() { + RetryTemplate template = RetryTemplate.newBuilder().infiniteRetry().build(); - @Test - public void testInfiniteRetry() { - RetryTemplate template = RetryTemplate.newBuilder() - .infiniteRetry() - .build(); + PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); + assertDefaultClassifier(policyTuple); - PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); - assertDefaultClassifier(policyTuple); - - Assert.assertTrue(policyTuple.baseRetryPolicy instanceof AlwaysRetryPolicy); - } + Assert.assertTrue(policyTuple.baseRetryPolicy instanceof AlwaysRetryPolicy); + } - @Test - public void testCustomPolicy() { - RetryPolicy customPolicy = mock(RetryPolicy.class); + @Test + public void testCustomPolicy() { + RetryPolicy customPolicy = mock(RetryPolicy.class); - RetryTemplate template = RetryTemplate.newBuilder() - .customPolicy(customPolicy) - .build(); + RetryTemplate template = RetryTemplate.newBuilder().customPolicy(customPolicy) + .build(); - PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); + PolicyTuple policyTuple = PolicyTuple.extractWithAsserts(template); - assertDefaultClassifier(policyTuple); - Assert.assertEquals(customPolicy, policyTuple.baseRetryPolicy); - } + assertDefaultClassifier(policyTuple); + Assert.assertEquals(customPolicy, policyTuple.baseRetryPolicy); + } - private void assertDefaultClassifier(PolicyTuple policyTuple) { - BinaryExceptionClassifier classifier = policyTuple.exceptionClassifierRetryPolicy.getExceptionClassifier(); - Assert.assertTrue(classifier.classify(new Exception())); - Assert.assertTrue(classifier.classify(new Exception(new Error()))); - Assert.assertFalse(classifier.classify(new Error())); - Assert.assertFalse(classifier.classify(new Error(new Exception()))); - } + private void assertDefaultClassifier(PolicyTuple policyTuple) { + BinaryExceptionClassifier classifier = policyTuple.exceptionClassifierRetryPolicy + .getExceptionClassifier(); + Assert.assertTrue(classifier.classify(new Exception())); + Assert.assertTrue(classifier.classify(new Exception(new Error()))); + Assert.assertFalse(classifier.classify(new Error())); + Assert.assertFalse(classifier.classify(new Error(new Exception()))); + } + /* ---------------- Exception classification -------------- */ - /* ---------------- Exception classification -------------- */ + @Test(expected = IllegalArgumentException.class) + public void testFailOnEmptyExceptionClassifierRules() { + RetryTemplate.newBuilder().traversingCauses().build(); + } - @Test(expected = IllegalArgumentException.class) - public void testFailOnEmptyExceptionClassifierRules() { - RetryTemplate.newBuilder() - .traversingCauses() - .build(); - } + @Test(expected = IllegalArgumentException.class) + public void testFailOnNotationMix() { + RetryTemplate.newBuilder().retryOn(IOException.class) + .notRetryOn(OutOfMemoryError.class); + } - @Test(expected = IllegalArgumentException.class) - public void testFailOnNotationMix() { - RetryTemplate.newBuilder() - .retryOn(IOException.class) - .notRetryOn(OutOfMemoryError.class); - } + /* ---------------- BackOff -------------- */ - - /* ---------------- BackOff -------------- */ + @Test(expected = IllegalArgumentException.class) + public void testFailOnBackOffPolicyNull() { + RetryTemplate.newBuilder().customBackoff(null).build(); + } - @Test(expected = IllegalArgumentException.class) - public void testFailOnBackOffPolicyNull() { - RetryTemplate.newBuilder() - .customBackoff(null) - .build(); - } + @Test(expected = IllegalArgumentException.class) + public void testFailOnBackOffPolicyConflict() { + RetryTemplate.newBuilder().noBackoff().fixedBackoff(1000).build(); + } - @Test(expected = IllegalArgumentException.class) - public void testFailOnBackOffPolicyConflict() { - RetryTemplate.newBuilder() - .noBackoff() - .fixedBackoff(1000) - .build(); - } + @Test + public void testUniformRandomBackOff() { + RetryTemplate template = RetryTemplate.newBuilder().uniformRandomBackoff(10, 100) + .build(); + Assert.assertTrue(getPropertyValue(template, + "backOffPolicy") instanceof UniformRandomBackOffPolicy); + } - @Test - public void testUniformRandomBackOff() { - RetryTemplate template = RetryTemplate.newBuilder() - .uniformRandomBackoff(10, 100) - .build(); - Assert.assertTrue(getPropertyValue(template, "backOffPolicy") instanceof UniformRandomBackOffPolicy); - } + @Test + public void testNoBackOff() { + RetryTemplate template = RetryTemplate.newBuilder().noBackoff().build(); + Assert.assertTrue( + getPropertyValue(template, "backOffPolicy") instanceof NoBackOffPolicy); + } - @Test - public void testNoBackOff() { - RetryTemplate template = RetryTemplate.newBuilder() - .noBackoff() - .build(); - Assert.assertTrue(getPropertyValue(template, "backOffPolicy") instanceof NoBackOffPolicy); - } + @Test + public void testExpBackOffWithRandom() { + RetryTemplate template = RetryTemplate.newBuilder() + .exponentialBackoff(10, 2, 500, true).build(); + Assert.assertTrue(getPropertyValue(template, + "backOffPolicy") instanceof ExponentialRandomBackOffPolicy); + } - @Test - public void testExpBackOffWithRandom() { - RetryTemplate template = RetryTemplate.newBuilder() - .exponentialBackoff(10, 2, 500, true) - .build(); - Assert.assertTrue(getPropertyValue(template, "backOffPolicy") instanceof ExponentialRandomBackOffPolicy - ); - } + @Test(expected = IllegalArgumentException.class) + public void testValidateInitAndMax() { + RetryTemplate.newBuilder().exponentialBackoff(100, 2, 100).build(); + } - @Test(expected = IllegalArgumentException.class) - public void testValidateInitAndMax() { - RetryTemplate.newBuilder().exponentialBackoff(100, 2, 100).build(); - } + @Test(expected = IllegalArgumentException.class) + public void testValidateMeaninglessMultipier() { + RetryTemplate.newBuilder().exponentialBackoff(100, 1, 200).build(); + } - @Test(expected = IllegalArgumentException.class) - public void testValidateMeaninglessMultipier() { - RetryTemplate.newBuilder().exponentialBackoff(100, 1, 200).build(); - } + @Test(expected = IllegalArgumentException.class) + public void testValidateZeroInitInterval() { + RetryTemplate.newBuilder().exponentialBackoff(0, 2, 200).build(); + } - @Test(expected = IllegalArgumentException.class) - public void testValidateZeroInitInterval() { - RetryTemplate.newBuilder().exponentialBackoff(0, 2, 200).build(); - } + /* ---------------- Utils -------------- */ + private static class PolicyTuple { - /* ---------------- Utils -------------- */ + RetryPolicy baseRetryPolicy; - private static class PolicyTuple { - RetryPolicy baseRetryPolicy; - BinaryExceptionClassifierRetryPolicy exceptionClassifierRetryPolicy; + BinaryExceptionClassifierRetryPolicy exceptionClassifierRetryPolicy; - static PolicyTuple extractWithAsserts(RetryTemplate template) { - CompositeRetryPolicy compositeRetryPolicy = getPropertyValue(template, "retryPolicy", - CompositeRetryPolicy.class); - PolicyTuple res = new PolicyTuple(); + static PolicyTuple extractWithAsserts(RetryTemplate template) { + CompositeRetryPolicy compositeRetryPolicy = getPropertyValue(template, + "retryPolicy", CompositeRetryPolicy.class); + PolicyTuple res = new PolicyTuple(); - Assert.assertFalse(getPropertyValue(compositeRetryPolicy, "optimistic", Boolean.class)); + Assert.assertFalse( + getPropertyValue(compositeRetryPolicy, "optimistic", Boolean.class)); + + for (final RetryPolicy policy : getPropertyValue(compositeRetryPolicy, + "policies", RetryPolicy[].class)) { + if (policy instanceof BinaryExceptionClassifierRetryPolicy) { + res.exceptionClassifierRetryPolicy = (BinaryExceptionClassifierRetryPolicy) policy; + } + else { + res.baseRetryPolicy = policy; + } + } + Assert.assertNotNull(res.exceptionClassifierRetryPolicy); + Assert.assertNotNull(res.baseRetryPolicy); + return res; + } + + } - for (final RetryPolicy policy : getPropertyValue(compositeRetryPolicy, "policies", RetryPolicy[].class)) { - if (policy instanceof BinaryExceptionClassifierRetryPolicy) { - res.exceptionClassifierRetryPolicy = (BinaryExceptionClassifierRetryPolicy) policy; - } else { - res.baseRetryPolicy = policy; - } - } - Assert.assertNotNull(res.exceptionClassifierRetryPolicy); - Assert.assertNotNull(res.baseRetryPolicy); - return res; - } - } } \ No newline at end of file diff --git a/src/test/java/org/springframework/retry/support/RetryTemplateTests.java b/src/test/java/org/springframework/retry/support/RetryTemplateTests.java index 2e94b8a..41f169d 100644 --- a/src/test/java/org/springframework/retry/support/RetryTemplateTests.java +++ b/src/test/java/org/springframework/retry/support/RetryTemplateTests.java @@ -128,7 +128,8 @@ public class RetryTemplateTests { try { retryTemplate.execute(callback); fail("Expected IllegalArgumentException"); - } catch (IllegalArgumentException e) { + } + catch (IllegalArgumentException e) { assertNotNull(e); assertEquals(retryAttempts, callback.attempts); return; @@ -158,11 +159,10 @@ public class RetryTemplateTests { RetryTemplate retryTemplate = new RetryTemplate(); retryTemplate.setRetryPolicy(new SimpleRetryPolicy(attempts, - Collections., Boolean> singletonMap( + Collections., Boolean>singletonMap( Exception.class, true))); - BinaryExceptionClassifier classifier = new BinaryExceptionClassifier( - Collections - .> singleton(IllegalArgumentException.class), + BinaryExceptionClassifier classifier = new BinaryExceptionClassifier(Collections + .>singleton(IllegalArgumentException.class), false); retryTemplate.execute(callback, new DefaultRetryState("foo", classifier)); assertEquals(attempts, callback.attempts); @@ -172,7 +172,7 @@ public class RetryTemplateTests { public void testSetExceptions() throws Throwable { RetryTemplate template = new RetryTemplate(); SimpleRetryPolicy policy = new SimpleRetryPolicy(3, - Collections., Boolean> singletonMap( + Collections., Boolean>singletonMap( RuntimeException.class, true)); template.setRetryPolicy(policy); @@ -183,7 +183,8 @@ public class RetryTemplateTests { try { template.execute(callback); - } catch (Exception e) { + } + catch (Exception e) { assertNotNull(e); assertEquals(1, callback.attempts); } @@ -221,7 +222,8 @@ public class RetryTemplateTests { } }); fail("Expected ExhaustedRetryException"); - } catch (IllegalStateException ex) { + } + catch (IllegalStateException ex) { // Expected for internal retry policy (external would recover // gracefully) assertEquals("Retry this operation", ex.getMessage()); @@ -241,7 +243,8 @@ public class RetryTemplateTests { } }); fail("Expected ExhaustedRetryException"); - } catch (IllegalStateException ex) { + } + catch (IllegalStateException ex) { // Expected for internal retry policy (external would recover // gracefully) assertEquals("Retry this operation", ex.getMessage()); @@ -289,7 +292,8 @@ public class RetryTemplateTests { } }); fail("Expected Error"); - } catch (Error e) { + } + catch (Error e) { assertEquals("Realllly bad!", e.getMessage()); } } @@ -312,7 +316,8 @@ public class RetryTemplateTests { } }); fail("Expected Error"); - } catch (TerminatedRetryException e) { + } + catch (TerminatedRetryException e) { assertEquals("Planned", e.getCause().getMessage()); } } @@ -334,7 +339,8 @@ public class RetryTemplateTests { } }); fail("Expected RuntimeException"); - } catch (BackOffInterruptedException e) { + } + catch (BackOffInterruptedException e) { assertEquals("foo", e.getMessage()); } } @@ -374,7 +380,8 @@ public class RetryTemplateTests { }); fail(); - } catch (Exception expected) { + } + catch (Exception expected) { assertEquals("maybe next time!", expected.getMessage()); } @@ -405,6 +412,7 @@ public class RetryTemplateTests { public void setExceptionToThrow(Exception exceptionToThrow) { this.exceptionToThrow = exceptionToThrow; } + } private static class MockBackOffStrategy implements BackOffPolicy { @@ -424,5 +432,7 @@ public class RetryTemplateTests { throws BackOffInterruptedException { this.backOffCalls++; } + } + } diff --git a/src/test/java/org/springframework/retry/support/StatefulRecoveryRetryTests.java b/src/test/java/org/springframework/retry/support/StatefulRecoveryRetryTests.java index f737287..47c5720 100644 --- a/src/test/java/org/springframework/retry/support/StatefulRecoveryRetryTests.java +++ b/src/test/java/org/springframework/retry/support/StatefulRecoveryRetryTests.java @@ -50,7 +50,8 @@ public class StatefulRecoveryRetryTests { @Test public void testOpenSunnyDay() throws Exception { - RetryContext context = retryTemplate.open(new NeverRetryPolicy(), new DefaultRetryState("foo")); + RetryContext context = retryTemplate.open(new NeverRetryPolicy(), + new DefaultRetryState("foo")); assertNotNull(context); // we haven't called the processor yet... assertEquals(0, count); @@ -117,7 +118,7 @@ public class StatefulRecoveryRetryTests { retryTemplate.setRetryPolicy(new SimpleRetryPolicy(1)); // Roll back for these: BinaryExceptionClassifier classifier = new BinaryExceptionClassifier(Collections - .> singleton(DataAccessException.class)); + .>singleton(DataAccessException.class)); // ...but not these: assertFalse(classifier.classify(new RuntimeException())); final String input = "foo"; @@ -211,7 +212,8 @@ public class StatefulRecoveryRetryTests { } catch (RetryException ex) { String message = ex.getMessage(); - assertTrue("Message doesn't contain 'inconsistent': " + message, message.contains("inconsistent")); + assertTrue("Message doesn't contain 'inconsistent': " + message, + message.contains("inconsistent")); } RetryContext context = retryTemplate.open(retryPolicy, state); @@ -247,7 +249,8 @@ public class StatefulRecoveryRetryTests { } catch (RetryException e) { String message = e.getMessage(); - assertTrue("Message does not contain 'capacity': " + message, message.indexOf("capacity") >= 0); + assertTrue("Message does not contain 'capacity': " + message, + message.indexOf("capacity") >= 0); } } diff --git a/src/test/java/org/springframework/retry/util/test/TestUtils.java b/src/test/java/org/springframework/retry/util/test/TestUtils.java index c085365..fd405f3 100644 --- a/src/test/java/org/springframework/retry/util/test/TestUtils.java +++ b/src/test/java/org/springframework/retry/util/test/TestUtils.java @@ -20,6 +20,7 @@ import org.springframework.util.Assert; /** * See Spring Integration TestUtils. + * * @author Mark Fisher * @author Iwein Fuld * @author Oleg Zhurakousky @@ -29,9 +30,10 @@ import org.springframework.util.Assert; public class TestUtils { /** - * Uses nested {@link org.springframework.beans.DirectFieldAccessor}s to obtain a property using dotted notation - * to traverse fields; e.g. - * "foo.bar.baz" will obtain a reference to the baz field of the bar field of foo. Adopted from Spring Integration. + * Uses nested {@link org.springframework.beans.DirectFieldAccessor}s to obtain a + * property using dotted notation to traverse fields; e.g. "foo.bar.baz" will obtain a + * reference to the baz field of the bar field of foo. Adopted from Spring + * Integration. * @param root The object. * @param propertyPath The path. * @return The field. @@ -49,14 +51,16 @@ public class TestUtils { return null; } else { - throw new IllegalArgumentException("intermediate property '" + tokens[i] + "' is null"); + throw new IllegalArgumentException( + "intermediate property '" + tokens[i] + "' is null"); } } return value; } @SuppressWarnings("unchecked") - public static T getPropertyValue(Object root, String propertyPath, Class type) { + public static T getPropertyValue(Object root, String propertyPath, + Class type) { Object value = getPropertyValue(root, propertyPath); if (value != null) { Assert.isAssignable(type, value.getClass());