INT-559 - Generic handler methods defined in a generic superclass are not properly resolved by PayloadTypeMatchingHandlerMethodResolver
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user