diff --git a/src/main/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandler.java b/src/main/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandler.java index 2cad5bc..e4a8f16 100644 --- a/src/main/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandler.java +++ b/src/main/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandler.java @@ -28,6 +28,7 @@ import org.springframework.retry.ExhaustedRetryException; import org.springframework.retry.RetryContext; import org.springframework.retry.interceptor.MethodInvocationRecoverer; import org.springframework.retry.support.RetrySynchronizationManager; +import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils.MethodCallback; import org.springframework.util.StringUtils; @@ -43,6 +44,7 @@ import org.springframework.util.StringUtils; * handled and there is a method whose first argument is RuntimeException, then it will be * preferred over a method whose first argument is Throwable. * + * @param the type of the return value from the recovery * @author Dave Syer * @author Josh Long * @author Aldo Sinanaj @@ -50,15 +52,15 @@ import org.springframework.util.StringUtils; * @author Nathanaƫl Roberts * @author Maksim Kita * @author Gary Russell - * @param the type of the return value from the recovery + * @author Artem Bilan */ public class RecoverAnnotationRecoveryHandler implements MethodInvocationRecoverer { - private SubclassClassifier classifier = new SubclassClassifier(); + private final SubclassClassifier classifier = new SubclassClassifier(); - private Map methods = new HashMap(); + private final Map methods = new HashMap(); - private Object target; + private final Object target; private String recoverMethodName; @@ -190,7 +192,9 @@ public class RecoverAnnotationRecoveryHandler implements MethodInvocationReco if (argument == null) { continue; } - if (!parameterTypes[i].isAssignableFrom(argument.getClass())) { + Class parameterType = parameterTypes[i]; + parameterType = ClassUtils.resolvePrimitiveIfNecessary(parameterType); + if (!parameterType.isAssignableFrom(argument.getClass())) { return false; } } @@ -208,7 +212,7 @@ public class RecoverAnnotationRecoveryHandler implements MethodInvocationReco } ReflectionUtils.doWithMethods(target.getClass(), new MethodCallback() { @Override - public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException { + public void doWith(Method method) throws IllegalArgumentException { Recover recover = AnnotationUtils.findAnnotation(method, Recover.class); if (recover == null) { recover = findAnnotationOnTarget(target, method); @@ -294,15 +298,17 @@ public class RecoverAnnotationRecoveryHandler implements MethodInvocationReco } } if (filteredMethods.size() > 0) { - this.methods = filteredMethods; + this.methods.clear(); + ; + this.methods.putAll(filteredMethods); } } private static class SimpleMetadata { - private int argCount; + private final int argCount; - private Class type; + private final Class type; public SimpleMetadata(int argCount, Class type) { super(); @@ -325,7 +331,7 @@ public class RecoverAnnotationRecoveryHandler implements MethodInvocationReco result[0] = t; startArgs = 1; } - int length = result.length - startArgs > args.length ? args.length : result.length - startArgs; + int length = Math.min(result.length - startArgs, args.length); if (length == 0) { return result; } diff --git a/src/test/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandlerTests.java b/src/test/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandlerTests.java index ab4baf4..0e8f369 100644 --- a/src/test/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandlerTests.java +++ b/src/test/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandlerTests.java @@ -274,6 +274,14 @@ public class RecoverAnnotationRecoveryHandlerTests { assertEquals(2, handler.recover(new Object[] { "Kevin" }, new RuntimeException("Planned"))); } + @Test + public void recoverByRetryableNameWithPrimitiveArgs() { + Method foo = ReflectionUtils.findMethod(RecoverByRetryableNameWithPrimitiveArgs.class, "foo", int.class); + RecoverAnnotationRecoveryHandler handler = new RecoverAnnotationRecoveryHandler( + new RecoverByRetryableNameWithPrimitiveArgs(), foo); + assertEquals(2, handler.recover(new Object[] { 2 }, new RuntimeException("Planned"))); + } + private static class InAccessibleRecover { @Retryable @@ -643,4 +651,34 @@ public class RecoverAnnotationRecoveryHandlerTests { } + protected static class RecoverByRetryableNameWithPrimitiveArgs + implements RecoverByRetryableNameWithPrimitiveArgsInterface { + + public int foo(int number) { + return 0; + } + + public int fooRecover(Throwable throwable, int number) { + return 0; + } + + public int barRecover(Throwable throwable, int number) { + return number; + } + + } + + protected interface RecoverByRetryableNameWithPrimitiveArgsInterface { + + @Retryable(recover = "barRecover") + public int foo(int number); + + @Recover + public int fooRecover(Throwable throwable, int number); + + @Recover + public int barRecover(Throwable throwable, int number); + + } + }