Skip to content

SPR-16060 - Enhance AnnotationUtils to find annotations on generic interfaces #1553

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,5 @@ out
test-output
atlassian-ide-plugin.xml
.gradletasknamecache
/.nb-gradle/

Original file line number Diff line number Diff line change
Expand Up @@ -581,21 +581,46 @@ private static <A extends Annotation> A searchOnInterfaces(Method method, Class<
A annotation = null;
for (Class<?> iface : ifcs) {
if (isInterfaceWithAnnotatedMethods(iface)) {
try {
Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes());
Method equivalentMethod = findMethodWithMatchingParameters(iface, method.getName(), method.getParameterTypes());
if (equivalentMethod != null) {
annotation = getAnnotation(equivalentMethod, annotationType);
}
catch (NoSuchMethodException ex) {
// Skip this interface - it doesn't have the method...
}
if (annotation != null) {
break;
if (annotation != null) {
break;
}
}
}
}
return annotation;
}

private static Method findMethodWithMatchingParameters(Class<?> cls, String methodName, Class<?>[] parameterTypes) {
try {
// first try exact match
return cls.getMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
// then look for method with assignable parameters
for (Method method : cls.getMethods()) {
if (method.getName().equals(methodName) &&
method.getParameterCount() == parameterTypes.length &&
parametersAreAssignable(parameterTypes, method)) {
return method;
}
}
}
// return null if there is no match
return null;
}

@SuppressWarnings("unchecked")
private static boolean parametersAreAssignable(Class<?>[] parameterTypes, Method method) {
for (int j = 0; j < parameterTypes.length; j++) {
if (!method.getParameterTypes()[j].isAssignableFrom(parameterTypes[j])) {
return false;
}
}
return true;
}

static boolean isInterfaceWithAnnotatedMethods(Class<?> iface) {
Boolean found = annotatedInterfaceCache.get(iface);
if (found != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,13 @@ public void findMethodAnnotationFromInterface() throws Exception {
assertNotNull(order);
}

@Test
public void findMethodAnnotationFromGenericInterfaceSuper() throws Exception {
Method method = ImplementsInterfaceWithGenericAnnotatedMethod.class.getMethod("foo", String.class);
Order order = findAnnotation(method, Order.class);
assertNotNull(order);
}

@Test
public void findMethodAnnotationFromInterfaceOnSuper() throws Exception {
Method method = SubOfImplementsInterfaceWithAnnotatedMethod.class.getMethod("foo");
Expand Down Expand Up @@ -1755,6 +1762,17 @@ public static class TransactionalAndOrderedClass extends TransactionalClass {
public static class SubTransactionalAndOrderedClass extends TransactionalAndOrderedClass {
}

public static interface InterfaceWithGenericAnnotatedMethod<T> {
@Order
void foo(T t);
}

public static class ImplementsInterfaceWithGenericAnnotatedMethod implements InterfaceWithGenericAnnotatedMethod<String> {
public void foo(String t) {
// no body in test method
}
}

public interface InterfaceWithAnnotatedMethod {

@Order
Expand Down