Έχω κάποιο κώδικα που χρησιμοποιεί κλάσεις API JAXB οι οποίες παρέχονται ως μέρος του JDK στη Java 6/7/8. Όταν τρέχω τον ίδιο κώδικα με την Java 9, κατά την εκτέλεση λαμβάνω σφάλματα που υποδεικνύουν ότι δεν μπορούν να βρεθούν κλάσεις JAXB.
Οι κλάσεις JAXB παρέχονται ως μέρος του JDK από τη Java 6, οπότε γιατί η Java 9 δεν μπορεί πλέον να βρει αυτές τις κλάσεις;
Τα APIs JAXB θεωρούνται ως APIs της Java EE και, επομένως, δεν περιέχονται πλέον στην προεπιλεγμένη διαδρομή κλάσεων στη Java SE 9. Στη Java 11 αφαιρούνται εντελώς από το JDK.
Η Java 9 εισάγει τις έννοιες των modules, και από προεπιλογή το aggregate module java.se
είναι διαθέσιμο στο class path (ή μάλλον, module path). Όπως υποδηλώνει το όνομα, το aggregate module java.se
δεν περιλαμβάνει τα Java EE APIs που παραδοσιακά συνοδεύουν τη Java 6/7/8.
Ευτυχώς, αυτά τα Java EE APIs που παρέχονταν στο JDK 6/7/8 εξακολουθούν να υπάρχουν στο JDK, αλλά απλά δεν βρίσκονται στο μονοπάτι κλάσεων από προεπιλογή. Τα επιπλέον APIs της Java EE παρέχονται στις ακόλουθες ενότητες:
java.activation
java.corba
java.transaction
java.xml.bind << This one contains the JAXB APIs
java.xml.ws
java.xml.ws.annotation
Γρήγορη και βρώμικη λύση: (μόνο JDK 9/10)<br>,
Για να καταστήσετε τα APIs JAXB διαθέσιμα κατά την εκτέλεση, καθορίστε την ακόλουθη επιλογή γραμμής εντολών:<br>,
----add-modules java.xml.bind
Αλλά εξακολουθώ να το χρειάζομαι αυτό για να λειτουργήσει με τη Java 8!!!<br>,
Εάν προσπαθήσετε να προσδιορίσετε την --add-modules
με ένα παλαιότερο JDK, θα ανατιναχτεί επειδή πρόκειται για μια μη αναγνωρισμένη επιλογή. Προτείνω μία από τις δύο επιλογές:
JDK_JAVA_OPTIONS
. Αυτή η μεταβλητή περιβάλλοντος διαβάζεται αυτόματα από τον εκκινητή java
για την Java 9+.-XX:+IgnoreUnrecognizedVMOptions
για να κάνετε την JVM να αγνοεί σιωπηλά τις μη αναγνωρισμένες επιλογές, αντί να ανατινάζεται. Αλλά προσέξτε! Οποιαδήποτε άλλα args της γραμμής εντολών χρησιμοποιείτε δεν θα επικυρώνονται πλέον για εσάς από την JVM. Αυτή η επιλογή λειτουργεί με το Oracle/OpenJDK καθώς και με το IBM JDK (από το JDK 8sr4)Εναλλακτική γρήγορη λύση: (μόνο JDK 9/10)<br>,
Σημειώστε ότι μπορείτε να καταστήσετε διαθέσιμες όλες τις παραπάνω ενότητες Java EE κατά την εκτέλεση, καθορίζοντας την επιλογή --add-modules java.se.ee
. Η ενότητα java.se.ee
είναι μια συγκεντρωτική ενότητα που περιλαμβάνει την ενότητα java.se.ee
καθώς και τις παραπάνω ενότητες API Java EE. Σημειώστε, αυτό δεν λειτουργεί στη Java 11 επειδή η java.se.ee
αφαιρέθηκε στη Java 11.
Σωστή μακροπρόθεσμη λύση: (JDK 9 και μετά)<br>,
Οι ενότητες API της Java EE που παρατίθενται παραπάνω έχουν όλες την ένδειξη @Deprecated(forRemoval=true)
, επειδή είναι προγραμματισμένες για κατάργηση στη Java 11. Έτσι, η προσέγγιση --add-module
δεν θα λειτουργεί πλέον στη Java 11 out of the box.
Αυτό που θα πρέπει να κάνετε στη Java 11 και μετά είναι να συμπεριλάβετε το δικό σας αντίγραφο των Java EE APIs στη διαδρομή κλάσεων ή στη διαδρομή μονάδων. Για παράδειγμα, μπορείτε να προσθέσετε τα JAX-B APIs ως εξάρτηση του maven ως εξής:
<!-- 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>
Ανατρέξτε στη σελίδα JAXB Reference Implementation page για περισσότερες λεπτομέρειες σχετικά με το JAXB.
Για πλήρεις λεπτομέρειες σχετικά με την αρθρωτότητα της Java, δείτε JEP 261: Module System
Για τον προγραμματιστή του Gradle ή του Android Studio: (JDK 9 και μετά)
Προσθέστε τις ακόλουθες εξαρτήσεις στο αρχείο build.gradle:
dependencies {
// Εξαρτήσεις JAX-B για JDK 9+
implementation "jakarta.xml.bind:jakarta.xml.bind-api:2.3.2",
υλοποίηση "org.glassfish.jaxb:jaxb-runtime:2.3.2",
}
Αυτό λειτούργησε για μένα:
<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>
Όπως πρότεινε ο @Jasper, για να αποφύγετε την εξάρτηση από ολόκληρη τη βιβλιοθήκη EclipseLink, μπορείτε επίσης να εξαρτάστε μόνο από το EclipseLink MOXy:
Maven
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.7.3</version>
</dependency>
Γκραντλ
compile group: 'org.eclipse.persistence', name: 'org.eclipse.persistence.moxy', version: '2.7.3'
Ως εξαρτήσεις για την εφαρμογή μου Java 8, η οποία παράγει ένα *.jar που μπορεί να εκτελεστεί τόσο από την JRE 8 όσο και από την JRE 9 χωρίς πρόσθετα ορίσματα.
Επιπλέον, αυτό πρέπει να εκτελεστεί κάπου πριν χρησιμοποιηθεί το JAXB API:
System.setProperty("javax.xml.bind.JAXBContextFactory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
Λειτουργεί εξαιρετικά μέχρι στιγμής, ως λύση. Δεν μοιάζει όμως με τέλεια λύση...
Κατά τη στιγμή της μεταγλώττισης καθώς και κατά την εκτέλεση, προσθέστε το διακόπτη --add-modules java.xml.bind
javac --add-modules java.xml.bind <java file name>
java --add-modules java.xml.bind <class file>
Μια καλή εισαγωγή των ενοτήτων του JDK 9
μπορείτε επίσης να βρείτε στο :