Re: maven-compiler-plugin ignores Javac annotation processor error
Hi Thomas, Apparently, I failed a couple of times to make myself clear and did not run my tests thoroughly enough. 1. Yes, you're right, from the command line, only javac 1.8 displays the error message. Javac 1.7 does not display anything (being OpenJDK's or Oracle's). 2. No, I have never seen a build with a warning. I was describing what I was expecting from Maven. Also, turns out I had messed my env variables up and was always running Maven with java 1.7. When running Maven with Java 1.8, the build does fail as you describe. So, for the second bug, the conclusion is: run maven with Java 1.8 to get a nice failing build and if a problem there was, it really was between the chair and the keyboard. Sorry for the bother, but I did learn quite a lot. Thanks Sébastien Lesaint 2015-02-23 10:28 GMT+01:00 Thomas Broyer t.bro...@gmail.com: On Mon Feb 23 2015 at 09:53:24 Sébastien Lesaint sebastien.lesa...@gmail.com wrote: Hello, Thanks Thomas for your extensive answer. But you seemed to focus only on the first problem (which I had identified as potentially _not_ a bug). What about the fact that m-compiler-p ignores the error returned by Javac and allows the build to continue ? Right now, I have a successful build (it's a demo, there is no test defined) and there is just nothing working. I would be far more comprehensive if the javac error was reported, the build failed and a quick google search would pop the workaround (either proc:none or use @AutoService) for that specific error. WDYT ? This is rather strange. When using OpenJDK 7, the build succeeds without actually compiling anything; and if I run javac manually with the options taken from mvn -X output, it also succeeds, without any warning about the missing processor (even when also passing -Xprefer:source -XprintProcessorInfo -XprintRounds and/or -verbose; with -XprintRounds we clearly see there's a problem though: only one round, with last round: false). When using OpenJDK 8 however, the build fails with a clear error: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project test: Compilation failure [ERROR] Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider foo.bar.BazProcessor not found So it looks like it could be a Javac bug that's been fixed in Java 8. I don't reproduce the same behavior as the one you describe though (build passing with warning). Tests conducted with Maven 3.0.5 and Maven 3.2.3 on Ubuntu 14.10 with the Ubuntu-provided OpenJDK versions, and default m-compiler-p version from the Maven super-pom.
Re: maven-compiler-plugin ignores Javac annotation processor error
Hello, Thanks Thomas for your extensive answer. But you seemed to focus only on the first problem (which I had identified as potentially _not_ a bug). What about the fact that m-compiler-p ignores the error returned by Javac and allows the build to continue ? Right now, I have a successful build (it's a demo, there is no test defined) and there is just nothing working. I would be far more comprehensive if the javac error was reported, the build failed and a quick google search would pop the workaround (either proc:none or use @AutoService) for that specific error. WDYT ? Thanks, Sébastien Lesaint 2015-02-21 13:14 GMT+01:00 Thomas Broyer t.bro...@gmail.com: On Fri Feb 20 2015 at 21:11:14 Sébastien Lesaint sebastien.lesa...@gmail.com wrote: Hello, I have been into annotation processing a lot for the past year and a half and I am now going back to the basics so that I can share knowledge I gathered. Doing so, I stumbled upon, again, a problem I had meet very early, for which I had googled the solution, but this time I went deeper to figure out what was really wrong. # the symptoms When writing an annotation processor and creating the associated service-discovery file `META-INF/services/javax.annotation.processing.Processor in a Maven module, one needs to disable annotation processing completely (using the procnone/proc configuration option of the maven-compiler-plugin) otherwise the module compilation succeeds but not a single .class file is created. # how I investigated I compiled the module with the -X option, extracted the javac command line and ran it by hand. I got the following compilation error: error: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider com.foo.BarProcessor not found The thing is, the com.foo.BarProcessor is the very processor I am compiling (and the single .java file of the module). # what I found I went through the maven logs, spent some time thinking about it and believe that we are facing one, maybe two bugs in the maven-compiler-plugin: 1. Maven copies resources from the src/main/resources directory to the target/classes directory 2. the maven-compiler-plugin builds up a javac command line that specifies the target/classes directory as a member on the classpath with the argument -classpath (is that a bug ? there may be a good reason to do so but in a basic jar module setup I can see any) This is because of m-compiler-p's attempt at incremental compilation. It looks at all source files and if one doesn't have a corresponding *.class file or is newer then it adds it to the list of source files to recompile. Because those will likely reference other classes that might not have changed, target/classes is included in the classpath so that the already-compiled classes can be found. That said, incremental compilation is (was) kind-of broken, as it doesn't track class dependencies and won't recompile those classes that reference the classes that have changed. See https://cwiki.apache.org/confluence/display/MAVEN/Incremental+Builds for an example. If you ask me, m-compiler-p should just check whether something needs to be recompiled (which in itself is already error-prone, for many reasons [1]) and recompile everything. Actually, m-compiler-p 3.1+ should apparently behave that way by deleting all *.class files it had created in a previous run (unless you set useIncrementalCompilation=false [2]), so it shouldn't need target/classes to be part of the classpath, at least for this use-case of incremental compilation, but still includes it anyway. Takari has a new plugin (and lifecycle) that apparently does truly incremental compilation [3], by tracking class dependencies (when using JDT rather than javac). It'd still fail your use-case though IIUC, if it supported annotation processing through JDT (I haven't looked at how it handles incremental builds with javac). The other reason for target/classes to be in the classpath is so that annotation processors could find resources (let's not debate here whether it's a good idea or not). m-compiler-p developers can't seem to agree on what should be done: should m-compiler-p use -sourcepath sometimes [4] or always [5] ? Should target/classes be included in the sourcepath [6] ? [1] http://blog.ltgt.net/maven-is-broken-by-design/ (note: things have changed a bit since I wrote this; e.g. incremental build in m-compiler-p 3.1+, the Takari lifecycle, etc.) [2] https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#useIncrementalCompilation [3] http://takari.io/2014/10/16/incremental-compilation.html [4] https://jira.codehaus.org/browse/MCOMPILER-26, https://jira.codehaus.org/browse/MCOMPILER-174 [5] https://jira.codehaus.org/browse/MCOMPILER-98 [6] https://jira.codehaus.org/browse/MCOMPILER-122 3. when
Re: maven-compiler-plugin ignores Javac annotation processor error
On Mon Feb 23 2015 at 09:53:24 Sébastien Lesaint sebastien.lesa...@gmail.com wrote: Hello, Thanks Thomas for your extensive answer. But you seemed to focus only on the first problem (which I had identified as potentially _not_ a bug). What about the fact that m-compiler-p ignores the error returned by Javac and allows the build to continue ? Right now, I have a successful build (it's a demo, there is no test defined) and there is just nothing working. I would be far more comprehensive if the javac error was reported, the build failed and a quick google search would pop the workaround (either proc:none or use @AutoService) for that specific error. WDYT ? This is rather strange. When using OpenJDK 7, the build succeeds without actually compiling anything; and if I run javac manually with the options taken from mvn -X output, it also succeeds, without any warning about the missing processor (even when also passing -Xprefer:source -XprintProcessorInfo -XprintRounds and/or -verbose; with -XprintRounds we clearly see there's a problem though: only one round, with last round: false). When using OpenJDK 8 however, the build fails with a clear error: [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project test: Compilation failure [ERROR] Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider foo.bar.BazProcessor not found So it looks like it could be a Javac bug that's been fixed in Java 8. I don't reproduce the same behavior as the one you describe though (build passing with warning). Tests conducted with Maven 3.0.5 and Maven 3.2.3 on Ubuntu 14.10 with the Ubuntu-provided OpenJDK versions, and default m-compiler-p version from the Maven super-pom.
Re: maven-compiler-plugin ignores Javac annotation processor error
Sure this is not a Javac problem ? Jeff On Fri, Feb 20, 2015 at 9:09 PM, Sébastien Lesaint sebastien.lesa...@gmail.com wrote: Hello, I have been into annotation processing a lot for the past year and a half and I am now going back to the basics so that I can share knowledge I gathered. Doing so, I stumbled upon, again, a problem I had meet very early, for which I had googled the solution, but this time I went deeper to figure out what was really wrong. # the symptoms When writing an annotation processor and creating the associated service-discovery file `META-INF/services/javax.annotation.processing.Processor in a Maven module, one needs to disable annotation processing completely (using the procnone/proc configuration option of the maven-compiler-plugin) otherwise the module compilation succeeds but not a single .class file is created. # how I investigated I compiled the module with the -X option, extracted the javac command line and ran it by hand. I got the following compilation error: error: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider com.foo.BarProcessor not found The thing is, the com.foo.BarProcessor is the very processor I am compiling (and the single .java file of the module). # what I found I went through the maven logs, spent some time thinking about it and believe that we are facing one, maybe two bugs in the maven-compiler-plugin: 1. Maven copies resources from the src/main/resources directory to the target/classes directory 2. the maven-compiler-plugin builds up a javac command line that specifies the target/classes directory as a member on the classpath with the argument -classpath (is that a bug ? there may be a good reason to do so but in a basic jar module setup I can see any) 3. when run, javac finds a META-INF/services/javax.annotation.processing.Processor file in the classpath and looks for the specified processor com.foo.BarProcessor 4. obviously, this processor can not be found, javac reports an error and stops the compilation before it even started compiling anything (ence not a single .class file in the target directory) 5. the error (error: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider com.foo.BarProcessorr not found) is ignored by the maven-compiler-plugin that considers the compilation successful and the maven build goes on (this is our big bug) # bonus Please note that this has pernicious side effects. Since the build is successful, the jar which is supposed to contain the processor is created but only with the resources which means that it contains the META-INF/services/javax.annotation.processing.Processor file. Now, any module or project which has this jar file as a dependency will produce 0 .class file. Their compilation classpath is contaminated with a META-INF/services/javax.annotation.processing.Processor which references an non existent processor. Javac will therefor fail with the Bad service configuration file and produces no .class file. # affected versions I tested this with Maven 3.1.1 3.2.5, maven-compiler-plugin 2.5, 3.1 and 3.2 and Oracle JDK 6, 7 8 on a ubuntu 64 bits machine. But, according to the various posts, stackoverflow entries, etc. all around the web which provide the procnone/proc solution, it occurs on other setups. # conclusion I initially though I would file a bug in the maven-compiler-plugin JIRA but it is unclear how I can create an account. So, I am using this mailing list to reach to the experts and the developer to get accurate feedback on the matter. Thanks in advance, Sébastien Lesaint -- Jeff MAURY Legacy code often differs from its suggested alternative by actually working and scaling. - Bjarne Stroustrup http://www.jeffmaury.com http://riadiscuss.jeffmaury.com http://www.twitter.com/jeffmaury
Re: maven-compiler-plugin ignores Javac annotation processor error
On Sat Feb 21 2015 at 10:12:23 Jeff MAURY jeffma...@jeffmaury.com wrote: Sure this is not a Javac problem ? No it's not. target/classes contains the META-INF/services/javax.annotation.processing.Processor and it's put in the classpath, and because there's no support for processorpath [1], javac looks up annotation processors in the classpath; so it finds that file, which references a class that you're about to compile, and tries to find the class in the classpath, where it's obviously not. This issue is actually known for YEARS: https://jira.codehaus.org/browse/MCOMPILER-97 [1] https://jira.codehaus.org/browse/MCOMPILER-134
Re: maven-compiler-plugin ignores Javac annotation processor error
On Fri Feb 20 2015 at 21:11:14 Sébastien Lesaint sebastien.lesa...@gmail.com wrote: Hello, I have been into annotation processing a lot for the past year and a half and I am now going back to the basics so that I can share knowledge I gathered. Doing so, I stumbled upon, again, a problem I had meet very early, for which I had googled the solution, but this time I went deeper to figure out what was really wrong. # the symptoms When writing an annotation processor and creating the associated service-discovery file `META-INF/services/javax.annotation.processing.Processor in a Maven module, one needs to disable annotation processing completely (using the procnone/proc configuration option of the maven-compiler-plugin) otherwise the module compilation succeeds but not a single .class file is created. # how I investigated I compiled the module with the -X option, extracted the javac command line and ran it by hand. I got the following compilation error: error: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing.Processor: Provider com.foo.BarProcessor not found The thing is, the com.foo.BarProcessor is the very processor I am compiling (and the single .java file of the module). # what I found I went through the maven logs, spent some time thinking about it and believe that we are facing one, maybe two bugs in the maven-compiler-plugin: 1. Maven copies resources from the src/main/resources directory to the target/classes directory 2. the maven-compiler-plugin builds up a javac command line that specifies the target/classes directory as a member on the classpath with the argument -classpath (is that a bug ? there may be a good reason to do so but in a basic jar module setup I can see any) This is because of m-compiler-p's attempt at incremental compilation. It looks at all source files and if one doesn't have a corresponding *.class file or is newer then it adds it to the list of source files to recompile. Because those will likely reference other classes that might not have changed, target/classes is included in the classpath so that the already-compiled classes can be found. That said, incremental compilation is (was) kind-of broken, as it doesn't track class dependencies and won't recompile those classes that reference the classes that have changed. See https://cwiki.apache.org/confluence/display/MAVEN/Incremental+Builds for an example. If you ask me, m-compiler-p should just check whether something needs to be recompiled (which in itself is already error-prone, for many reasons [1]) and recompile everything. Actually, m-compiler-p 3.1+ should apparently behave that way by deleting all *.class files it had created in a previous run (unless you set useIncrementalCompilation=false [2]), so it shouldn't need target/classes to be part of the classpath, at least for this use-case of incremental compilation, but still includes it anyway. Takari has a new plugin (and lifecycle) that apparently does truly incremental compilation [3], by tracking class dependencies (when using JDT rather than javac). It'd still fail your use-case though IIUC, if it supported annotation processing through JDT (I haven't looked at how it handles incremental builds with javac). The other reason for target/classes to be in the classpath is so that annotation processors could find resources (let's not debate here whether it's a good idea or not). m-compiler-p developers can't seem to agree on what should be done: should m-compiler-p use -sourcepath sometimes [4] or always [5] ? Should target/classes be included in the sourcepath [6] ? [1] http://blog.ltgt.net/maven-is-broken-by-design/ (note: things have changed a bit since I wrote this; e.g. incremental build in m-compiler-p 3.1+, the Takari lifecycle, etc.) [2] https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#useIncrementalCompilation [3] http://takari.io/2014/10/16/incremental-compilation.html [4] https://jira.codehaus.org/browse/MCOMPILER-26, https://jira.codehaus.org/browse/MCOMPILER-174 [5] https://jira.codehaus.org/browse/MCOMPILER-98 [6] https://jira.codehaus.org/browse/MCOMPILER-122 3. when run, javac finds a META-INF/services/javax.annotation.processing.Processor file in the classpath and looks for the specified processor com.foo.BarProcessor 4. obviously, this processor can not be found, javac reports an error and stops the compilation before it even started compiling anything (ence not a single .class file in the target directory) 5. the error (error: Bad service configuration file, or exception thrown while constructing Processor object: javax.annotation.processing. Processor: Provider com.foo.BarProcessorr not found) is ignored by the maven-compiler-plugin that considers the compilation successful and the maven build goes on (this is our big bug) # bonus Please note that this has pernicious side effects. Since the build