Eclipse uses it's own compiler (ECJ) to compile Java code. Debugging a program compiled with Eclipse is easier, because simple code changes can be applied instantly (by the hot code replacement).
Maven on the other hand uses (by default) oracle JDK, that generates different byte code preventing hot code replacement in a Eclipse debug session.
So I would like to use Eclipse ECJ compiler with my maven build, if I plan to debug the program. A convenient way for me would be a "ecj" profile:
Compile release
$ mvn package
Compile snapshot with enabled hot code replacement
$ mvn -P ecj package
Also the profile activation can be specified in settings.xml or even Eclipse project properties.
My questions are:
Is this the right way to go?
How this can be configured?
Can maven toolchain be used for this?
The Eclipse Java Compiler (ecj) has a lot of advantages over the standard javac compiler. It is fast, and it has way more warnings and errors that can be configured, improving code quality. One of the most interesting things in the compiler is the addition of null types inside the compiler: by annotating your code with #Nullable and #NotNull annotations you can force the Eclipse compiler to check null accesses at compile time instead of runtime. When applied rigorously this teaches you to code way more safe (by preventing null values) and it prevents NPE exceptions during testing or production.
To use the Eclipse Compiler inside Maven is not too hard, but there is a lot of misinformation and old information on the Internets which causes a lot of confusion. I hope this helps to set things straight.
To make Maven use the ecj compiler you need to use the plexus-compiler-eclipse plugin and nothing else. A typical configuration would be the following:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<compilerId>eclipse</compilerId>
<source>${source.jdk.version}</source>
<target>${target.jdk.version}</target>
<!-- Passing arguments is a trainwreck, see https://issues.apache.org/jira/browse/MCOMPILER-123 -->
<compilerArguments>
<properties>${project.basedir}/.settings/org.eclipse.jdt.core.prefs</properties>
</compilerArguments>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.8.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>ecj</artifactId>
<version>3.13.101</version>
</dependency>
</dependencies>
</plugin>
</pluginManagement>
Put this part in either the pluginManagement or the build section of your parent/root pom.
Now let's explain the different parts ;)
The maven-compiler-plugin needs to be of a recent version. The source and target parameters define the versions of java to use for source code and bytecode, and are usually the same.
Passing arguments to the compiler is an utter trainwreck. See the separate section on that below here. In this example I use the properties setting which allows me to provide detailed settings on which errors and warnings I want to have when compiling things. By using the ${project.basedir} variable inside the parameter I have these settings per project: every project is required to have a .settings/org.eclipse.jdt.core.prefs file present (which is by happy chance the location where the Eclipse IDE leaves its compiler settings).
The dependency on plexus-codehaus-eclipse defines the plugin that knows how to run the Eclipse compiler. The 2.8.3 version was the latest at the time of writing but this version has a few issues. Version 2.8.4 should come with a rewritten interface to the compiler which fixes a lot of issues, but this version is still in the works at the time of writing. You can find details on the plugin here, so progress can be followed on new releases/code changes.
The other important dependency is the org.eclipse.jdt:ecj dependency: this one specifies the exact version of the ecj compiler to use. You should always specify it because otherwise build stability will suffer when the plugin decides to use another version of the compiler one day before you have a big release ;) The version number to use for the ecj compiler is a bit of a problem. You might be able to find the version number from the list of releases and then check this maven repository for something that looks like it. But this repository only contains the older versions. When you need a more recent release you should apparently look here at this one - this is where Eclipse currently pushes its versions. This newer repository does away with the easily recognizable version numbers of the earlier one; it uses version numbers like 3.1x.x as seen above. Eclipse usually has a major release once every year plus one or two fix releases in between. The second part in the 3.13.x number corresponds to the internal versioning used inside the Eclipse Platform project for releases. It is hard to get by a list but at least these are known:
Version Eclipse Release Compiler Version
3.13.0 Oxygen Release 4.7
3.13.50 Oxygen 1a 4.7.1a
3.13.100 Oxygen R2 4.7.2
The version always starts with 3, the 13 is more or less the "year" of the release. So when 13 is Oxygen (2017, 4.7) 14 will probably be Photon (2018, 4.8).
Versions of the plexus-compiler-eclipse plugin: before 2.8.4
Versions before 2.8.4 of the plexus-compiler-plugin used an internal API to start the Eclipse compiler. This causes a lot of things not to work that well, as this internal API, for instance, does not interpret the usual command line parameters of the ecj compiler. This makes it quite hard to use, and some things are not supported. The following is a list of restrictions:
Annotations processing is not implemented. Any configuration is silently ignored.
Adding specific parameters by using the <compilerArguments> tag is hard as there are multiple problems with the implementation:
The compiler mojo seems to add dashes to all parameters entered here. The internal API used by this version of the plugin, however, needs parameters without dashes. So the plugin removes them again.
As the parameters here are not really command line ecj parameters it is hard to know which ones to use: look at the Compiler.java class and CompilerOptions.java classes inside Eclipse's source code for details.
The plugin DOES accept some parameters there, but these are interpreted by the plugin itself and then "translated" to the internal api.
This plugin accepts the following parameters in the <compilerArguments>> tag:
<properties>filename</properties>: defines a properties file that will be passed to the -properties parameter of the compiler. Examples of this file's format can be found by looking at the file .settings/org.eclipse.jdt.core.prefs in an Eclipse project: this file stores the compiler's configuration. It contains settings for warnings, errors and informational messages plus compiler compliance settings.
<errorsAsWarnings>whatever</errorsAsWarnings>. When this is valid the plugin will ignore any error that is generated by the compiler and report them as warnings. Of course compilation still failed so depending on the error a .class file might have been written/updated or not. This gets handled by the plugin itself: it just changes all errors to warnings and tells the world that compilation worked.
From 2.8.4
Version 2.8.4 of the plexus-compiler-eclipse plugin has been mostly rewritten. It now uses the public API of the ECJ compiler which more or less is the ECJ compiler itself. This for instance means that everything that ECJ can do (like annotations processing) the plugin can now do too, and parameters entered in the tag are now passed to the compiler, which means you should be able to use ecj's help page to find out interesting parameters to add.
Like the previous version this version also requires you to remove the '-' from all parameter names; the dash is automagically added again before the parameter name is added to the ecj command line.
This version supports annotation processing as defined by Maven; by adding the required parts to the compilation blob you can have your annotation processors run. For example:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<annotationProcessors>
<annotationProcessor>db.annotationprocessing.EntityAnnotationProcessor</annotationProcessor>
</annotationProcessors>
<annotationProcessorPaths>
<dependency>
<groupId>to.etc.domui</groupId>
<artifactId>property-annotations-processor</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
</annotationProcessorPaths>
</configuration>
<dependencies>
<dependency>
<groupId>to.etc.domui</groupId>
<artifactId>property-annotations-processor</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
This part may seem incomplete because there is no reference to the plexus-compiler-eclipse plugin at all, but remember that in Maven that configuration inherits: the parent POM in this case contained the part above, and this just adds a bit of configuration for this POM's project only.
It is possible to change the default javac compiler that is used by the maven-compiler-plugin. The Eclipse compiler is bundled in the artifact plexus-compiler-eclipse and it is declared by setting the compilerId attribute of the maven-compiler-plugin to eclipse.
If you want to activate this change for a custom profile, you could have the following configuration:
<profile>
<id>ecj</id>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<compilerId>eclipse</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
The plugin is maintained in the plexus-compiler GitHub repository. Version 2.8.1 uses 3.11.1.v20150902-1521 of JDT, although you could use your own version by adding a dependency on org.eclipse.tycho:org.eclipse.jdt.core after the Plexus Compiler dependency.
Related
I am using the latest version of STS which at the moment is 4.11. I'm building a new project and trying to get AspectJ CTW working with Spring Boot. I have some unit tests to check the aspects with #Async method calls. The funny thing is that the unit tests pass with a maven clean install, but not when building through STS.
I believe the reason is the AJDT plugin or AJDT configurator plugins are not working because I see this error:
Plugin execution not covered by lifecycle configuration:
dev.aspectj:aspectj-maven-plugin:1.13.M3:compile
(execution: default, phase: compile)
I am using the latest aspectj maven plugin with these settings.
<plugin>
<groupId>dev.aspectj</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.13.M3</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<complianceLevel>${maven.compiler.target}</complianceLevel>
<encoding>${project.build.sourceEncoding}</encoding>
<XnoInline>true</XnoInline>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
And I tried to install these two software installations:
http://download.eclipse.org/tools/ajdt/410/dev/update
http://dist.springsource.org/release/AJDT/configurator/
Getting this set up always seems to be a pain. Has anyone managed to do it with Java 11?
AspectJ Development Tools (AJDT)
I do not use STS, but mostly IntelliJ IDEA and if Eclipse, then plain Eclipse for Java developers. A while ago, I prepared a new AJDT version for Eclipse 2021-03, which still seems to be working in 2021-06, while developing AspectJ 1.9.7.
Try downloading the latest snapshot from aspectj.dev:
https://aspectj.dev/maven/org/eclipse/ajdt/org.eclipse.ajdt.releng/2.2.4-SNAPSHOT/
At the time of writing this, the latest snapshot is:
https://aspectj.dev/maven/org/eclipse/ajdt/org.eclipse.ajdt.releng/2.2.4-SNAPSHOT/org.eclipse.ajdt.releng-2.2.4-20210509.044425-2.zip
Sorry that I cannot provide you with a regular Eclipse update site, but while contributing to AspectJ, I have no access to the Eclipse infrastructure. The lead developer is busy, so my own web server is the easiest way to provide you with AJDT. The ZIP archive is about 15 MB in size. You can import it into Eclipse as a virtual update site as described here (scroll to "Install AJDT (AspectJ Development tools) for Eclipse IDE").
AspectJ Maven Plugin by aspectj.dev
Some small news: Yesterday I released version 1.13 of AspectJ Maven. It has a few more improvements compared to 1.13.M3, most notably 1.13
depends on AspectJ 1.9.8.M1 by default (you can also use 1.9.7, of course, but 1.9.8.M1 supports the --release N compiler switch),
recognises language level 17 as a valid parameter for source, target, compliance level and release parameters, i.e. it can be used with latest AspectJ 1.9.8 snapshots in order to experimentally compile Java 17-EA,
has precedence rules for compiler level settings, i.e. if compliance level is set, you do not need source and target (they are the same) and if you set source and target, you do not need to specify compliance level anymore. That before you had to set all three, was always a bug IMO. Besides, if you set the release for cross-compilation, all of source, target and compliance level are ignored.
More information can be found on the plugin's GitHub site.
Update: I found an m2e connector for AJDT which is maintained by Miika Vesti for his private use. At first it was not working for the dev.aspectj groupID, because he had forgotten to push an update to the Eclipse update site, but I got in touch with him and now it works. Please see the project's read-me for more information. You can use the existing update site for Eclipse 2020-12 in order to install a connector which also works on Eclipse 2021-06.
The connector needs some more work in order to import all AspectJ Maven settings correctly, e.g. it does not work in some of my projects where I deactivated Maven Compiler Plugin, because it currently relies on it being active and things like source/target compiler levels being configured there. Only then it will also correctly import source and target directories as well as dependencies - most prominently the Aspectj runtime library - correctly and result in a usable Eclipse project. I am trying to work with Miika in order to make the connector more self-sufficient in the future.
I have a requirement to compile an app for use under JRE 6.
Initially the app was compiled for use under JRE 8.
So I added:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.6</maven.compiler.source>
<maven.compiler.target>1.6</maven.compiler.target>
</properties>
to pom.xml
After fixing all the errors caused by unavaiable diamond operator, string in switch statement etc. I ran the app under JRE 6 and got the error.
Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: java/nio/file/Paths
Ok. This class is available only since Java 7. But the question arises: what does the above maven setting exactly? Does it only check the syntax? If so, then it's not quite useful.
What needs to be done to configure maven so that it notifies me about missing classes in particular Java version too?
java.nio.file.Paths was introduced in Java 7. You will have to change the implementation of your code to only use classes available in Java 6.
And yes, the Maven property only tells javac to use Java 6 syntax. That's very useful. Maven will not magically change your code for you. javac started by mvn package will tell you about unresolveable imports.
The purpose is to instruct maven to pass the -source and -target to the javac compile executable. It makes sure you only use language features that are available in the given JRE (the diamond operator is a great example), but it does not prevent use of APIs that only came along later.
Have a read of this
In particular the part at the bottom of the page:
Merely setting the target option does not guarantee that your code actually runs on a JRE with the specified version. The pitfall is unintended usage of APIs that only exist in later JREs...
I think it's unfair to say the parameters are not useful they certainly are. But they are not magical tools that know which libraries may be available at runtime.
The Animal Sniffer plugin for maven verifies that classes compiled with a newer JDK/API are compatible with an older JDK/API.
https://www.mojohaus.org/animal-sniffer/
Ok. I figured out how to do it.
You don't have to install the target JDK or JRE. All you need is rt.jar from that JRE.
Then you have to set the path to the jar file in bootclasspath in pom.xml.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<compilerArguments>
<verbose />
<bootclasspath>C:/data/tmp/rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
A couple of days ago, I upgraded Jenkins to version 1.643. Before, we were using Jenkins 1.593. Starting with Jenkins 1.612, Jenkins requires Java 7, see changelog, announcement and issue. Our Jenkins server has Java 8.
I have a Maven project consisting of submodules.
In the job configuration in Jenkins, I have configured the build to use JDK 1.6.
When looking at the build environment, it's indeed 1.6:
JAVA_HOME=/var/lib/jenkins/tools/hudson.model.JDK/1.6
One of the submodules fails to build on Jenkins, with this error:
[ERROR] /var/lib/jenkins/<REDACTED>.java:[15,-1] cannot access java.lang.Object
bad class file: java/lang/Object.class(java/lang:Object.class)
class file has wrong version 52.0, should be 50.0
According to what I can Google, class file version 52.0 is JDK 1.8 while the compiler is expecting version 50.0, which is JDK 1.6. I assuming that class file 52.0 refers to rt.jar (Java Runtime) which contains java.lang.Object (see also pom.xml snippet below).
I have found this SO question (and others that are duplicate of it), but they are all in the context of someone building from their IDE (IntelliJ) or from command prompt, and after reading them, I don't see how I could apply the suggested solutions. They involve setting $JAVA_HOME, which is already done by Jenkins.
My question is different because the issue is in the context of Jenkins (and Maven), and only occurred after the Jenkins upgrade. When I execute mvn clean install on my own desktop (with JDK 1.8), the error does not occur. If I execute the file command on the offending class file, but on the desktop where compilation succeeded, I get compiled Java class data, version 50.0 (Java 1.6). For me, this confirms that my pom.xml is (probably) still correct and it's (probably) a Jenkins configuration issue.
That specific submodule has this in the pom.xml, which may or may not be relevant:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArguments>
<verbose />
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
So, as you can see, it takes rt.jar from the current $JAVA_HOME so it can cross compile with a target of 1.6.
I'm a bit lost about the origin of this Java 8. Before the Jenkins upgrade, we were already using Java 8 on the server and cross compiling with a target of Java 6. What am I missing here?
EDIT
Do I even need this? If I comment out
<compilerArguments>
<verbose />
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
</compilerArguments>
in pom.xml, I can still cross compile on my desktop and the class files are still version 50.0.
EDIT
When I take that part out, the build does not fail any more.
Which means I solved it myself.
I want to change the question to: why did it fail in the first place? And why didn't it fail before on Jenkins 1.593?
I changed my pom.xml to exactly how it is described in this SO answer: Maven release plugin: specify java compiler version
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<bootclasspath>${java.home}/lib/rt.jar</bootclasspath>
</configuration>
</plugin>
</plugins>
</build>
As you can see:
I explicitly set the groupId
I explicitly set the version to the latest version, 3.3
The configuration parameters are formatted a bit differently.
My educated guess is that the Maven on the Jenkins server didn't pick up configuration inside compilerArguments and was only happy when it is directly inside configuration. I leave it to the comments to explain how and why, but for me the issue is solved.
I think you have a few errors in your assumptions.
compilerArguments is deprecated. It's been superseded by compilerArgs.
Like you can see from compiler plugin documentation, compilerArguments/compilerArgs is meant to be used only for arguments not supported by configuration section itself. As bootclasspath is supported, using it in compilerArgs/compilerArguments section is generally incorrect.
compilerArgs/compilerArguments is only used if fork is set to true, which was not correct for your configuration.
The third point was probably the most important reason why it didn't work for you. Using configuration section for your use case there should be no issues, and indeed based on your question/answer, this seems to be the case.
Also note that java.home is not JAVA_HOME. I've expanded on that on my other answer here. I'd guess that is related to why you see changes between Jenkins versions.
Eclipse uses it's own compiler (ECJ) to compile Java code. Debugging a program compiled with Eclipse is easier, because simple code changes can be applied instantly (by the hot code replacement).
Maven on the other hand uses (by default) oracle JDK, that generates different byte code preventing hot code replacement in a Eclipse debug session.
So I would like to use Eclipse ECJ compiler with my maven build, if I plan to debug the program. A convenient way for me would be a "ecj" profile:
Compile release
$ mvn package
Compile snapshot with enabled hot code replacement
$ mvn -P ecj package
Also the profile activation can be specified in settings.xml or even Eclipse project properties.
My questions are:
Is this the right way to go?
How this can be configured?
Can maven toolchain be used for this?
The Eclipse Java Compiler (ecj) has a lot of advantages over the standard javac compiler. It is fast, and it has way more warnings and errors that can be configured, improving code quality. One of the most interesting things in the compiler is the addition of null types inside the compiler: by annotating your code with #Nullable and #NotNull annotations you can force the Eclipse compiler to check null accesses at compile time instead of runtime. When applied rigorously this teaches you to code way more safe (by preventing null values) and it prevents NPE exceptions during testing or production.
To use the Eclipse Compiler inside Maven is not too hard, but there is a lot of misinformation and old information on the Internets which causes a lot of confusion. I hope this helps to set things straight.
To make Maven use the ecj compiler you need to use the plexus-compiler-eclipse plugin and nothing else. A typical configuration would be the following:
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<compilerId>eclipse</compilerId>
<source>${source.jdk.version}</source>
<target>${target.jdk.version}</target>
<!-- Passing arguments is a trainwreck, see https://issues.apache.org/jira/browse/MCOMPILER-123 -->
<compilerArguments>
<properties>${project.basedir}/.settings/org.eclipse.jdt.core.prefs</properties>
</compilerArguments>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.8.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.jdt</groupId>
<artifactId>ecj</artifactId>
<version>3.13.101</version>
</dependency>
</dependencies>
</plugin>
</pluginManagement>
Put this part in either the pluginManagement or the build section of your parent/root pom.
Now let's explain the different parts ;)
The maven-compiler-plugin needs to be of a recent version. The source and target parameters define the versions of java to use for source code and bytecode, and are usually the same.
Passing arguments to the compiler is an utter trainwreck. See the separate section on that below here. In this example I use the properties setting which allows me to provide detailed settings on which errors and warnings I want to have when compiling things. By using the ${project.basedir} variable inside the parameter I have these settings per project: every project is required to have a .settings/org.eclipse.jdt.core.prefs file present (which is by happy chance the location where the Eclipse IDE leaves its compiler settings).
The dependency on plexus-codehaus-eclipse defines the plugin that knows how to run the Eclipse compiler. The 2.8.3 version was the latest at the time of writing but this version has a few issues. Version 2.8.4 should come with a rewritten interface to the compiler which fixes a lot of issues, but this version is still in the works at the time of writing. You can find details on the plugin here, so progress can be followed on new releases/code changes.
The other important dependency is the org.eclipse.jdt:ecj dependency: this one specifies the exact version of the ecj compiler to use. You should always specify it because otherwise build stability will suffer when the plugin decides to use another version of the compiler one day before you have a big release ;) The version number to use for the ecj compiler is a bit of a problem. You might be able to find the version number from the list of releases and then check this maven repository for something that looks like it. But this repository only contains the older versions. When you need a more recent release you should apparently look here at this one - this is where Eclipse currently pushes its versions. This newer repository does away with the easily recognizable version numbers of the earlier one; it uses version numbers like 3.1x.x as seen above. Eclipse usually has a major release once every year plus one or two fix releases in between. The second part in the 3.13.x number corresponds to the internal versioning used inside the Eclipse Platform project for releases. It is hard to get by a list but at least these are known:
Version Eclipse Release Compiler Version
3.13.0 Oxygen Release 4.7
3.13.50 Oxygen 1a 4.7.1a
3.13.100 Oxygen R2 4.7.2
The version always starts with 3, the 13 is more or less the "year" of the release. So when 13 is Oxygen (2017, 4.7) 14 will probably be Photon (2018, 4.8).
Versions of the plexus-compiler-eclipse plugin: before 2.8.4
Versions before 2.8.4 of the plexus-compiler-plugin used an internal API to start the Eclipse compiler. This causes a lot of things not to work that well, as this internal API, for instance, does not interpret the usual command line parameters of the ecj compiler. This makes it quite hard to use, and some things are not supported. The following is a list of restrictions:
Annotations processing is not implemented. Any configuration is silently ignored.
Adding specific parameters by using the <compilerArguments> tag is hard as there are multiple problems with the implementation:
The compiler mojo seems to add dashes to all parameters entered here. The internal API used by this version of the plugin, however, needs parameters without dashes. So the plugin removes them again.
As the parameters here are not really command line ecj parameters it is hard to know which ones to use: look at the Compiler.java class and CompilerOptions.java classes inside Eclipse's source code for details.
The plugin DOES accept some parameters there, but these are interpreted by the plugin itself and then "translated" to the internal api.
This plugin accepts the following parameters in the <compilerArguments>> tag:
<properties>filename</properties>: defines a properties file that will be passed to the -properties parameter of the compiler. Examples of this file's format can be found by looking at the file .settings/org.eclipse.jdt.core.prefs in an Eclipse project: this file stores the compiler's configuration. It contains settings for warnings, errors and informational messages plus compiler compliance settings.
<errorsAsWarnings>whatever</errorsAsWarnings>. When this is valid the plugin will ignore any error that is generated by the compiler and report them as warnings. Of course compilation still failed so depending on the error a .class file might have been written/updated or not. This gets handled by the plugin itself: it just changes all errors to warnings and tells the world that compilation worked.
From 2.8.4
Version 2.8.4 of the plexus-compiler-eclipse plugin has been mostly rewritten. It now uses the public API of the ECJ compiler which more or less is the ECJ compiler itself. This for instance means that everything that ECJ can do (like annotations processing) the plugin can now do too, and parameters entered in the tag are now passed to the compiler, which means you should be able to use ecj's help page to find out interesting parameters to add.
Like the previous version this version also requires you to remove the '-' from all parameter names; the dash is automagically added again before the parameter name is added to the ecj command line.
This version supports annotation processing as defined by Maven; by adding the required parts to the compilation blob you can have your annotation processors run. For example:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<annotationProcessors>
<annotationProcessor>db.annotationprocessing.EntityAnnotationProcessor</annotationProcessor>
</annotationProcessors>
<annotationProcessorPaths>
<dependency>
<groupId>to.etc.domui</groupId>
<artifactId>property-annotations-processor</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
</annotationProcessorPaths>
</configuration>
<dependencies>
<dependency>
<groupId>to.etc.domui</groupId>
<artifactId>property-annotations-processor</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
This part may seem incomplete because there is no reference to the plexus-compiler-eclipse plugin at all, but remember that in Maven that configuration inherits: the parent POM in this case contained the part above, and this just adds a bit of configuration for this POM's project only.
It is possible to change the default javac compiler that is used by the maven-compiler-plugin. The Eclipse compiler is bundled in the artifact plexus-compiler-eclipse and it is declared by setting the compilerId attribute of the maven-compiler-plugin to eclipse.
If you want to activate this change for a custom profile, you could have the following configuration:
<profile>
<id>ecj</id>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<compilerId>eclipse</compilerId>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-eclipse</artifactId>
<version>2.8.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
The plugin is maintained in the plexus-compiler GitHub repository. Version 2.8.1 uses 3.11.1.v20150902-1521 of JDT, although you could use your own version by adding a dependency on org.eclipse.tycho:org.eclipse.jdt.core after the Plexus Compiler dependency.
In one of the classes I have this code:
str.isEmpty()
which compiles fine until I add this element to the POM:
<parent>
<artifactId>teevra.platform.parent</artifactId>
<groupId>com.hs.fusion</groupId>
<version>2.0.0</version>
</parent>
And then immediately the eclipse starts giving an error saying "The method isEmpty() is undefined for the type String". I obviously need this parent to access classes/interfaces needed for this child project.
I wonder what is causing the shift from Java Version 1.6 to 1.4 and how can it be prevented? Even more baffling is the fact that from command prompt, the project builds fine but not in Eclipse Juno.
Any help would be greatly appreciated,
G.
You need to specify the specific version of java to use. your problem is probably that your eclipse default is different from the maven default, so as soon as you add the dependency, m2e regenerates the project settings using the maven default (1.5)
Just specify the required java version explicitly. Something like this in your plugins section
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
To ensure that no invalid JRE calls leak into your project, you should use http://mojo.codehaus.org/animal-sniffer/ It seems like your parent lowered the source/target of the maven-compiler-plugin