Skip to content

Commit 4671928

Browse files
committed
Add generic check for function return type
Fixes: [#215](#215) Signed-off-by: deepesh-verma <[email protected]>
1 parent 868d205 commit 4671928

File tree

2 files changed

+67
-13
lines changed

2 files changed

+67
-13
lines changed

src/main/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandler.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.retry.annotation;
1818

1919
import java.lang.reflect.Method;
20+
import java.lang.reflect.ParameterizedType;
2021
import java.util.HashMap;
2122
import java.util.Map;
2223

@@ -173,27 +174,34 @@ public void doWith(Method method) throws IllegalArgumentException, IllegalAccess
173174
if (recover == null) {
174175
recover = findAnnotationOnTarget(target, method);
175176
}
176-
if (recover != null && method.getReturnType().isAssignableFrom(failingMethod.getReturnType())) {
177-
Class<?>[] parameterTypes = method.getParameterTypes();
178-
if (parameterTypes.length > 0 && Throwable.class.isAssignableFrom(parameterTypes[0])) {
179-
@SuppressWarnings("unchecked")
180-
Class<? extends Throwable> type = (Class<? extends Throwable>) parameterTypes[0];
181-
types.put(type, method);
182-
RecoverAnnotationRecoveryHandler.this.methods.put(method,
183-
new SimpleMetadata(parameterTypes.length, type));
184-
}
185-
else {
186-
RecoverAnnotationRecoveryHandler.this.classifier.setDefaultValue(method);
187-
RecoverAnnotationRecoveryHandler.this.methods.put(method,
188-
new SimpleMetadata(parameterTypes.length, null));
177+
if (recover != null && failingMethod.getGenericReturnType() instanceof ParameterizedType) {
178+
if (method.getGenericReturnType().equals(failingMethod.getGenericReturnType())) {
179+
putToMethodsMap(method, types);
189180
}
190181
}
182+
else if (recover != null && method.getReturnType().isAssignableFrom(failingMethod.getReturnType())) {
183+
putToMethodsMap(method, types);
184+
}
191185
}
192186
});
193187
this.classifier.setTypeMap(types);
194188
optionallyFilterMethodsBy(failingMethod.getReturnType());
195189
}
196190

191+
private void putToMethodsMap(Method method, Map<Class<? extends Throwable>, Method> types) {
192+
Class<?>[] parameterTypes = method.getParameterTypes();
193+
if (parameterTypes.length > 0 && Throwable.class.isAssignableFrom(parameterTypes[0])) {
194+
@SuppressWarnings("unchecked")
195+
Class<? extends Throwable> type = (Class<? extends Throwable>) parameterTypes[0];
196+
types.put(type, method);
197+
RecoverAnnotationRecoveryHandler.this.methods.put(method, new SimpleMetadata(parameterTypes.length, type));
198+
}
199+
else {
200+
RecoverAnnotationRecoveryHandler.this.classifier.setDefaultValue(method);
201+
RecoverAnnotationRecoveryHandler.this.methods.put(method, new SimpleMetadata(parameterTypes.length, null));
202+
}
203+
}
204+
197205
private Recover findAnnotationOnTarget(Object target, Method method) {
198206
try {
199207
Method targetMethod = target.getClass().getMethod(method.getName(), method.getParameterTypes());

src/test/java/org/springframework/retry/annotation/RecoverAnnotationRecoveryHandlerTests.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,19 @@
1818

1919
import java.lang.reflect.Method;
2020
import java.util.ArrayList;
21+
import java.util.Collections;
2122
import java.util.List;
2223

2324
import org.junit.Rule;
2425
import org.junit.Test;
2526
import org.junit.rules.ExpectedException;
2627

2728
import org.springframework.retry.ExhaustedRetryException;
29+
import org.springframework.util.CollectionUtils;
2830
import org.springframework.util.ReflectionUtils;
2931

3032
import static org.junit.Assert.assertEquals;
33+
import static org.junit.Assert.assertFalse;
3134

3235
/**
3336
* @author Dave Syer
@@ -107,6 +110,17 @@ public void parentReturnTypeRecoverMethod() {
107110

108111
}
109112

113+
@Test
114+
public void genericReturnTypeRecover() {
115+
RecoverAnnotationRecoveryHandler<?> handler = new RecoverAnnotationRecoveryHandler<List<String>>(
116+
new GenericReturnTypeRecover(),
117+
ReflectionUtils.findMethod(GenericReturnTypeRecover.class, "foo", String.class));
118+
List<String> recoverResponse = (List<String>) handler.recover(new Object[] { "Aldo" },
119+
new RuntimeException("Planned"));
120+
assertFalse(CollectionUtils.isEmpty(recoverResponse));
121+
assertEquals("fooRecover", recoverResponse.get(0));
122+
}
123+
110124
@Test
111125
public void multipleQualifyingRecoverMethods() {
112126
Method foo = ReflectionUtils.findMethod(MultipleQualifyingRecovers.class, "foo", String.class);
@@ -293,6 +307,38 @@ public Number quux(RuntimeException re, String name) {
293307

294308
}
295309

310+
protected static class GenericReturnTypeRecover {
311+
312+
private static class One {
313+
314+
String name;
315+
316+
public One(String name) {
317+
this.name = name;
318+
}
319+
}
320+
321+
@Retryable
322+
public List<String> foo(String name) {
323+
return Collections.singletonList("foo");
324+
}
325+
326+
@Retryable
327+
public List<One> bar(String name) {
328+
return Collections.singletonList(new One("bar"));
329+
}
330+
331+
@Recover
332+
public List<String> fooRecover(String name) {
333+
return Collections.singletonList("fooRecover");
334+
}
335+
336+
@Recover
337+
public List<One> barRecover(String name) {
338+
return Collections.singletonList(new One("barRecover"));
339+
}
340+
}
341+
296342
protected static class MultipleQualifyingRecoversNoThrowable {
297343

298344
@Retryable

0 commit comments

Comments
 (0)