Adding module export to mvn test execution runtime - java

Getting this error during tests:
class javax.crypto.JceSecurity (in unnamed module #0x45da40ad) cannot access class jdk.internal.util.StaticProperty (in module java.base) because module java.base does not export jdk.internal.util to unnamed module #0x45da40ad
I've tried creating jvm.config at the root, next to pom.xml as such
--add-modules ALL-SYSTEM
--add-opens java.base/jdk.internal.util=ALL-UNNAMED
--illegal-access=permit
That doesn't change anything.
So i try to configure maven compiler plugin as such:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<fork>true</fork>
<compilerArgs>
<arg>--add-modules</arg>
<arg>ALL-SYSTEM</arg>
<arg>--add-opens</arg>
<arg>java.base/jdk.internal.util=ALL-UNNAMED</arg>
</compilerArgs>
<argLine>
--add-modules ALL-SYSTEM
--add-opens java.base/jdk.internal.util=ALL-UNNAMED
--illegal-access=permit
</argLine>
<source>${java.compiler.source}</source>
<target>${java.compiler.target}</target>
</configuration>
</plugin>
for the record i even tried it so:
<argLine>
--add-modules ALL-SYSTEM
--add-opens java.base/jdk.internal.util=ALL-UNNAMED
--illegal-access=permit
</argLine>
Nothing. Then i tried surefire plugin like so :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<forkCount>0</forkCount>
<argLine>
--add-modules ALL-SYSTEM
--add-opens java.base/jdk.internal.util=ALL-UNNAMED
--illegal-access=permit
</argLine>
<systemPropertyVariables>
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
</plugin>
Two days working on this and failing miserably. Please help. Using OpenJdk11

I cross checked with surefire 3.0.0-M3 and -M5 and it should be absolutely sufficient to configure surefire with add-opens Oracle's Migration Guide
Also your format is absolutely correct: --add-opens <module>/<package>=ALL-UNNAMED. In Combination with --illegal-access=permit it should work fine.
I see only one more option: remove =ALL-UNNAMED from your opens-argument, this will crash the VM/ Surefire and proves your settings are active.
Beyond that your test classes ought to be invoked through reflection by your favorite runner (test method package private/ without public-modifier). This requires the same opens-declaration for your test classes/ cause the same issues – unless the Maven project isn't a module itself.
Maybe clarify this in your question.

Many tutorials and guides publish the following workaround
<forkCount>0</forkCount>
Please do not use it!
The surefire subprocess is A MUST especially in JPMS.
Please do not apply the workaround with forkCount=0 and rather report a bug in the Apache JIRA and communicate with the open source developers.

Thank to the other answers, it helped me to dig deeper. I managed to solve it with the following changes in pom
<properties>
<!-- Must be in pom's properties section. <sonar.jacoco.reportPaths>target/coverage.exec</sonar.jacoco.reportPaths> -->
<jacoco.version>0.7.7.201606060606</jacoco.version>
<!-- Used by surefire plugin run tests with openjdk11 -->
<argLine>--add-modules java.base --add-opens java.base/jdk.internal.util=ALL-UNNAMED --illegal-access=permit</argLine>
</properties>
.........
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.compiler.source}</source>
<target>${java.compiler.target}</target>
</configuration>
</plugin>
........
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<systemPropertyVariables>
<jacoco-agent.destfile>target/jacoco.exec</jacoco-agent.destfile>
</systemPropertyVariables>
</configuration>
</plugin>
Basically i had to put the argline in properties. Compiler doesn't seem to need it because it's not picking it up from there. But surefire does, it's reading the argline from maven's properties.

Related

Properly pass JDK argument into Maven pom file

Because I need to customize Host header in HTTP request, I need to start my Spring Boot Java app with following argument (available since JDK 12):
java -jar -Djdk.httpclient.allowRestrictedHeaders=host application.jar
but how to pass it into maven pom.xml file to be able to use this argument durring tests which are failing because of missing this flag?
I tried to use maven-compiler-plugin in following way:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<compilerArgs>
<arg>-Djdk.httpclient.allowRestrictedHeaders=host</arg>
</compilerArgs>
</configuration>
</plugin>
but it's wrong:
error: invalid flag: -Djdk.httpclient.allowRestrictedHeaders=host
Following examples are not working either:
-jdk.httpclient.allowRestrictedHeaders=host
jdk.httpclient.allowRestrictedHeaders=host
So i tried even with spring-boot-maven-plugin
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<jvmArguments>-Djdk.httpclient.allowRestrictedHeaders=host</jvmArguments>
</configuration>
</plugin>
but it's also not working because in that case this flag is ignored and I got restriction error when I run mvn test. Which is not happening when I run java with this flag.
You seem to be configuring the wrong plugin. You said you need to "be able to use this argument during tests" which means you should be configuring Maven Surefire Plugin.
Have a look at the example they have provided. May be you can use systemProperties:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<systemProperties>
<property>
<name>propertyName</name>
<value>propertyValue</value>
</property>
[...]
</systemProperties>
</configuration>
</plugin>
or the argLine approach:
<argLine>-Djava.endorsed.dirs=...</argLine>

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>

Unable to pass java compiler parameters using maven

As the title says I am unable to pass command line parameters to the java compiler using maven, I am using the maven-compiler-plugin to do it, and accordingly to this (specifically for the compilerArgs option of the pluging) I am using the "latest way" to speficy the arguments passed to the compiler. Well enough talk, more code, this is my maven configuration for the plug-in and I am not sure what am I doing wrong:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<fork>true</fork>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
I am following the instructions for the usage of the tool which says that <fork> have to be set to true, and I do not know what am I missing... a little bit of help please?
May or may not be helpful to mention that: I need the parameters argument as specified here because I want to get the name of the arguments in my methods in runtime using reflection; I use the -X argument when calling maven to see the debug and I shows me the "fork" call that it does and I cannot se ANYWHERE the arguments I am passing (maybe I need to enable the plug-in; but I think In this case is automatically enabled since it is not part of any profile, I am not a maven expert so please correct me if I am wrong).
EDIT: I have tried in several ways with and without the dash I have even tried the "old way" to do it:
<compilerArguments>
<parameters />
</compilerArguments>
And:
<compilerArgument>-parameters</compilerArgument>
My mistake: I created the code before modifying my pom file, and ran it using maven to check that is was actually working. After that, I modified my pom to include the -parameters flag. The code had already been compiled without that flag and was not modified after. Therefore, maven saw no changes in the code and did not recompile the file.
SOLUTION execute a mvn clean, delete the compiled classes, delete the target folder, or whatever is necessary to ensure that the files are recompiled.
Please mention, that you always have to write a '-' letter before
the parameters.
Below you can see a configuration for your plugin with some sample
compiler arguments.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<fork>true</fork>
<compilerArgs>
<arg>-verbose</arg>
<arg>-Xlint:all,-options,-path</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
From the maven compile plugin main page:
The Compiler Plugin is used to compile the sources of your project. Since 3.0, the default compiler is javax.tools.JavaCompiler (if you are using java 1.6) and is used to compile Java sources. If you want to force the plugin using javac, you must configure the plugin option forceJavacCompilerUse.
I'm guessing the javax.tools.JavaCompiler doesn't works the same way javac does with the -parameters option.
Try forcing the javac use
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
<fork>true</fork>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>

"The command line is too long" -- when running maven test

Running $mvn test on a 64-bit Windows gives me the following error, even if I do $mvn test -Dgwt.genParam=false:
The command line is too long
Make sure you are using version 2.16 and that you have the useManifestOnlyJar option (as documented here).
For example:
<project>
[...]
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.16</version>
<configuration>
<useManifestOnlyJar>true</useManifestOnlyJar>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
[...]
</project>
This will create jar with a manifest that re-creates your classpath (as opposed to setting it via the CLASSPATH variable which is an approach that is affected by Windows' command-line limit problem).

IntelliJ Maven integration

I imported a Maven project into IntelliJ, but it seems like it's ignoring the <configuration> specified for the surefire plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<argLine>-Djava.endorsed.dirs=${settings.localRepository}/com/sun/metro/webservices-api/2.0.1
</argLine>
<excludes>
<exclude>**/CacheStoreTest.java</exclude>
</excludes>
</configuration>
</plugin>
When I run the tests from within the IDE, it picks up the webservices-api.jar bundled with JDK6 instead of the version from my Maven repository and it also runs the tests in CacheStoreTest even though I've indicated they should be excluded.
It's a known issue, please watch/vote.

Categories