Relationship between Eclipse default JRE, project compliance and compiler used - java

I couldn't understand for some time why my Maven project wasn't building in Eclipse and presented me with "Bad version number in .class file" errors.
I checked all my dependencies and ensured they were built for Java 6 or lower (using this handy JAR version checking tool).
I opened my project properties and confirmed I had project-specific compiler settings, set to compliance level 1.6.
I also confirmed I had the Java 6 libraries on my build path.
Finally, I discovered the cause was related to the default JRE selected for my workspace. This was set to jdk1.5 for some reason. Setting this to something higher than this (I chose jdk1.8) solved the issue. In the end, I had to select jdk1.7 to allow my AspectJ weaving to work correctly.
My question is: why did this solve it? According to the preferences page, this setting only influences which JRE is added to the build path of newly created Java projects. I can't fathom why this would affect my ability to build my project. Any suggestions? It seems as though Eclipse uses the default JRE selection to influence what type of compiler is used.
I'm using m2e to bind Eclipse and Maven. My POM build section is as follows:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<!-- http://maven.apache.org/plugins/maven-compiler-plugin/ -->
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.5</version>
<configuration>
<complianceLevel>1.6</complianceLevel>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Related

Problem running tests with enabled preview features in surefire and failsafe

I'm trying to migrate a project to Java 12, with --enable-preview.
I added --enable-preview in compiler settings:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>12</release>
<compilerArgs>
<arg>--enable-preview</arg>
</compilerArgs>
</configuration>
</plugin>
And also added it in argLine for surefire and failsafe:
<properties>
<argLine>--enable-preview</argLine>
</properties>
And do a mvn clean verify results in:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M3:test (default-test) on project lombok-jdk10: Execution default-test of goal org.apache.maven.plugins:maven-surefire-plugin:3.0.0-M3:test failed: java.lang.UnsupportedClassVersionError: Preview features are not enabled for com/kirela/lombok/BarTest (class file version 56.65535). Try running with '--enable-preview' -> [Help 1]
I also tried adding argLine directly to surefire/failsafe configuration, but the result is same.
What am I missing here?
I this a bug in surefire/failsafe?
EDIT2: Surefire and failsafe config:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<forkCount>2</forkCount>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<forkCount>2</forkCount>
</configuration>
</plugin>
EDIT3:
Minimal working example is here: https://github.com/krzyk/lombok-jdk10-example
The project fails with --enable-preview, but works when I remove it.
This works for me:
mvn clean install works (with junit tests)
IDEA recognizes module language level correctly as 12 (Preview) - Switch expressions
junit tests in IDEA work
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<release>12</release>
<compilerArgs>
<arg>--enable-preview</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
Environment:
Ubuntu 18.04.3 x64
IDEA 2019.2.1
Maven 3.6.0
jdk:
IMPLEMENTOR="Oracle Corporation"
JAVA_VERSION="12"
JAVA_VERSION_DATE="2019-03-19"
ADDITION: Similarly this approach works for java 13.
ADDITION: Similarly this approach works for java 17.
There are two solutions:
Add --enable-preview to MAVEN_OPTS environment variable.
Explanation by the maintainer of surefire:
The argLine does what it has to do without any issue.
The plugin runs JUnit filter which finally selects relevant classes to run in one or multiple JVMs.
So the JUnit engine runs twice. Once in plugin JVM, and second in the forked JVM.
Due to the classes are compiled with different major or minor version (in bytecode of *.class files) than the version of Java runtime supports in Maven, this JRE fails because Java in Maven does not understand the bytecode. So, it is curious that the same JVM (javac) produced two major versions depending on JVM option and java from the same JVM does not understand it been incompatible for itself. Although version in forked JVM is totally fine and understands the the classes compiled by javac because javac and forked JVM start with the same option --enable-preview.
It is the same situation as if you compiled your sources with Java 12 by maven-compiler-plugin using the toolchain and run the whole Maven build with Java 11. So the classes would be compiled with higher version (in bytecode) than the JRE could understand in Maven process.
We have a wish to rework providers and perform the filtering inside of the forked JVM but this is very compilicated change and still questionary.
The issue is that I used forkCount, it appears surefire doesn't pass parameters to JVM run in fork.
Remove the forkCount parameter from surefire/failsafe configuration.
This will of course cause the tests to run in a single JVM, so if you wanted to speed up the tests using the forks, it won't work now.
Add a configuration for surefire and failsafe maven plugin
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>

Maven: excluding files from compilation doesn't work in IntelliJ IDEA

I want to temporarily exclude some directory from compilation, so I configure maven-compiler-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/foo/**/*.java</exclude>
</excludes>
</configuration>
</plugin>
Everything works fine from the command line and Eclipse, but in IntelliJ IDEA I got compilation errors in excluded directory. Any idea what might be causing the problem?
It's an open issue, please follow for updates.
I had the same issue migrating maven projects.
I got it working by choosing below option:
File > Settings > Build, Execution, Deployment > Build Tools > Maven >
Runner
Check the 'Delegate IDE build/run actions to Maven' option.
Instruction is available here:
IntelliJ documentation
I found this question while trying to solve Java 9 module-info compilation in IntelliJ IDEA.
I want my library compiled with Java 8, but at the same time I want it to have module-info (which can be compiled only with JDK 9+). A solution of this problem suggested by Maven: exclude module-info from compilation with JDK 8 and include if JDK 9 is used. It works with command line but IDEA fails to compile such project. It is possible to adjust IDEA Compile configuration by adding module info to Excludes, but I wanted more clear solution.
It is possible to trick IDEA by adding Maven Profile with extended list of source directories:
<profile>
<!-- This profile enables two pass compilation:
1. Compile all sources with Java 9 target version (including module-info.java)
2. Recompile all sources with Java 8 target version, but module-info.java
After this all classes will have Java 8 bytecode (version 52), while
module-info.class will have Java 9 bytecode (version 53) -->
<id>J9-module</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<release>8</release>
</configuration>
<executions>
<execution>
<id>default-compile</id>
<goals>
<goal>compile</goal>
</goals>
<phase>compile</phase>
<configuration>
<compileSourceRoots>
<sourceRoot>${project.basedir}/src/main/java</sourceRoot>
<sourceRoot>${project.basedir}/src/main/java9</sourceRoot>
</compileSourceRoots>
<release>9</release>
</configuration>
</execution>
<execution>
<id>java-8-recompile</id>
<goals>
<goal>compile</goal>
</goals>
<phase>compile</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
With the profile shown above IDEA itself will compile only standard src/main/java.

Automatically generate Java from .proto with maven/m2e in Eclipse IDE

For my team, I'd like to configure maven/eclipse build to automatically generate Java code from *.proto files (in a project that uses gRPC). Currently one needs to run mvn generate-source or mvn protobuf:compile (as in plugin usage page). Or what is the same add Run configuration to invoke maven goal compile.
Whenever Eclipse Maven project is refreshed (Alt+F5) or IDE is restarted, project is rebuilt but without what should appear in target/generated, thus turning project into red. So one need to generate and refresh project (F5). UPDATE Eclipse has needed source folders configured in .clathpath file.
As I know that should be m2e connector, but I could only find one https://github.com/masterzen/m2e-protoc-connector for the oldest Googles plugin com.google.protobuf.tools:maven-protoc-plugin, that is even not mentioned currently at https://github.com/grpc/grpc-java
We use exactly referenced/recommended
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
that is:
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.4.1.Final</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.1:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Related:
Linking to generated Java protobuf code in Eclipse
looked at this but that author was using other older, not supported now plugin : Eclipse build loop caused by protobuf generated code (related to Maven Project Builder)
P.P.S That plugin https://github.com/igor-petruk/protobuf-maven-plugin however has continuation as https://github.com/os72/protoc-jar-maven-plugin
Instead of using org.xolstice.maven.plugins:protobuf-maven-plugin my team has used com.github.os72:protoc-jar-maven-plugin to generate the message classes. I believe they are the same since under the hood they all seem to be using the tools from Google.
I am not using any m2e connectors for this plugin (Edit: protoc-jar-maven-plugin's m2e connector is bundled with it so no extra installation is needed, which is why it seemed like I wasn't using one, but technically I was, but this doesn't really matter). Unfortunately the changes in the .proto file are not "automatically" propagated to the generated .java files, you need to manually run Maven or trigger the project to be built in Eclipse (instructions below), but fortunately the target/generated-sources file is not vanishing or emptying or anything strange like what you describe.
If you want to rebuild the .java files from the .proto classes without using mvn clean compile from the command line you can clean the Eclipse project . Project → Clean... → select your project → Select build option (only shows if you have "Build Automatically" from the Project menu is unchecked).
I was able to do this in the latest Eclipse Neon (it will probably work in later ones too, but I don't know for certain).
Below is the POM I am using. I don't think it requires any special explanation, my solution is to simply use a different plugin than the one you are using. (If some explanation is needed I'll be happy to provide it though.)
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.github.jacksonbailey</groupId>
<artifactId>protobuf-m2e-sample</artifactId>
<version>0.1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.github.os72</groupId>
<artifactId>protoc-jar-maven-plugin</artifactId>
<version>3.1.0.1</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<protocVersion>3.1.0</protocVersion>
<inputDirectories>
<include>src/main/resources</include>
</inputDirectories>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
for protobuf-maven-plugin
Thanks to sergei-ivanov answer in https://github.com/xolstice/protobuf-maven-plugin/issues/16, that gave link https://github.com/trustin/os-maven-plugin#issues-with-eclipse-m2e-or-other-ides :
One need to download os-maven-plugin-x.x.x.Final.jar (the version as in your pomx.ml) and put it into the <ECLIPSE_HOME>/plugins directory.
After that Eclipse will generate source on project clean, including after Maven -update project... (Alt+F5), but not after Project -> Build (or with default Build Automatically). Also on IDE start it will not compile.
Yes, that is illogical:
Project - Clean will generate and compile Java source
but
Project - Build will not.
P.S. Raised Bug 507412
Both eclipse and vscode can automatically compile proto when changed.
<plugin>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>detect</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.32.1:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
See: https://github.com/trustin/os-maven-plugin#issues-with-eclipse-m2e-or-other-ides

How to make Maven use JDK1.8 instead of JDK1.6

I am new to maven, and I find that though I change the facet of the jdk of the project to 1.8, every time I "update maven",it will get back to jdk 1.6.
Why is that?
I installed jdk 1.8 in my windows, and I am using eclipse.
I read Specify JDK for Maven to use and add the following but it does not work.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<executions>
<execution>
<id>enforce-versions</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireJavaVersion>
<version>1.8</version>
</requireJavaVersion>
</rules>
</configuration>
</execution>
</executions>
</plugin>
The version of the JDK that maven will use is set in the maven-compiler-plugin like so:
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source> <!-- use java 8 -->
<target>1.8</target>
</configuration>
</plugin>
See Setting the -source and -target of the Java Compiler for more information.
Check the maven compiler plugin to specify source and target java version,
http://maven.apache.org/plugins/maven-compiler-plugin/examples/set-compiler-source-and-target.html
Regards,
Prasanna
maybe too late, but it works for me:
<!-- we want JDK 1.8 source and binary compatiblility -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- ... -->
<!-- we want sources to be processed by a specific 1.8 javac -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<verbose>true</verbose>
<fork>true</fork>
<executable>${JAVA_1_8_HOME}/bin/javac</executable>
</configuration>
</plugin>
Your question help me a lot anyway :) Thanks :)
In a comment you asked:
So what about maven-enforcer-plugin, what is this to do?
According to that documentation for the plugin:
"This goal is meant to be bound to a lifecycle phase and configured in your pom.xml. The enforcers execute the configured rules to check for certain constraints."
In other words, it checks that certain constraints have been satisfied. It does not cause them to be satisfied.
In your example, the effect of the plugin should be to cause the build to fail if the Java version is not Java 1.8.
... and why it solves the thread "Specify JDK for Maven to use"?
The answer you are referring to says this:
"And it never harms to ... add maven-enforce-plugin to make sure the right jdk is used. This is a good practice for your pom."
As you can see, it does not state that maven-enforce-plugin "solves" the problem. It is actually providing a way to ensure that the problem has been solved ... and fail the build if it hasn't.

Maven native dependences in Eclipse

I'm trying to get some native dependencies (LWJGL) working smoothly in Eclipse (Juno) with Maven.
Current situation:
I'm using the maven-nativedependencies-plugin version 0.0.6. This seems to successfully download and unpack the native libraries to the target/natives subdirectory of my project. Fine so far.
I can make the dependencies work by manually adding the target/natives directory in Properties / Java Build Path / Maven Dependencies / Native Library Location / Edit...
However this only works temporarily as it doesn't seem that the native library location can be specified anywhere in the pom. In particular, it breaks whenever I do a Maven / Update Project... because the Native Library Location is cleared (presumably by m2e re-configuring the project according to the pom)
Whenever the native library location is cleared, I just get the error "java.lang.UnsatisfiedLinkError: no lwjgl in java.library.path"
What is the best way to get this working reliably?
Try this steps;
Go to the run configuration of your java project.
Open the Arguments tab and enter "-Djava.library.path=target/natives"
into the VM Arguments.
For maven project;
Make sure your pom.xml like this;
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>com.googlecode.mavennatives</groupId>
<artifactId>maven-nativedependencies-plugin</artifactId>
<version>0.0.6</version>
<executions>
<execution>
<id>unpacknatives</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<archive>
<manifest>
<mainClass>${main.class}</mainClass>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>bundle-project-sources</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>src/META-INF/assembly.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
And then left click on the eclipse project, go to the maven menu and click on "update project configuration". If you are still having problems, in the eclipse console tab, open the maven console and do the "update project configuration" option again
In my application, I need sqljdbc4.jar from MS. My project is a Maven project, so I had the same problem that I could not edit Native Library Location under sqljdbc4.jar in Eclipse.
My error is this:
Failed to load the sqljdbc_auth.dll cause : no sqljdbc_auth in java.library.path
So I added this:
-Djava.library.path="C:\Documents and Settings\ccrhlj01\My Documents\Microsoft JDBC Driver 4.0 for SQL Server\sqljdbc_4.0\enu\auth\x86"
in my VM arguments.
Go to the run configuration of your java project.
Open the Arguments tab and enter -Djava.library.path="C:\Documents and Settings\ccrhlj01\My Documents\Microsoft JDBC Driver 4.0 for SQL Server\sqljdbc_4.0\enu\auth\x86" into the VM Arguments.
Remember the quotation marks around the path. In my case, that is my location, you need to find your dll location.
Actually, you can copy your dll to any directory on the PATH variable, ex: C:\Windows\System32. This way, you don't have to add the argument in the VM arguments tab in Eclipse.

Categories