How do I use Annotation Processing API in runtime?

10,907

Solution 1

You can access the annotations at run time using reflection - getAnnotations.

To get a list of classes (in your classpath) using your annotation, you could - at runtime - iterate through all the classes testing if they have that annotation.

Alternatively - at build time - you could construct a class with a list of classes.

Solution 2

Did you specify that your annotation is available at runtime using the RetentionPolicy ? If not you need to use @Retention annotation on yours.

@Retention(RetentionPolicy.RUNTIME)

public @interface MyAnnotation {
    String[] parameters();
    String[] exceptions();
}
Share:
10,907
corgrath
Author by

corgrath

Updated on June 27, 2022

Comments

  • corgrath
    corgrath over 1 year

    I have and followed several Annotation Processing Tool (APT) guides (such as 1 and 2) on the Internet and have managed to get it working in compiler/ build time, and even got it working in Eclipse.

    Is there a way I can use APT in run time to get a list of Types (Classes) using my annotation.

    I wrote something like:

    @SupportedAnnotationTypes("com.domain.MyAnnotation")
    public class MyAbstractProcessor extends AbstractProcessor {
    
        public static Map<Element, MyAnnotation> patches = new HashMap<Element, MyAnnotation>();
    
        @Override
        public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnvironment) {
    
            // Get all classes that has the annotation
            Set<? extends Element> classElements = roundEnvironment.getElementsAnnotatedWith(MyAnnotation.class);
    
            // For each class that has the annotation
            for (final Element classElement : classElements) {
    
                patches.put(classElement, annotation);
    

    So MyAbstractProcessor.patches would be populate with a list of classes using the annotation. A noble idea, apart from the flaw that this APT is executing at build time, and not run time.

    Is it even possible to use APT in run time?

    Or am I using the wrong frameworks to get what I want?

  • corgrath
    corgrath over 11 years
    "Alternatively - at build time - you could construct a class with a list of classes." - You mean, output to a file which gets read by the application in run time?
  • emory
    emory over 11 years
    Yes, use processingEnv.getFiler().createSourceFile(qualifiedName).ope‌​nWriter() and write out the contents of patches to a static variable in the qualifedName class. Of course you have to write all the required class boilerplate `public class simpleName { private static final Map < > patches = new Map < > { contents of patches } ...
  • corgrath
    corgrath over 11 years
    Yes, I did. Both SOURCE and RUNTIME :-)
  • zeropouet
    zeropouet over 11 years
    Normally It should work, with this retention policy. If it is not working with APT, you might try JSR 269 (Pluggable Annotations Processing).
  • corgrath
    corgrath over 11 years
    Wow, the createSourceFile is great. I didn't know that was possible. Thanks :-)
  • mostafa.S
    mostafa.S over 2 years
    question arises, imagine we write some runtime annotation processor with reflection, and present our whole library which includes our annotations, and some other guy uses our library in their own project. And he uses our annotations in his code, when our annotation runtime processing method is called and by whom? there should be some entry point for the runtime processor, right? or I am missing some key point?
  • emory
    emory over 2 years
    @mostafa.S Spring Boot is an example. I believe they use reflection to do annotation processing at runtime. I use Spring Boot in my own projects. I use Spring Boot annotations in my code (e.g., AT Service, AT Autowired, AT RestController, etc). The Spring Boot application is the entrypoint. You are correct, there is always some entry point.
  • mostafa.S
    mostafa.S over 2 years
    @emory yes, in case of Spring Boot, it is quite clear. because Spring boot application is called in main() method, so it can run the processor it self at any time it wants. but some other frameworks such as AT EnableKafka. does java runtime call their processor? it's a big ambiguity for me.