7

I'm using SpringBoot 2.4.2. And I'm struggling with @AliasFor with custom annotation.

I implemented below custom annotation.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CustomAnnotation {

  @AliasFor("aliasAttribute")
  String value() default "";

  @AliasFor("value")
  String aliasAttribute() "";
}

And using it like this.

@CustomAnnoatation("test")
@Component
public class TestClass() {
 // codes here
}

And this test code fails.

@SpringBootTest(classes = TestClass.class)
public class CustomAnnotationTest {

  @Autowired
  TestClass testClass;

  @Test
  public void valueTest1() {
    Annotation annotation = testClass.getClass().getAnnotation(CustomAnnotation.class);

    assertThat(((CustomAnnotation) annotation).value()).isEqualTo(((CustomAnnotation) annotation).aliasAttribute());
  }
}

with message

org.opentest4j.AssertionFailedError: 
Expecting:
 <"">
to be equal to:
 <"test">

I don't know why, anyone know?

7
  • Because you aren't using Spring to read the annotation thus it won't work. You will need to use the Spring annotation utils to read the annotation for proper support. Commented Feb 24, 2021 at 8:08
  • @M. Deinum Doesn't it happen while spring initializing beans? What the '@SpringBootTest' annotation does. Also this post didn't use Spring annotation utils. examples.javacodegeeks.com/spring-aliasfor-annotation-example Commented Feb 24, 2021 at 8:23
  • Line 27 of the test in that sample clearly uses the AnnotationUtils. Commented Feb 24, 2021 at 8:36
  • yes, but it's 'findAnnotation' so I thought it was just used to find specific annotation. how about this? gist.github.com/SomboChea/0324964054c8269ce5f21e7f8ff4c01a The full example of the code doesn't use any annotation utils. Commented Feb 24, 2021 at 9:38
  • That code doesn't because the bean is constructed by spring which internally uses that, if you would write a test you still need the AnnotationUtils. Hence it still is used. Without using the spring capabilities for synthesized annotations you will not get the value for aliases because it is a spring feature. Commented Feb 24, 2021 at 9:46

1 Answer 1

7

An annotation is static metadata for a class, field etc. so Spring cannot change anything about it. To make features as @AliasFor possible Spring uses, what they call, synthesized annotations. For those to be used/detected you need to utilize the Spring internals to obtain that synthesized annotation and for the @AliasFor to work. For this use AnnotationUtils.findAnnotation (Spring uses that internally as well).

@AliasFor is a Spring feature so without using the Spring components this won't work.

Your test method is basically the same as

@Test
  public void valueTest1() {
    Annotation annotation = TestClass.class.getAnnotation(CustomAnnotation.class);

    assertThat(((CustomAnnotation) annotation).value()).isEqualTo(((CustomAnnotation) annotation).aliasAttribute());
  }

Both this test and your test will fail, because they simply don't use the Spring infrastructure for detecting annotations and apply the features of Spring.

When using AnnotationUtils.findAnnotation the test will pass.

class CustomAnnotationTest {

    @Test
    void testStandardJava() {
        CustomAnnotation annotation = TestClass.class.getAnnotation(CustomAnnotation.class);
        assertThat(annotation.value()).isEqualTo(annotation.aliasAttribute());
    }

    @Test
    void testWithSpring() {
        CustomAnnotation annotation = AnnotationUtils.findAnnotation(TestClass.class, CustomAnnotation.class);
        assertThat(annotation.value()).isEqualTo(annotation.aliasAttribute());
    }
}

The testStandardJava will fail, the testWithSpring will pass because it uses the proper mechanisms.

Sign up to request clarification or add additional context in comments.

2 Comments

hmm.. I thought Spring copies the value of one to another pair attribute of @Alisfor when it initializes beans but it doesn't seem to be. Thanks for your explanations.
No because that simply isn't possible. As stated in my answer annotations are static metadata. They cannot be changed at runtime.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.