INT-559 - Generic handler methods defined in a generic superclass are not properly resolved by PayloadTypeMatchingHandlerMethodResolver

This commit is contained in:
Marius Bogoevici
2009-02-10 18:59:35 +00:00
parent 2540d63b90
commit f8961bcf5b
2 changed files with 36 additions and 3 deletions

View File

@@ -20,6 +20,7 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.HashMap;
import java.util.Map;
@@ -90,10 +91,10 @@ public class PayloadTypeMatchingHandlerMethodResolver implements HandlerMethodRe
Assert.isTrue(expectedType == null,
"Message-handling method must only have one parameter expecting a Message or Message payload."
+ " Other parameters may be included but only if they have @Header or @Headers annotations.");
Type parameterType = parameterTypes[i];
Type parameterType = extractRawTypeIfGeneric(parameterTypes[i]);
if (parameterType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) parameterType;
Type rawType = parameterizedType.getRawType();
Type rawType = extractRawTypeIfGeneric(parameterizedType.getRawType());
if (rawType instanceof Class) {
Class<?> rawTypeClass = (Class<?>) rawType;
if (Message.class.isAssignableFrom(rawTypeClass)) {
@@ -114,6 +115,13 @@ public class PayloadTypeMatchingHandlerMethodResolver implements HandlerMethodRe
return expectedType;
}
private Type extractRawTypeIfGeneric(Type parameterType) {
if (parameterType instanceof TypeVariable<?>) {
parameterType = ((TypeVariable<?>) parameterType).getBounds()[0];
}
return parameterType;
}
private Method findClosestMatch(Class<?> payloadType) {
Set<Class<?>> expectedTypes = this.methodMap.keySet();
int minTypeDiffWeight = Integer.MAX_VALUE;
@@ -133,7 +141,7 @@ public class PayloadTypeMatchingHandlerMethodResolver implements HandlerMethodRe
private Class<?> determineExpectedTypeFromParameterizedMessageType(ParameterizedType parameterizedType) {
Class<?> expectedType = null;
Type actualType = parameterizedType.getActualTypeArguments()[0];
Type actualType = extractRawTypeIfGeneric(parameterizedType.getActualTypeArguments()[0]);
if (actualType instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) actualType;
if (wildcardType.getUpperBounds().length == 1) {
@@ -146,6 +154,7 @@ public class PayloadTypeMatchingHandlerMethodResolver implements HandlerMethodRe
else if (actualType instanceof Class) {
expectedType = (Class<?>) actualType;
}
return expectedType;
}

View File

@@ -165,6 +165,30 @@ public class PayloadTypeMatchingHandlerMethodResolverWithMessageParameterTests {
assertEquals(expected, resolved);
assertEquals(new Integer(123), resolved.invoke(service, message));
}
@Test
public void testGenericSuperclass() throws Exception {
Object service = new ConcreteTestService();
Method[] candidates = HandlerMethodUtils.getCandidateHandlerMethods(service);
PayloadTypeMatchingHandlerMethodResolver methodResolver =
new PayloadTypeMatchingHandlerMethodResolver(candidates);
Method expected = ConcreteTestService.class.getMethod("genericMethod", Message.class);
Message<?> message = MessageBuilder.withPayload("SomeString").build();
Method resolved = methodResolver.resolveHandlerMethod(message);
assertEquals(expected, resolved);
assertEquals(message.getPayload(), resolved.invoke(service, message));
}
public static class GenericTestService<T extends Message<K>, K> {
public K genericMethod(T message) {
return message.getPayload();
}
}
public static class ConcreteTestService extends GenericTestService<Message<String>, String> {
}
public static class TestService {