J'ai un code qui utilise les classes de l'API JAXB qui ont été fournies en tant que partie du JDK dans Java 6/7/8. Lorsque j'exécute le même code avec Java 9, j'obtiens, au moment de l'exécution, des erreurs indiquant que les classes JAXB sont introuvables.
Les classes JAXB font partie intégrante du JDK depuis Java 6, alors pourquoi Java 9 ne trouve-t-il plus ces classes ?
Les API JAXB sont considérées comme des API Java EE et ne figurent donc plus dans le chemin des classes par défaut dans Java SE 9. Dans Java 11, elles sont complètement supprimées du JDK.
Java 9 introduit les concepts de modules, et par défaut le module d'agrégation java.se
est disponible sur le chemin des classes (ou plutôt, le chemin des modules). Comme son nom l'indique, le module agrégé java.se
n'inclut pas les APIs Java EE qui ont été traditionnellement fournies avec Java 6/7/8.
Heureusement, ces API Java EE qui étaient fournies dans le JDK 6/7/8 sont toujours dans le JDK, mais elles ne sont simplement pas dans le chemin des classes par défaut. Les API Java EE supplémentaires sont fournies dans les modules suivants :
java.activation
java.corba
java.transaction
java.xml.bind << This one contains the JAXB APIs
java.xml.ws
java.xml.ws.annotation
Solution simple et rapide : (JDK 9/10 uniquement)
Pour rendre les API JAXB disponibles au moment de l'exécution, spécifiez l'option de ligne de commande suivante :
--add-modules java.xml.bind
Mais j'ai encore besoin de cela pour fonctionner avec Java 8 ! !!
Si vous essayez de spécifier --add-modules
avec un ancien JDK, il va exploser parce que c’est une option non reconnue. Je suggère l'une des deux options suivantes :
JDK_JAVA_OPTIONS
. Cette variable d'environnement est [automatiquement lue][1] par le lanceur java
pour Java 9+.-XX:+IgnoreUnrecognizedVMOptions
pour que la JVM ignore silencieusement les options non reconnues, au lieu d'exploser. Mais attention ! Tout autre argument de ligne de commande que vous utilisez ne sera plus validé pour vous par la JVM. Cette option fonctionne aussi bien avec Oracle/OpenJDK qu'avec IBM JDK (à partir de JDK 8sr4).Autre solution rapide : (JDK 9/10 uniquement)
Notez que vous pouvez rendre tous les modules Java EE ci-dessus disponibles au moment de l'exécution en spécifiant l'option --add-modules java.se.ee
. Le module java.se.ee
est un module agrégé qui inclut java.se.ee
ainsi que les modules API Java EE ci-dessus. Notez que cela ne fonctionne pas sur Java 11** car java.se.ee
a été supprimé dans Java 11.
Solution appropriée à long terme : (JDK 9 et au-delà)
Les modules de l'API Java EE énumérés ci-dessus sont tous marqués @Deprecated(forRemoval=true)
, car leur suppression est [prévue][2] dans [Java 11][3]. Ainsi, l'approche --add-module
ne fonctionnera plus dans Java 11 dès le départ.
Ce que vous devrez faire à partir de Java 11, c'est inclure votre propre copie des API Java EE dans le chemin des classes ou des modules. Par exemple, vous pouvez ajouter les API JAX-B en tant que dépendance maven comme ceci :
<!-- 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>
Consultez la [page d'implémentation de référence JAXB] (https://eclipse-ee4j.github.io/jaxb-ri/) pour plus de détails sur JAXB.
Pour plus de détails sur la modularité de Java, voir [JEP 261 : Module System][4].
Pour les développeurs Gradle ou Android Studio : (JDK 9 et au-delà)
Ajoutez les dépendances suivantes à votre fichier build.gradle :
``groovy dépendances { // Dépendances JAX-B pour le JDK 9+. implementation "jakarta.xml.bind:jakarta.xml.bind-api:2.3.2" ; implémentation "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
Cela a marché pour moi :
<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>
Comme @Jasper l'a suggéré, afin d'éviter de dépendre de l'ensemble de la bibliothèque EclipseLink, vous pouvez également dépendre uniquement d'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'
Comme dépendances pour mon application Java 8, qui produit un *.jar qui peut être exécuté par JRE 8 ou JRE 9 sans arguments supplémentaires.
En outre, il doit être exécuté quelque part avant que l'API JAXB ne soit utilisée :
System.setProperty("javax.xml.bind.JAXBContextFactory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
Cela fonctionne très bien jusqu'à présent, comme solution de rechange. Mais cela ne semble pas être une solution parfaite...
Au moment de la compilation comme au moment de l'exécution, ajoutez le commutateur --add-modules java.xml.bind
.
javac --add-modules java.xml.bind <java file name>
java --add-modules java.xml.bind <class file>
Une bonne introduction des modules du JDK 9
peut également être trouvée à :