I am trying to use ErrorProne and Lombok together.
Various open issues in this repos suggest that this is possible but perhaps difficult or unsupported?
I have found that using ErrorProne seems to entirely disable the "@Value" and "@Data" and similar Lombok annotations, causing compile errors in code that relies on the getters generated by these annoations.
How can I get these two libraries to work together?
I am trying to use ErrorProne on a codebase that relies on Lombok code-generation annotations.
I have prepared two simple examples based on the "examples/maven" example in this repos:
The relevant class looks like this:
import lombok.Value;
@Value
public class SomeDataClass {
public String name;
@Override
public String toString() {
return "SomeDataClass[" + this.getName() + "]";
}
}
1) Maven and Lombok together: https://github.com/RichardBradley/error-prone/tree/d3ca8c6716a8cde2b2489f5beafa36837acc54e9/examples/maven-with-lombok
This fails to build with the following message:
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] C:\Work\error-prone\examples\maven-with-lombok\src\main\java\SomeDataClass.java:[11,38] error: cannot find symbol
symbol: method getName()
[INFO] 1 error
2) The same code, but with ErrorProne disabled: https://github.com/RichardBradley/error-prone/tree/ccadedda3/examples/maven-with-lombok
This builds fine
Latest master, 976ab7c62771 (2.3.3-SNAPSHOT)
Related issues:
@Data with ErrorProne, closed as dupMany thanks,
Rich
Lombok needs to be in the processor path. By default, the processor path is the same as the compilation classpath, so adding Lombok as a project dependency is enough. But as soon as your specify it explicitly (through <annotationProcessorPaths> in Maven), you need to add to it everything that needs to be there, and that includes Lombok.
Specifically, you need to add it as a project dependency so you can use the annotations, and in the <annotationProcessorPaths> so that it can process them (and do its dark magic generating code where it's not supposed to)
Thanks, that's very helpful. I have created PRs with suggested doc improvements to help users with similar issues in the future.
I am now getting "Compilation Failure" with no error info from Maven, but I will keep digging.
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ errorprone-example ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 3 source files to C:\Work\error-prone\examples\maven-with-lombok\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.907 s
[INFO] Finished at: 2018-11-23T14:38:20Z
[INFO] Final Memory: 24M/981M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project errorprone-example: Compilation failure -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
{
Repro at: https://github.com/RichardBradley/error-prone/tree/00df8f2a7/examples/maven-with-lombok
I am using javac 1.8.0_151 on Windows 10 x64
I have attempted to run javac using the args passed to it by Maven (determined using mvn -X compile) in the above repro case and I get this output:
A plugin threw an uncaught exception.
Consult the following stack trace for details.
java.lang.NoSuchMethodError: com.sun.tools.javac.util.JavacMessages.add(Lcom/sun/tools/javac/util/JavacMessages$ResourceBundleHelper;)V
at com.google.errorprone.BaseErrorProneJavaCompiler.setupMessageBundle(BaseErrorProneJavaCompiler.java:202)
at com.google.errorprone.ErrorProneJavacPlugin.init(ErrorProneJavacPlugin.java:40)
at com.sun.tools.javac.main.Main.compile(Main.java:470)
at com.sun.tools.javac.main.Main.compile(Main.java:381)
at com.sun.tools.javac.main.Main.compile(Main.java:370)
at com.sun.tools.javac.main.Main.compile(Main.java:361)
at com.sun.tools.javac.Main.compile(Main.java:56)
at com.sun.tools.javac.Main.main(Main.java:42)
Rather strangely, it seems that the "-J-Xbootclasspath/p:..." arg is not printed by maven -X compile. It is not clear to me whether Maven is not passing this arg or if it is passing it but hiding it from the debug output somehow.
If I retry and manually add that arg, then I get this error from javac:
An annotation processor threw an uncaught exception.
Consult the following stack trace for details.
java.lang.NoClassDefFoundError: com/sun/tools/javac/file/BaseFileObject
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at lombok.launch.ShadowClassLoader.loadClass(ShadowClassLoader.java:448)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at lombok.javac.apt.LombokFileObjects$Compiler$2.wrap(LombokFileObjects.java:60)
at lombok.javac.apt.LombokFileObjects.createEmpty(LombokFileObjects.java:109)
at lombok.javac.apt.InterceptingJavaFileManager.getJavaFileForOutput(InterceptingJavaFileManager.java:47)
at com.sun.tools.javac.processing.JavacFiler.createSourceOrClassFile(JavacFiler.java:499)
at com.sun.tools.javac.processing.JavacFiler.createSourceFile(JavacFiler.java:425)
at lombok.javac.apt.LombokProcessor.forceNewRound(LombokProcessor.java:289)
at lombok.javac.apt.LombokProcessor.process(LombokProcessor.java:278)
at lombok.core.AnnotationProcessor$JavacDescriptor.process(AnnotationProcessor.java:114)
at lombok.core.AnnotationProcessor.process(AnnotationProcessor.java:164)
at lombok.launch.AnnotationProcessorHider$AnnotationProcessor.process(AnnotationProcessor.java:59)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:968)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:884)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.access$2200(JavacProcessingEnvironment.java:108)
at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1206)
at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1315)
at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1246)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:922)
at com.sun.tools.javac.main.Main.compile(Main.java:302)
at com.sun.tools.javac.main.Main.compile(Main.java:162)
at com.sun.tools.javac.Main.compile(Main.java:57)
at com.sun.tools.javac.Main.main(Main.java:43)
Caused by: java.lang.ClassNotFoundException: com.sun.tools.javac.file.BaseFileObject
at java.lang.ClassLoader.findClass(ClassLoader.java:530)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at lombok.launch.ShadowClassLoader.loadClass(ShadowClassLoader.java:418)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 26 more
(and indeed, that file does not exist in javac-9+181-r4173-1.jar)
It looks like Lombok 1.16.10 expects a version of javac which is incompatible with the javac provided by ErrorProne? Any ideas how I can fix?
It works if you update Lombok to 1.18.4.
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ errorprone-example ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 3 source files to /tmp/error-prone/examples/maven-with-lombok/target/classes
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /tmp/error-prone/examples/maven-with-lombok/src/main/java/Main.java:[20,4] error: [DeadException] Exception created but not thrown
(see https://errorprone.info/bugpattern/DeadException)
Did you mean 'throw new RuntimeException();'?
[ERROR] /tmp/error-prone/examples/maven-with-lombok/src/main/java/SomethingElse.java:[19,44] error: [GetClassOnClass] Calling getClass() on an object of type Class returns the Class object for java.lang.Class; you probably meant to operate on the object directly
(see https://errorprone.info/bugpattern/GetClassOnClass)
Did you mean 'System.out.println(String.class.toString());' or 'System.out.println(Class.class.toString());'?
[INFO] 2 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.734 s
[INFO] Finished at: 2018-11-23T15:58:38+01:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project errorprone-example: Compilation failure: Compilation failure:
[ERROR] /tmp/error-prone/examples/maven-with-lombok/src/main/java/Main.java:[20,4] error: [DeadException] Exception created but not thrown
[ERROR] (see https://errorprone.info/bugpattern/DeadException)
[ERROR] Did you mean 'throw new RuntimeException();'?
[ERROR] /tmp/error-prone/examples/maven-with-lombok/src/main/java/SomethingElse.java:[19,44] error: [GetClassOnClass] Calling getClass() on an object of type Class returns the Class object for java.lang.Class; you probably meant to operate on the object directly
[ERROR] (see https://errorprone.info/bugpattern/GetClassOnClass)
[ERROR] Did you mean 'System.out.println(String.class.toString());' or 'System.out.println(Class.class.toString());'?
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
Yep, that works for me.
Thanks very much for your help!
Most helpful comment
Lombok needs to be in the processor path. By default, the processor path is the same as the compilation classpath, so adding Lombok as a project dependency is enough. But as soon as your specify it explicitly (through
<annotationProcessorPaths>in Maven), you need to add to it everything that needs to be there, and that includes Lombok.Specifically, you need to add it as a project dependency so you can use the annotations, and in the
<annotationProcessorPaths>so that it can process them (and do its dark magic generating code where it's not supposed to)