Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get field's type annotation in Java Annotation Processing?

For example, I have this code:

@Retention(RetentionPolicy.SOURCE)
public @interface ClassAnnotation {
}

@ClassAnnotation
public class AnnotatedClass {
}

@ClassAnnotation
public class AnotherAnnotatedClass {

    private AnnotatedClass someField;
    private int intIsNotAnnotated;
}

And this processor to preprocess it in compile time:

@SupportedAnnotationTypes({ "com.example.ClassAnnotation" })
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class AwesomeProcessor extends AbstractProcessor {

    public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {
        // Skipped for brevity...
        // For each annotated class
        for (Element e : roundEnv.getElementsAnnotatedWith(ClassAnnotation.class)) {
            // Skipped for brevity...
            // For each field
            for (Element ee : classElement.getEnclosedElements()) {
                // Skipped for brevity... (of course there's kind checking)
                TypeMirror fieldType = fieldElement.asType();
                TypeElement fieldTypeElement = (TypeElement) processingEnv.
                    getTypeUtils().asElement(fieldType);
            }
        }
        // Skipped for brevity
    }
}

I need to check whether a field's type is a class that is annotated with my annotation. Somehow I've got a TypeElement named fieldTypeElement, it may represent AnnotatedClass from someField or int from intIsNotAnnotated in the example. How to get @ClassAnnotation of AnnotatedClass of someField? I've tried fieldTypeElement.getAnnotation(ClassAnnotation.class) and fieldTypeElement.getAnnotationMirrors(), but it returns null and empty list respectively.

like image 442
fikr4n Avatar asked Sep 30 '22 09:09

fikr4n


1 Answers

I think you are somehow getting the wrong TypeElement but unfortunatly that part of the code is missing.

This simple example works as expected:

processingEnv.getElementUtils().getTypeElement("AnnotatedClass").getAnnotationMirrors()

contains @ClassAnnotation.

To get the TypeElement of a field, you'll have to

  1. get the fields's type
  2. cast the type to DeclaredType
  3. get the declared type's element
  4. cast the element to TypeElement

The last step isn't necessary though to get an element's annotations:

Element field = // ... 
List<? extends AnnotationMirror> annotationMirrors =
    ((DeclaredType) field.asType()).asElement().getAnnotationMirrors();

The updated code should work, I've tested it and it runs fine. The error must be elsewhere. Some other things to check for:

  • Make sure the build is good, sometimes a build step fails and old code is used unnoticed
  • Check the RetentionPolicy of the annotation. None, CLASS or RUNTIME are fine but SOURCE won't work
like image 67
kapex Avatar answered Oct 06 '22 20:10

kapex