I've got a class that uses jdk.internal.misc.Signal.
In module-info.java there is requires jdk.unsupported.
If I try to compile this I get:
[ERROR] MyClass.java:[28,20] package jdk.internal.misc is not visible
[ERROR] (package jdk.internal.misc is declared in module java.base, which does not export it to module MyModule)
Then if I add <arg>--add-exports</arg><arg>java.base/jdk.internal.misc=MyModule</arg>
to maven-compiler-plugin:3.8.1 I get:
[ERROR] exporting a package from system module java.base is not allowed with --release
Then if I remove <release>11</release> I get:
Fatal error compiling: warning: source release 11 requires target release 11
I've the feeling that I'm missing something important or maybe it is just a bug?
I'm using maven 3.6.3 and openjdk 11.0.2.
jdk.internal.misc.Signal is in java.base module. If you take a look inside its module-info.java file you will notice this:
exports jdk.internal.misc to
(...)
jdk.unsupported;
However jdk.unsupported contains sun.misc.Signal which is the original pre-Java 9 class for handling signals.
In general usage of classes in .internal. packages is a bad practice because they are not part of public API.
Instead I would suggest to use sun.misc.Signal with requires jdk.unsupported module clause until there is a #Deprecated annotation with information which API should be used instead.
BTW. This is a great example how JPMS helps with hiding internal implementation details of a library (in this case JDK) from un/intended usage.
fixed by changing <release>11</release> into <target>11</target> in my pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
Related
While moving a project to Gradle, I stopped using my custom build of org.json which had a module-info.java fitted to it to comply to the module system. Now, I am using it via Maven normally, and as org.json is not a module by default, it gets put into the unnamed module.
My module-info looks like this:
open module mymodule {
requires java.desktop;
requires java.logging;
}
I am getting the error:
SomeSourceFile.java: error: package org.json is not visible
import org.json.*;
^
(package org.json is declared in the unnamed module, but module mymodule does not read it)
This is logical, except I don't know why my module doesn't read the unnamed module (the purpose of the unnamed module is full backwards compatibility with non-modular software so all packages are exported etc.), and how I could make my module read the unnamed module. As you can see, I have already tried making my module open to no avail.
Probably updating the Maven Compiler Plugin (to 3.8.1, for instance) will do the trick.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
The other thing will be to require the JSON module. From their pom.xml, I can see that they declare the Automatic-Module-Name as org.json (https://github.com/stleary/JSON-java/blob/master/pom.xml#L186)
So your module-info.java will become like this:
open module mymodule {
requires java.desktop;
requires java.logging;
requires org.json;
}
I am trying to create a modular Spring Boot sample using JMPS which introduced in Java 9.
Currently, I created a standalone Maven module for the testing work.
module greeting.webapp.test {
requires greeting.webapp;
requires spring.test;
requires spring.boot;
requires spring.web;
requires spring.boot.starter.webflux;
requires spring.boot.starter.test;
requires spring.boot.test;
requires spring.boot.test.autoconfigure;
requires org.junit.jupiter;
requires org.junit.jupiter.api;
requires org.junit.jupiter.params;
requires org.junit.jupiter.engine;
requires org.junit.platform.commons;
requires org.assertj.core;
requires mockito.junit.jupiter;
}
And when run the sample test, I got the following errors.
Exception in thread "main" java.lang.IllegalAccessError: class org.junit.platform.launcher.TestIdentifier (in unnamed module #0x6325a3ee) cannot access class org.junit.platform.commons.util.Preconditions (in module org.junit.platform.commons) because module org.junit.platform.commons does not export org.junit.platform.commons.util to unnamed module #0x6325a3ee
at org.junit.platform.launcher.TestIdentifier.from(TestIdentifier.java:56)
at com.intellij.junit5.JUnit5IdeaTestRunner.<clinit>(JUnit5IdeaTestRunner.java:86)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:377)
at com.intellij.rt.junit.JUnitStarter.getAgentClass(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:210)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
And in the test module, I have to move the test scoped deps to compile time to make it work in jmps, how to resolve this issue?
There is no easy way, or no good way at all, imho.
The problem you are having is that you have not configured maven surefire correctly. You can try that - I did and somehow was unlucky, but I did not invest too much time in making it work (neither do I think that will work, but that is a different problem). Instead I configured surefire plugin manually, via:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>
--add-exports org.junit.platform.commons/org.junit.platform.commons.util=ALL-UNNAMED
--add-exports org.junit.platform.commons/org.junit.platform.commons.logging=ALL-UNNAMED
</argLine>
</configuration>
</plugin>
Overall, I like gradle approach more. You can read on my experience with it here. I also don't think that IDEs (Intellij in my case) have yet proper support to run a single (maven based project) test, unlike gradle. But, to be fair, I only tried that against your repo, so far...
You can also read about a rather neat approach that gradle has taken when you need to declare modules here, with their dedicated plugin.
After switching to Java 11, all the powermock related tests (annotated with #RunWith(PowermockRunner.class) and #PowerMockIgnore) are failing.
Is this known issue? I read a relevant SO post which was posted a year ago, and the latest release of Powermock was 2 months ago. I don't see any difference in behaviour with JDK 11.
For better clarity, it would be great if you could specify the powermock API version, what i can think of the probable clause of the exception would be PowerMock classloader reloads XML11Configuration but without specifying module/or ignore module of the class. As result the unnamed module is autogenerated.
I can suggest another workaround. If it works then my guess is correct. Could you try to
use this option #PowerMockIgnore({"com.sun.org.apache.xerces.", "javax.xml.parsers.",, "javax.xml.", "org.xml."})
It should work.
The existing "mvn hpi:run" command will not work correctly on Java
11 unless Java modules are downloaded and passed to the environment.
List item If you use Mockito/PowerMock in your plugin tests, you may need to update to the recent versions with Java 11 support-
You may also need to add test annotations to workaround PowerMock
Issue #864. Example for the Jenkins Core
Adding byte buddy dependency helped me to run PowerMock tests in java 14.
As mentioned above PowerMock reflection access internal packages java.xml/jdk.xml, a workaround consist in allowing access to those internal packages :
if you are using maven to build your project you should add the JVM argument :
--add-opens java.xml/jdk.xml.internal=ALL-UNNAMED
for example :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>--add-opens java.xml/jdk.xml.internal=ALL-UNNAMED</argLine>
</configuration>
</plugin>
If use reflect in JDK11, you might see some warning like 'An illegal reflective access operation has occurred', because reflect JDK inner API is illegal since JDK9, still you can use it with a warning above.
To fix the problem temporary, try to use --add-exports or --add-opens in your argLing.
For example: --add-opens java.xml/jdk.xml.internal=ALL-UNNAMED
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M5</version>
<configuration>
<argLine>
#{argLine} --add-opens java.xml/jdk.xml.internal=ALL-UNNAMED
</argLine>
</configuration>
</plugin>
For more infomation, watch --add-opens introduce
My project depends on Netty Epoll transport. Here is dependency:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>${netty.version}</version>
<classifier>${epoll.os}</classifier>
</dependency>
The auto-generated module name for this dependency is:
netty.transport.native.epoll
And as the native keyword is reserved in Java 9 I can't add this module as a dependency to my project:
module core {
requires netty.transport.native.epoll;
}
Due to:
module not found: netty.transport.<error>
Additionally the jar tool --describe-module reports the following:
Unable to derive module descriptor for:
netty-transport-native-epoll-4.1.17.Final-SNAPSHOT-linux-x86_64.jar
netty.transport.native.epoll: Invalid module name: 'native' is not a
Java identifier
Are there any workarounds? (except "release correct netty artifact", of course).
EDIT:
As the quick fix for maintainers - you can add next line to build:
<manifestEntries>
<Automatic-Module-Name>netty.transport.epoll</Automatic-Module-Name>
</manifestEntries>
The solution to this seems to be:-
A way possible to uninterruptedly using the same artifact name with a new(different) module name could be by packaging META-INF/MANIFEST.MF of the artifact with an attribute Automatic-Module-Name which governs the name of the module to be used by the module descriptor when converted as an automatic module.
OR
Artifact owners can add module declarations using module-info.java to their JAR. (this could result in a slow bottom-up migration)
Since the module declaration defined in the specs as:
A module declaration introduces a module name that can be used in
other module declarations to express relationships between modules. A
module name consists of one or more Java identifiers (§3.8) separated
by "." tokens.
Intersetingly the declarations suggests -
In some cases, the Internet domain name may not be a valid package
name. Here are some suggested conventions for dealing with these
situations:
If the domain name contains a hyphen, or any other special character
not allowed in an identifier (§3.8), convert it into an underscore.
If any of the resulting package name components are keywords (§3.9),
append an underscore to them.
If any of the resulting package name components start with a digit, or
any other character that is not allowed as an initial character of an
identifier, have an underscore prefixed to the component.
But keep in mind as you do so that Underscore is a keyword in Java9
int _; // is would throw an error on javac based out of JDK9
int _native; // works fine
From now on you can also use this small Maven plugin to automatically modify the manifest file in a Scala jar in your local Maven repo: https://github.com/makingthematrix/scala-suffix
Under the link you will find the overview of the whole issue and what you need to add to you pom.xml, but I was asked to also explain here, so here it goes:
As it was mentioned already, Java does not recognize suffixes in modules names like _2.13 as version numbers and treat them as integral parts of modules names. So, when your project tries to use a class from the Scala dependency, it will look for your.scala.dependency.2.13 instead of just your.scala.dependency, it will fail to do it, and it will crash.
To fix this on your side (i.e. without any action from the library's creator) add this to the <plugins> section of your pom.xml:
<plugin>
<groupId>io.github.makingthematrix</groupId>
<artifactId>scala-suffix-maven-plugin</artifactId>
<version>0.1.0</version>
<configuration>
<libraries>
<param>your-scala-dependency</param>
</libraries>
</configuration>
<executions>
<execution>
<goals>
<goal>suffix</goal>
</goals>
</execution>
</executions>
</plugin>
where your-scala-dependency is a name of your Scala dependency without the version suffix (if there are more than one, just add them with more <param> tags). This should be the same as artifactId in your <dependency> section.
The plugin modifies the dependency's JAR file in your local Maven repository. It opens the jar, reads META-INF/MANIFEST.MF and adds to it a line:
Automatic-Module-Name: your-scala-dependency
If the property Automatic-Module-Name already exists, the plugin does nothing - we assume that in that case the dependency should already work. This prevents the plugin from modifying the same JAR file more than once.
I have a Hibernate 5 project that perfectly builds and runs on Java 8. I tried to test it on JDK 9 ea build 171.
Since it is a huge project and have other dependencies I had to add java.xml.bind module to the JVM configuration for tests:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.20</version>
<configuration>
<argLine>--add-modules java.xml.bind</argLine>
</configuration>
</plugin>
There were other issues that I could resolve but if used aggregated module java.se.ee(as recommended):
<argLine>--add-modules java.se.ee</argLine>
I got an exception :
java.lang.NoClassDefFoundError: javax/transaction/SystemException
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:374)
at org.jboss.logging.Logger$1.run(Logger.java:2554)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at org.jboss.logging.Logger.getMessageLogger(Logger.java:2529)
I couldn't even understand why it happened because JTA library(with SystemException class) is in the class-path when tests were running.
Any suggestions on how to fix this?
Java SE defines a small subset of JTA. It doesn't include javax.transaction.SystemException as that exception is in the Java EE version of JTA, not the Java SE subset.
When you run with --add-modules java.se.ee then it causes the modules shared between Java SE and Java EE to be resolved, this includes the the java.transaction module. Any attempt to load a type in the javax.transaction package will be loaded from the java.transaction module but since this module only has a small subset of JTA then javax.transaction.SystemException will not be found.
If you drop --add-modules java.se.ee from your command line then you'll find that javax.transaction.SystemException can be loaded, as it's on the class path. So if you only need JAXB (module java.xml.bind) then specify that module to --add-modules, not the "java.se.ee" aggregator that will cause all modules shared with Java EE to be resolved.
Though the question seems old, yet unanswered and since the GA release of JDK is completed. According to the migration guide and the java docs, since the module java.transaction which exports the package javax.transaction has been marked as #Deprecated.
You should ideally migrate your code to be using javaee/javax.transaction instead. Currently, you can do so using automatic module converted from the dependency:
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.2</version>
</dependency>
and adding to the module-info.java the following:-
requires javax.transaction.api;
Edit: Thanks to #ImpulseTheFox for verifying that the automatic module name for the jar version 1.3 above requires:-
requires java.transaction;