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;
Related
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.
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>
I've tried to "upgrade" a project using Hibernate to Java 9, but I am having problems getting the module to function properly.
The relevant part of my module-info.java looks like this:
module test {
...
requires java.base;
requires hibernate.core;
requires javax.transaction;
requires java.sql;
}
and the relevant dependencies in my POM are
org.jboss.spec.javax.transaction:jboss-transaction-api_1.2_spec, 2.0.0.Alpha1
org.hibernate:hibernate-core, 5.2.12.Final
javax.transaction:javax.transaction-api, 1.2
The problem is, if I run the program, I get a NoClassDefFoundError for javax.transaction.SystemException. I looked into this, and quite obviously, my module is missing a requires on javax.transaction.
So I add a module dependency on javax.transaction-api. I then go on and attempt to run the program again - now I'm missing java.sql.SQLException.
Here is what I am having a problem with: if I add a dependency on the module java.sql, which contains this class, I end up with a conflict:
module reads package javax.transaction.xa from both java.sql and javax.transaction.api
java.sql and javax.transaction.api contain different packages, and have one in common (javax.transaction.xa), but I require all of them.
How do I deal with this? Is there something simple I am missing?
Use version 1.3 instead of 1.2 of javax.transaction-api, in this version javax.transaction.xa has been removed.
Maven dependency:
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.3</version>
</dependency>
I am compiling my legacy source code using JDK 9.0.1 as follows:
javac --add-modules=java.base,java.xml.ws -cp lib\jsr305.jar;lib\javax.annotation-api-1.2.jar TestJava.java
It gives an error because the annotations defined in jsr305.jar are not visible due to split module issue. The error is as follows:
TestJava.java:3: error: cannot find symbol
import javax.annotation.Nonnull;
^
symbol: class Nonnull
location: package javax.annotation
Here the module java.xml.ws.annotation is getting loaded since it is required for java.xml.ws. So it is ignoring the types in jsr305.jar. I don't want this module to be loaded but refer all its annotation types from javax.annotation-api-1.2.jar. I don't want to do --patch-module either because it would break in future releases.
If I use --limit-module=java.xml.ws.annotation it gives the same error. If I remove java.xml.ws from -add-modules, it compiles successfully but I need to export few APIs from it so can't remove it. Is there any way I can load module java.xml.ws but not java.xml.ws.annotation?
EDIT : I think I have added some confusion by giving an example of split between java.xml.ws.annotaion and jsr305.jar. Though it's my actual problem, I am more interested in knowing - can I avoid loading a transitively dependent module, say loading java.xml.ws without loading java.xml.ws.annotation? As per my understanding in JEP 261 it says,
--limit-modules <module>(,<module>)*
where <module> is a module name. The effect of this option is to limit
the observable modules to those in the transitive closure of the named
modules plus the main module, if any, plus any further modules
specified via the --add-modules option.
So, why isn't --limit-module preventing java.xml.ws.annotation from loading?
I know of no way to prevent resolution of a transitive dependency.
Short-term fix
You should be able to make it work by patching the module with --patch-module java.xml.ws=lib\jsr305.jar:lib\javax.annotation-api-1.2.jar. My opinion: If you just want to get your build working on Java 9, that is a good choice. It's a little dubious but still acceptable if you want to use it in production.
If you're worried about long-term compatibility:
I don't think --patch-module will disappear any time soon - do you have a source for that?
I'm pretty sure java.xml.ws will be removed quite soon - it is already deprecated for removal.
In your place I'd worry about the module more than about patching it.
Long-term solution
So for a long-term solution you should remove your dependency on java.xml.ws. JDK-8189188 has a section on this (with lots of links that I was too lazy to copy):
The Reference Implementations (RIs) of JAX-WS and JAXB are a good starting point because they are complete replacements for the java.xml.ws and java.xml.bind modules in JDK 9. The RIs are available as Maven artifacts: (note that they must be deployed on the classpath)
com.sun.xml.ws : jaxws-ri (JAX-WS, plus SAAJ and Web Services Metadata)
com.sun.xml.bind : jaxb-ri (JAXB)
The tools for JAX-WS and JAXB are also available as Maven artifacts:
wsgen and wsimport: com.sun.xml.ws : jaxws-tools, plus tool scripts
schemagen and xjc: com.sun.xml.bind : jaxb-jxc and com.sun.xml.bind : jaxb-xjc, plus tool scripts
There are also Maven artifacts that contain just the APIs of the Java EE technologies:
javax.xml.ws : jaxws-api (JAX-WS, plus javax.xml.soap : javax.xml.soap-api for SAAJ and javax.xml : webservices-api for Web Services Metadata)
javax.xml.bind : jaxb-api (JAXB)
javax.activation : javax.activation-api (JAF)
javax.annotation : javax.annotation-api (Common Annotations)
Adding either the API JARs or the reference implementations to your class path together with all other javax.annotation-related JARs will work because all class path content ends up in the same module (the unnamed one) and thus split packages are no problem there.
My current project consisting of a war and ejb module, is using a jar (incorperated via maven). This jar contains a CDI component which, when I inject this in the war module it works as expected, but when I inject this in my ejb module I get a NoClassDefFoundError during startup from my WAS 8.5 in eclipse (full profile).
When I start the server first, add the inject later and republish it seems to work. Also when I use Liberty profile it works. Also on Z/os and IPAS it works as expected.
I think it might has something todo with classloading, but have no idea how to solve this properly.
Using Eclipse Neon, WAS 8.5.5.11 full profile , jee6
Project is using java 8 while the component is using java 6
This is the first part of the stacktrace:
[13-9-17 14:54:26:589 CEST] 0000003e InjectionProc W CWNEN0047W: Resource annotations on the fields of the BestelFacade class will be ignored. The annotations could not be obtained because of the exc
eption : Logger
at java.lang.Class.getDeclaredFieldsImpl(Native Method)
Thanks
I found a way to get the job done, but I'm not sure if this is a proper solution or just a workaround while masking the real problem.
When I take a look at the ear module assembly I see in the source column c:/ws/.../jar and in the deploy path lib/jar
when I change the source into /..ear/target/../jar it works
Try setting the <bundleDir>/</bundleDir>
This will place the external jar/ejb not in lib, but in the root.
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
...........
<defaultLibBundleDir>lib</defaultLibBundleDir>
<modules>
<jarModule>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
<bundleDir>/</bundleDir>
</jarModule>
</modules>
</configuration>
</plugin>