Given this project:
https://github.com/michael-simons/bootiful-databases
Using JDK 9-EA
java -version
java version "9"
Java(TM) SE Runtime Environment (build 9+180)
Java HotSpot(TM) 64-Bit Server VM (build 9+180, mixed mode)
And jOOQ 3.9.4 with the corresponding code generator
Start a postgres database from within the project
./mvnw docker:start
Try to generate jOOQ-Metamodel:
./mvnw clean compile
After having the migrations applied, jOOQs code generator runs and fails as follows:
[ERROR] Failed to execute goal org.jooq:jooq-codegen-maven:3.9.4:generate (default) on project bootiful-databases: Execution default of goal org.jooq:jooq-codegen-maven:3.9.4:generate failed: A required class was missing while executing org.jooq:jooq-codegen-maven:3.9.4:generate: javax/xml/bind/JAXB
[ERROR] -----------------------------------------------------
[ERROR] realm = plugin>org.jooq:jooq-codegen-maven:3.9.4
[ERROR] strategy = org.codehaus.plexus.classworlds.strategy.SelfFirstStrategy
[ERROR] urls[0] = file:/Users/msimons/.m2/repository/org/jooq/jooq-codegen-maven/3.9.4/jooq-codegen-maven-3.9.4.jar
[ERROR] urls[1] = file:/Users/msimons/.m2/repository/org/jooq/jooq-codegen/3.9.4/jooq-codegen-3.9.4.jar
[ERROR] urls[2] = file:/Users/msimons/.m2/repository/org/jooq/jooq/3.9.4/jooq-3.9.4.jar
[ERROR] urls[3] = file:/Users/msimons/.m2/repository/org/jooq/jooq-meta/3.9.4/jooq-meta-3.9.4.jar
[ERROR] urls[4] = file:/Users/msimons/.m2/repository/backport-util-concurrent/backport-util-concurrent/3.1/backport-util-concurrent-3.1.jar
[ERROR] urls[5] = file:/Users/msimons/.m2/repository/org/codehaus/plexus/plexus-interpolation/1.11/plexus-interpolation-1.11.jar
[ERROR] urls[6] = file:/Users/msimons/.m2/repository/org/codehaus/plexus/plexus-utils/1.5.15/plexus-utils-1.5.15.jar
[ERROR] urls[7] = file:/Users/msimons/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar
[ERROR] Number of foreign imports: 1
[ERROR] import: Entry[import from realm ClassRealm[maven.api, parent: null]]
[ERROR]
[ERROR] -----------------------------------------------------
[ERROR] : javax.xml.bind.JAXB
Same error occurs on https://github.com/springbootbuch/database_examples and I assume on plain (without the Spring Boot stuff) jOOQ projects as well.
Thanks for your report. I can reproduce this. Will investigate ASAP
This particular issue can be worked around by specifying (example using Windows shell syntax):
set MAVEN_OPTS=%MAVEN_OPTS% --add-modules java.xml.bind
An (outdated) explanation can be seen here:
http://mail.openjdk.java.net/pipermail/jdk9-dev/2016-May/004309.html
Will continue investigating. There are several possible options for a fix:
1) There might be a clean fix where jOOQ imports all the required JDK modules, e.g. by specifying this in a module-info.java. We'd have to see if this can be done also in the JDK 8 build, or if we need a separate JDK 9 build for this.
2) We could intercept the NoClassDefFoundError and print a message with the above workaround
3) Other possible solution...
A similar issue has been encountered when building jetty with JDK 9:
https://github.com/eclipse/jetty.project/issues/1265
The solution there was to include
--add-modules java.se.ee
A word of warning about --add-modules java.se.ee. It can be a bag of hurt if you're using JTA as some, but not all, JTA classes are in that module. That split leads to failures at runtime.
FWIW, we have this general problem in Spring Boot too. We intend to address it by adding Maven dependencies for various things (JAXB, JSR-330, etc) instead of relying on them coming from the JDK.
The blanket --add-modules java.se.ee is not the best thing to do. Better to only add the specific modules you need. All of those are endorsed standards or standalone technologies, so looking for libs that implement them and explicitly depending on them is a good solution, too.
Thanks for the hint, @wilkinsona. jOOQ doesn't have a JTA dependency.
Closing this now, as the workaround is the only reasonable solution prior to creating an actual JDK 9 build (#6486).
Thanks for clarifying the issue.
For future reference: There's another fix, which does not use MAVEN_OPTS and can be maintained local to the project. See this answer on StackOverflow.
This particular issue could also be solved without modularising the library, by specifying an explicit Maven dependency on the JAXB API (see #6610), as @wilkinsona also mentioned in his comment: https://github.com/jOOQ/jOOQ/issues/6477#issuecomment-319496039.
However, this will lead to a new error:
[ERROR] Failed to execute goal org.jooq:jooq-codegen-maven:3.10.0-SNAPSHOT:generate (generate-h2) on project jooq-test: Error running jOOQ code generation tool: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
[ERROR] - with linked exception:
[ERROR] [java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory]
Any ideas about the most reasonable way forward here, @nicolaiparlog / @wilkinsona ?
The fact that you don't see a NoClassDefFoundError for JAXBException means that the JAXB API was found and works properly. Looks like the implementation is missing, but I'm no JAXB user, so I don't know whether that's to be expected and what to do about it.
Yes, the API was found and worked properly, but then again, it won't be the JDK's API, so there might be ClassCastException between JAXB and JAXB from different modules, if users add the JAXB module to their module path. What a mess :-/
I guess the only proper solution would be to cross release a jOOQ JDK 8 and jOOQ JDK 9+ version.
While modularising a far simpler library (jOOX: https://github.com/jOOQ/jOOX/issues/153), I'm closing in on a solution here:
javax.xml.bind:jaxb-api dependency only. It's sufficient to add this dependency to the pom.xml, and the result will work for both Java 8 and 9As far as I can tell, the above could even be implemented in a patch release, without breaking things. In jOOQ 3.11 (probably), we'll modularise jOOQ and stuff will work more naturally in jOOQ.
I've created an issue for this: #6879
Most helpful comment
Workaround
This particular issue can be worked around by specifying (example using Windows shell syntax):
An (outdated) explanation can be seen here:
http://mail.openjdk.java.net/pipermail/jdk9-dev/2016-May/004309.html
Possible fix
Will continue investigating. There are several possible options for a fix:
1) There might be a clean fix where jOOQ imports all the required JDK modules, e.g. by specifying this in a
module-info.java. We'd have to see if this can be done also in the JDK 8 build, or if we need a separate JDK 9 build for this.2) We could intercept the
NoClassDefFoundErrorand print a message with the above workaround3) Other possible solution...