This is the first time I am writing a Annotation Processor and I want to invoke it programmatically. Is it possible?
I have written small code for processor:
@SupportedAnnotationTypes({"app.dev.ems.support.annotation.HBMModel"})
public class HBMModelProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(HBMModel.class);
System.out.println(elements);
return true;
}
}
Now If I want to invoke the process method, then how can I do this? Can I do it in following way:
HBMModelProcessor modelProcessor = new HBMModelProcessor();
modelProcessor.process(annotations, roundEnv)
Any information will be very helpful to me.
Thanks.
This is a link to my answer to a similar question .
You could do annotation processing the way you suggest in your question, but you would somehow have to produce the annotations
and roundEnv
.
The intended use of annotation processing is during compilation. I recommend a two step compilation process.
The compiler will produce the annotations
and roundEnv
variables and an instance of your processor. (Most compilers require that your processor be public and have a public constructor.) The compiler will then invoke the process
method.
You can call the Java compiler with annotation processors programmatically, inside the same process, like this:
import com.sun.tools.javac.processing.PrintingProcessor;
import fi.jumi.actors.generator.JavaSourceFromString;
import org.junit.*;
import org.junit.rules.TemporaryFolder;
import javax.annotation.processing.Processor;
import javax.tools.*;
import javax.tools.JavaCompiler.CompilationTask;
import java.io.IOException;
import java.util.Arrays;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public class ExampleTest {
@Rule
public final TemporaryFolder tempDir = new TemporaryFolder();
@Test
public void example() throws IOException {
JavaFileObject src = new JavaSourceFromString(
"com.example.GuineaPig",
"package com.example;\n" +
"public interface GuineaPig {\n" +
" void foo();\n" +
"}"
);
compile(new PrintingProcessor(), src);
}
private void compile(Processor processor, JavaFileObject... compilationUnits) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(tempDir.getRoot()));
CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, Arrays.asList(compilationUnits));
task.setProcessors(Arrays.asList(
processor
));
boolean success = task.call();
for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
System.err.println(diagnostic);
}
assertThat("compile succeeded", success, is(true));
}
}
If you remove the call to setProcessors
then it will detect annotation processors automatically based on the META-INF/services/javax.annotation.processing.Processor
files on classpath.
jOOR has an API to simplify access to javax.tools.JavaCompiler
as shown in this answer . You can trigger it easily as follows:
Reflect.compile(
"com.example.MyClass",
"package com.example; "
+ "@app.dev.ems.support.annotation.HBMModel "
+ "class MyClass {}",
new CompileOptions().processors(new HBMModelProcessor())
);
This is specifically useful for unit testing annotation processors. See also this blog post here: https://blog.jooq.org/2018/12/07/how-to-unit-test-your-annotation-processor-using-joor
Disclaimer, I work for the company behind jOOR.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.