8

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
  • 11,673
  • 15
  • 68
  • 99

2 Answers2

6

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.

emory
  • 10,725
  • 2
  • 30
  • 58
  • "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? – corgrath Apr 20 '12 at 06:57
  • 1
    Yes, use `processingEnv.getFiler().createSourceFile(qualifiedName).openWriter()` 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 } ... – emory Apr 20 '12 at 07:04
  • Wow, the createSourceFile is great. I didn't know that was possible. Thanks :-) – corgrath Apr 20 '12 at 11:51
  • 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? – mostafa.S Jul 05 '21 at 05:30
  • @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. – emory Jul 06 '21 at 16:39
  • @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. – mostafa.S Jul 07 '21 at 05:15
1

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();
}
zeropouet
  • 124
  • 3
  • 11