Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Debugging Annotation processors in eclipse

I am writing a simple annotation processor and trying to debug it using eclipse. I created a new project for annotation processor and configured javax.annotation.processing.Processor under META-INF as needed and it processes annotations fine.

Then, I added some more code and tried debugging, but could never make the execution stop at the breakpoints added in the annotation processor. I am compiling using ant and I am using the following ANT options.

export ANT_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000"

After triggering ant build, i go create a remote debug configuration and the debugger starts fine. Ant build also starts successfully. But the execution never stops at any break point added in the annotation processor.

like image 963
user1793318 Avatar asked Jan 29 '14 09:01

user1793318


2 Answers

This is a problem I just ran into, and the eclipse plugin solution seems super cumbersome to me. I found a simpler solution using javax.tools.JavaCompiler to invoke the compilation process. Using the code below, you can just Right-Click > Debug As > JUnit Test in eclipse and debug you annotation processor directly from there

   @Test
   public void runAnnoationProcessor() throws Exception {
      String source = "my.project/src";

      Iterable<JavaFileObject> files = getSourceFiles(source);

      JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

      CompilationTask task = compiler.getTask(new PrintWriter(System.out), null, null, null, null, files);
      task.setProcessors(Arrays.asList(new MyAnnotationProcessorClass()));

      task.call();
   }

   private Iterable<JavaFileObject> getSourceFiles(String p_path) throws Exception {
     JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
     StandardJavaFileManager files = compiler.getStandardFileManager(null, null, null);

     files.setLocation(StandardLocation.SOURCE_PATH, Arrays.asList(new File(p_path)));

     Set<Kind> fileKinds = Collections.singleton(Kind.SOURCE);
     return files.list(StandardLocation.SOURCE_PATH, "", fileKinds, true);
   }
like image 50
ekj Avatar answered Sep 27 '22 21:09

ekj


This question has been posted over 6 years ago, however, I ran into the same problem now and still couldn't find a good answer on the Internet.

I was finally able to work out a good setup that allows me to develop an Annotation Processor, use it in compilation of another project, and debug it as needed.

The setup is like this:

  1. Annotation Processor developed in a project with GAV:

    <groupId>infra</groupId> <artifactId>annotation-processor</artifactId> <version>1.0-SNAPSHOT</version>

  2. In the annotation-processor POM file I specified the following:

    <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compiler.plugin.version}</version> <configuration> <compilerArgument>-proc:none</compilerArgument> <source>${java.source.version}</source> <target>${java.source.version}</target> <encoding>UTF-8</encoding> </configuration> </plugin> </plugins> </build>

    Notice the <compilerArgument>-proc:none</compilerArgument> specification.

  3. In the project where the annotation-processor is used, it is used during the compilation of the project. I.e. the annotation-processor is invoked during the execution of the compiler, javac. I found that in order to debug the annotation-processor execution while running javac directly, I can use the following command line:

    javac -J-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=1044 -d target/classes -proc:only -processor infra.annotation.CustomizationAnnotationProcessor -cp ../annotation-processor/target/annotation-processor-1.0-SNAPSHOT.jar src\main\java\org\digital\annotationtest\MyTestClass.java

    Notice the suspend=y part in the command line of javac. This tells the JVM to suspend execution until the debugger attaches to it.

  4. In this situation, I can start the eclipse debugger by starting a Remote Java Application Debug Configuration. Configure it to use the annotation-processor project, and attach to the process on localhost and port 1044. this allows you to debug the annotation processor code. If you set a breakpoint in the init or process methods, the debugger will break.

  5. In order to enable the same debug experience while compiling using Maven, I setup the POM file as follows:

    1. Add a dependency to the POM where the annotation-processor is used: <dependency> <groupId>infra</groupId> <artifactId>annotation-processor</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
    2. In the same project using the annotation-processor define the following:

    <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven.compiler.plugin.version}</version> <configuration> <source>1.8</source> <target>1.8</target> <fork>true</fork> <compilerArgs> <compilerArg>-J-verbose</compilerArg> <compilerArg>${enableDebugAnnotationCompilerArg}</compilerArg> </compilerArgs> <forceJavacCompilerUse>true</forceJavacCompilerUse> <annotationProcessorPaths> <annotationProcessorPath> <groupId>infra</groupId> <artifactId>annotation-processor</artifactId> <version>1.0-SNAPSHOT</version> </annotationProcessorPath> </annotationProcessorPaths> <annotationProcessors> <annotationProcessor>infra.annotation.CustomizationAnnotationProcessor</annotationProcessor> </annotationProcessors> </configuration> </plugin> </plugins> </build> <profiles> <profile> <id>debugAnnotation</id> <properties> <enableDebugAnnotationCompilerArg>-J-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=1044</enableDebugAnnotationCompilerArg> </properties> </profile> </profiles>

    Notice the use of <fork>true</fork>, and <compilerArg>${enableDebugAnnotationCompilerArg}</compilerArg>.
    Also, notice the profile deinition of debugAnnotation and the definition of the <enableDebugAnnotationCompilerArg> property. This allows us to start a debugging session of the annotation-processor by running mvn -P debugAnnotation package and attaching the eclipse debugger to the compiler process the same way as described in 4 above.

like image 41
AWesley Avatar answered Sep 27 '22 21:09

AWesley