Jeg har noget kode, der bruger JAXB API-klasser, som er blevet leveret som en del af JDK i Java 6/7/8. Når jeg kører den samme kode med Java 9, får jeg ved kørselstid fejl, der angiver, at JAXB-klasser ikke kan findes.
JAXB-klasserne har været en del af JDK'et siden Java 6, så hvorfor kan Java 9 ikke længere finde disse klasser?
JAXB API'erne betragtes som Java EE API'er og er derfor ikke længere indeholdt i standardklassestien i Java SE 9. I Java 11 er de helt fjernet fra JDK'et.
Java 9 indfører begreberne moduler, og som standard er aggregatmodulet java.se
tilgængeligt på klassestien (eller rettere modulstien). Som navnet antyder, indeholder java.se
aggregatmodulet ikke de Java EE API'er, som traditionelt er blevet leveret sammen med Java 6/7/8.
Heldigvis findes disse Java EE API'er, som blev leveret i JDK 6/7/8, stadig i JDK'et, men de er bare ikke som standard på klassestien. De ekstra Java EE API'er findes i følgende moduler:
java.activation
java.corba
java.transaction
java.xml.bind << This one contains the JAXB APIs
java.xml.ws
java.xml.ws.annotation
Hurtig og beskidt løsning: (kun JDK 9/10)
For at gøre JAXB API'erne tilgængelige på køretid skal du angive følgende kommandolinjeindstilling:
--add-modules java.xml.bind
Men jeg har stadig brug for, at det virker med Java 8!!!
Hvis du prøver at angive --add-modules
med et ældre JDK, vil det gå galt, fordi det er en ikke-erkendt indstilling. Jeg foreslår en af to muligheder:
JDK_JAVA_OPTIONS
. Denne miljøvariabel bliver [automatisk læst][1] af java
-startprogrammet for Java 9+.-XX:+IgnoreUnrecognizedVMOptions
for at få JVM'en til lydløst at ignorere ikke-genkendte indstillinger i stedet for at sprænge i luften. Men pas på! Alle andre kommandolinjeargs du bruger vil ikke længere blive valideret for dig af JVM'en. Denne indstilling virker med Oracle/OpenJDK såvel som IBM JDK (fra JDK 8sr4)Alternativ hurtig løsning: (kun JDK 9/10)
Bemærk, at du kan gøre alle de ovennævnte Java EE-moduler tilgængelige på køretid ved at angive indstillingen --add-modules java.se.ee
. Modulet java.se.ee
er et samlet modul, der omfatter java.se.ee
samt de ovennævnte Java EE API-moduler. Bemærk, at dette ikke virker på Java 11, fordi java.se.ee
blev fjernet i Java 11.
Den rigtige løsning på lang sigt: (JDK 9 og senere)
Ovennævnte Java EE API-moduler er alle markeret med @Deprecated(forRemoval=true)
, fordi de [er planlagt til fjernelse][2] i [Java 11][3]. Så fremgangsmåden --add-module
vil ikke længere fungere i Java 11 uden videre.
Det, du skal gøre i Java 11 og fremover, er at inkludere din egen kopi af Java EE API'erne i class path eller module path. Du kan f.eks. tilføje JAX-B API'erne som en maven-afhængighed på følgende måde:
<!-- API, java.xml.bind module -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.2</version>
</dependency>
<!-- Runtime, com.sun.xml.bind module -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
</dependency>
Se [JAXB Reference Implementation page] (https://eclipse-ee4j.github.io/jaxb-ri/) for at få flere oplysninger om JAXB.
For fuldstændige oplysninger om Java-modularitet, se [JEP 261: Module System][4]
For Gradle- eller Android Studio-udvikler: (JDK 9 og senere)
Tilføj følgende afhængigheder til din build.gradle-fil:
Tilføj følgende: ````groovy afhængigheder { // JAX-B-afhængigheder for JDK 9+ implementering "jakarta.xml.bind:jakarta.xml.bind-api:2.3.2" implementering "org.glassfish.jaxb:jaxb-runtime:2.3.2" }
[1]: https://www.oracle.com/technetwork/java/javase/9-new-features-3745613.html#JDK-8170832
[2]: http://openjdk.java.net/jeps/320
[3]: http://openjdk.java.net/projects/jdk/11/
[4]: http://openjdk.java.net/jeps/261
[5]: https://stackoverflow.com/a/46455026/3763032
Dette virkede for mig:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.7.0</version>
</dependency>
Som @Jasper foreslog, kan du for at undgå at være afhængig af hele EclipseLink-biblioteket også bare være afhængig af EclipseLink MOXy:
Maven
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.7.3</version>
</dependency>
Gradle
compile group: 'org.eclipse.persistence', name: 'org.eclipse.persistence.moxy', version: '2.7.3'
Som afhængigheder for min Java 8-app, som producerer en *.jar, der kan køres af både JRE 8 og JRE 9 uden yderligere argumenter.
Desuden skal dette udføres et eller andet sted, før JAXB API vil blive brugt:
System.setProperty("javax.xml.bind.JAXBContextFactory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
Virker fint indtil videre, som en workaround. Ser dog ikke ud til at være en perfekt løsning...
På kompileringstidspunktet og på kørselstidspunktet skal du tilføje kontakten ``--add-modules java.xml.bind```
javac --add-modules java.xml.bind <java file name>
java --add-modules java.xml.bind <class file>
En god introduktion til JDK 9
-modulerne kan også findes på :