Skip to content

Commit

Permalink
fix(core): handle meta annotations using spring @AliasFor
Browse files Browse the repository at this point in the history
One example is the `@KafkaListener` annotation reported in GH-510
  • Loading branch information
timonback committed Jan 1, 2024
1 parent 95d63a9 commit 74a92e7
Show file tree
Hide file tree
Showing 2 changed files with 214 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ public static <T extends Annotation> Set<T> findAnnotations(Class<T> annotationC
RepeatableContainers.standardRepeatables())
.stream(annotationClass)
.filter(MergedAnnotationPredicates.firstRunOf(MergedAnnotation::getAggregateIndex))
.map(MergedAnnotation::withNonMergedAttributes)
.collect(MergedAnnotationCollectors.toAnnotationSet());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// SPDX-License-Identifier: Apache-2.0
package io.github.stavshamir.springwolf.asyncapi.scanners.channels.annotation;

import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.fail;

class AnnotationUtilTest {

@Nested
public class FindAnnotationOrThrow {
@Test
void findNoAnnotationTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("notAnnotatedMethod");

// when
try {
AnnotationUtil.findAnnotationOrThrow(AnnotationUtilTestAnnotation.class, method);
fail();
} catch (IllegalArgumentException e) {
// then
assertThat(e.getMessage()).isEqualTo("Method must be annotated with java.lang.reflect.Method");
}
}

@Test
void findAnnotationTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("annotatedMethod");

// when
AnnotationUtilTestAnnotation annotation =
AnnotationUtil.findAnnotationOrThrow(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation.field()).isEqualTo("value");
}

@Test
void findAnnotationRepeatedTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("annotatedMethodRepeated");

// when
AnnotationUtilTestAnnotation annotation =
AnnotationUtil.findAnnotationOrThrow(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation.field()).isEqualTo("value");
}

@Test
void findMetaAnnotationTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("annotatedMethodWithMetaAnnotation");

// when
AnnotationUtilTestAnnotation annotation =
AnnotationUtil.findAnnotationOrThrow(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation.field()).isEqualTo("metaField");
}
}

@Nested
public class FindAnnotation {
@Test
void findNoAnnotationTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("notAnnotatedMethod");

// when
AnnotationUtilTestAnnotation annotation =
AnnotationUtil.findAnnotation(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation).isNull();
}

@Test
void findAnnotationTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("annotatedMethod");

// when
AnnotationUtilTestAnnotation annotation =
AnnotationUtil.findAnnotation(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation.field()).isEqualTo("value");
}

@Test
void findAnnotationRepeatedTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("annotatedMethodRepeated");

// when
AnnotationUtilTestAnnotation annotation =
AnnotationUtil.findAnnotation(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation.field()).isIn("value", "value2");
}

@Test
void findMetaAnnotationTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("annotatedMethodWithMetaAnnotation");

// when
AnnotationUtilTestAnnotation annotation =
AnnotationUtil.findAnnotation(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation.field()).isEqualTo("metaField");
}
}

@Nested
public class FindAnnotations {
@Test
void findNoAnnotationTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("notAnnotatedMethod");

// when
Set<AnnotationUtilTestAnnotation> annotation =
AnnotationUtil.findAnnotations(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation).isEmpty();
}

@Test
void findAnnotationTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("annotatedMethod");

// when
Set<AnnotationUtilTestAnnotation> annotation =
AnnotationUtil.findAnnotations(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation).hasSize(1);
assertThat(annotation.stream().findAny().get().field()).isEqualTo("value");
}

@Test
void findAnnotationRepeatedTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("annotatedMethodRepeated");

// when
Set<AnnotationUtilTestAnnotation> annotation =
AnnotationUtil.findAnnotations(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation).hasSize(2);
assertThat(annotation.stream().map(AnnotationUtilTestAnnotation::field))
.containsExactlyInAnyOrder("value", "value2");
}

@Test
void findMetaAnnotationTest() throws NoSuchMethodException {
Method method = TestClass.class.getMethod("annotatedMethodWithMetaAnnotation");

// when
Set<AnnotationUtilTestAnnotation> annotation =
AnnotationUtil.findAnnotations(AnnotationUtilTestAnnotation.class, method);

// then
assertThat(annotation).hasSize(1);
assertThat(annotation.stream().findAny().get().field()).isEqualTo("metaField");
}
}

private class TestClass {
public void notAnnotatedMethod() {}

@AnnotationUtilTestAnnotation
public void annotatedMethod() {}

@AnnotationUtilTestAnnotation
@AnnotationUtilTestAnnotation(field = "value2")
public void annotatedMethodRepeated() {}

@AnnotationUtilTestMetaAnnotation
public void annotatedMethodWithMetaAnnotation() {}
}

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(AnnotationUtilTestAnnotationRepeatable.class)
@interface AnnotationUtilTestAnnotation {
String field() default "value";
}

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@interface AnnotationUtilTestAnnotationRepeatable {
AnnotationUtilTestAnnotation[] value();
}

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@AnnotationUtilTestAnnotation
@interface AnnotationUtilTestMetaAnnotation {
@AliasFor(annotation = AnnotationUtilTestAnnotation.class, attribute = "field")
String metaField() default "metaField";
}
}

0 comments on commit 74a92e7

Please sign in to comment.