Fachlicher Vertrag: unverändert zu erhalten
- Namespace, Elementnamen, Reihenfolge und optionale Felder bleiben schema-kompatibel.
- Zeichensatz und Datums-/Zahlenformate ändern sich nicht unbemerkt.
- Externe Entitäten werden nicht aufgelöst.
javax.xml.bind wird nachvollziehbar in jakarta.xml.bind überführt. Die Akte zeigt nicht nur das Ziel, sondern die tatsächlichen Dateien, APIs, Dependencies, Codebelege, Tests, Risiken und Cutover-Schritte.
| Dimension | Legacy | Modern | Migrationskonsequenz |
|---|---|---|---|
| Programmiermodell | XmlElement, XmlRootElement, example | XmlElement, XmlRootElement, example | Annotationen und Containerfunktionen werden nur dort eingesetzt, wo sie eine konkrete technische Verantwortung übernehmen. |
| Abhängigkeiten | 3 direkte Dependencies | 3 direkte Dependencies | 1 neu, 1 entfernt; Versionen und transitive Auswirkungen im erfolgreichen Online-Build prüfen. |
| Öffentliche API | 6 erkannte Methoden | 6 erkannte Methoden | Methoden werden nach fachlicher Rolle gemappt; reine Bootstrap- und Framework-Methoden sind kein fachlicher Vertrag. |
| Datenmodell | class LegacyCustomer, class LegacyXmlMapper, class XmlLegacyApplication | class ModernCustomer, class ModernXmlMapper, class XmlModernApplication | Feldnamen, IDs, Null-Semantik, Gleichheit und Serialisierungsform werden separat regressionstestet. |
| Fehlerverhalten | Legacy-Exceptions und Rückgabewerte | explizitere Fach-/Framework-Fehlerabbildung | Fehler dürfen nicht nur technisch übersetzt werden; Status, Ursache, Retrybarkeit und Client-Vertrag müssen erhalten oder versioniert werden. |
| Tests | Bestands- und Golden-Master-Tests | Unit-, Slice-, Contract- und Integrationstests | Der Modern-Pfad wird zuerst gegen denselben fachlichen Vektor geprüft und danach um neue technische Risiken ergänzt. |
| Betrieb | Legacy-Start/Lifecycle | modernes Packaging, Health und externe Konfiguration | Golden-Master-Dokumente und negative XXE-/Malformed-Tests sind obligatorisch. |
| Rollback | Legacy-Artefakt bleibt unverändert | Modern-Artefakt getrennt deploybar | Kein Rollback über Datenverlust: Schema, Nachrichten und verschlüsselte Daten müssen rückwärtslesbar oder durch Dual-Read abgesichert sein. |
namespace and schema compatibility
round-trip, invalid XML, encoding and XXE-negative tests
Die Zuordnung ist semantisch: Eine Legacy-Klasse kann in mehrere moderne Rollen zerlegt werden.
| Legacy-Rolle / Datei | Modern-Rolle / Datei | Bedeutung |
|---|---|---|
| LegacyCustomer.java | ModernCustomer.java | javax JAXB Model wird Jakarta JAXB Model. |
| LegacyXmlMapper.java | ModernXmlMapper.java | Marshaller/Unmarshaller-Verantwortung bleibt erhalten. |
| XmlLegacyApplication.java | XmlModernApplication.java | Bootstrap wird auf Jakarta Runtime umgestellt. |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| LegacyCustomer.java | class LegacyCustomer | XmlElement, XmlRootElement | String getName() void setName(String name) String getEmail() void setEmail(String email) | — | 35 |
| LegacyXmlMapper.java | class LegacyXmlMapper | — | String toXml(LegacyCustomer customer) | Mapper | 18 |
| XmlLegacyApplication.java | class XmlLegacyApplication | example | void main(String[] args) | — | 10 |
| Datei | Typ | Annotationen | öffentliche API | Pattern | Zeilen |
|---|---|---|---|---|---|
| ModernCustomer.java | class ModernCustomer | XmlElement, XmlRootElement | String getName() void setName(String name) String getEmail() void setEmail(String email) | — | 35 |
| ModernXmlMapper.java | class ModernXmlMapper | — | String toXml(ModernCustomer customer) | Mapper | 18 |
| XmlModernApplication.java | class XmlModernApplication | example | void main(String[] args) | — | 10 |
| Status | Dependency | Version | Scope | Prüfung |
|---|---|---|---|---|
| ENTFERNT | javax.xml.bind:jaxb-api | 2.3.1 | compile | Legacy-Laufzeit entfällt oder wird durch Plattform/BOM ersetzt. |
| NEU | jakarta.xml.bind:jakarta.xml.bind-api | 4.0.2 | compile | Neue Laufzeit-/Testabhängigkeit; transitiv, lizenz- und security-seitig prüfen. |
| GEÄNDERT | org.glassfish.jaxb:jaxb-runtime | ${jaxb.legacy.version} → ${jaxb.modern.version} | compile → compile | Gemeinsame Dependency; Version und Scope im effektiven POM prüfen. |
| BEIBEHALTEN | org.junit.jupiter:junit-jupiter | BOM/Parent → BOM/Parent | test → test | Gemeinsame Dependency; Version und Scope im effektiven POM prüfen. |
Die folgenden Ausschnitte stammen direkt aus den enthaltenen Projekten. Dadurch ist sichtbar, welche Verantwortung tatsächlich verschoben wurde.
Migrationsbedeutung: javax JAXB Model wird Jakarta JAXB Model.
projects/08-xml-jaxb/legacy/src/main/java/at/aydin/lab/xml/legacy/LegacyCustomer.java
package at.aydin.lab.xml.legacy;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "customer")
public class LegacyCustomer {
private String name;
private String email;
public LegacyCustomer() {
}
public LegacyCustomer(String name, String email) {
this.name = name;
this.email = email;
}
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
projects/08-xml-jaxb/modern/src/main/java/at/aydin/lab/xml/modern/ModernCustomer.java
package at.aydin.lab.xml.modern;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "customer")
public class ModernCustomer {
private String name;
private String email;
public ModernCustomer() {
}
public ModernCustomer(String name, String email) {
this.name = name;
this.email = email;
}
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
--- LegacyCustomer.java
+++ ModernCustomer.java
@@ -1,16 +1,16 @@
-package at.aydin.lab.xml.legacy;
+package at.aydin.lab.xml.modern;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
+import jakarta.xml.bind.annotation.XmlElement;
+import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "customer")
-public class LegacyCustomer {
+public class ModernCustomer {
private String name;
private String email;
- public LegacyCustomer() {
+ public ModernCustomer() {
}
- public LegacyCustomer(String name, String email) {
+ public ModernCustomer(String name, String email) {
this.name = name;
this.email = email;
}
Migrationsbedeutung: Marshaller/Unmarshaller-Verantwortung bleibt erhalten.
projects/08-xml-jaxb/legacy/src/main/java/at/aydin/lab/xml/legacy/LegacyXmlMapper.java
package at.aydin.lab.xml.legacy;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.StringWriter;
// Design Pattern: Mapper
// Zweck: Domänenobjekt und XML-Repräsentation werden kontrolliert ineinander überführt.
public final class LegacyXmlMapper {
public String toXml(LegacyCustomer customer) throws Exception {
JAXBContext context = JAXBContext.newInstance(LegacyCustomer.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter writer = new StringWriter();
marshaller.marshal(customer, writer);
return writer.toString();
}
}
projects/08-xml-jaxb/modern/src/main/java/at/aydin/lab/xml/modern/ModernXmlMapper.java
package at.aydin.lab.xml.modern;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Marshaller;
import java.io.StringWriter;
// Design Pattern: Mapper
// Zweck: Jakarta JAXB kapselt die XML-Serialisierung hinter einer klaren API.
public final class ModernXmlMapper {
public String toXml(ModernCustomer customer) throws Exception {
JAXBContext context = JAXBContext.newInstance(ModernCustomer.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter writer = new StringWriter();
marshaller.marshal(customer, writer);
return writer.toString();
}
}
--- LegacyXmlMapper.java
+++ ModernXmlMapper.java
@@ -1,14 +1,14 @@
-package at.aydin.lab.xml.legacy;
+package at.aydin.lab.xml.modern;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.Marshaller;
+import jakarta.xml.bind.JAXBContext;
+import jakarta.xml.bind.Marshaller;
import java.io.StringWriter;
// Design Pattern: Mapper
-// Zweck: Domänenobjekt und XML-Repräsentation werden kontrolliert ineinander überführt.
-public final class LegacyXmlMapper {
- public String toXml(LegacyCustomer customer) throws Exception {
- JAXBContext context = JAXBContext.newInstance(LegacyCustomer.class);
+// Zweck: Jakarta JAXB kapselt die XML-Serialisierung hinter einer klaren API.
+public final class ModernXmlMapper {
+ public String toXml(ModernCustomer customer) throws Exception {
+ JAXBContext context = JAXBContext.newInstance(ModernCustomer.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter writer = new StringWriter();
Migrationsbedeutung: Bootstrap wird auf Jakarta Runtime umgestellt.
projects/08-xml-jaxb/legacy/src/main/java/at/aydin/lab/xml/legacy/XmlLegacyApplication.java
package at.aydin.lab.xml.legacy;
public final class XmlLegacyApplication {
private XmlLegacyApplication() {
}
public static void main(String[] args) throws Exception {
System.out.println(new LegacyXmlMapper().toXml(new LegacyCustomer("Aydin", "aydin@example.test")));
}
}
projects/08-xml-jaxb/modern/src/main/java/at/aydin/lab/xml/modern/XmlModernApplication.java
package at.aydin.lab.xml.modern;
public final class XmlModernApplication {
private XmlModernApplication() {
}
public static void main(String[] args) throws Exception {
System.out.println(new ModernXmlMapper().toXml(new ModernCustomer("Aydin", "aydin@example.test")));
}
}
--- XmlLegacyApplication.java
+++ XmlModernApplication.java
@@ -1,10 +1,10 @@
-package at.aydin.lab.xml.legacy;
+package at.aydin.lab.xml.modern;
-public final class XmlLegacyApplication {
- private XmlLegacyApplication() {
+public final class XmlModernApplication {
+ private XmlModernApplication() {
}
public static void main(String[] args) throws Exception {
- System.out.println(new LegacyXmlMapper().toXml(new LegacyCustomer("Aydin", "aydin@example.test")));
+ System.out.println(new ModernXmlMapper().toXml(new ModernCustomer("Aydin", "aydin@example.test")));
}
}
| ID | Ebene | Prüfung | erforderlicher Nachweis |
|---|---|---|---|
| 08-XML-JAXB-A01 | Integration/Contract | Legacy-XML wird vom Modern Mapper gelesen. | Automatisierter Test und CI-Protokoll |
| 08-XML-JAXB-A02 | Integration/Contract | Modern erzeugtes XML erfüllt das bestehende Schema. | Automatisierter Test und CI-Protokoll |
| 08-XML-JAXB-A03 | Integration/Contract | Round-trip verliert keine Pflichtinformationen. | Automatisierter Test und CI-Protokoll |
| 08-XML-JAXB-A04 | Integration/Contract | Ungültiges XML wird sauber abgewiesen. | Automatisierter Test und CI-Protokoll |
| 08-XML-JAXB-A05 | Integration/Contract | XXE-Test bleibt negativ. | Automatisierter Test und CI-Protokoll |
| 08-XML-JAXB-T01 | Unit | Fachlogik ohne Container oder externen Dienst testen. | Unit-Test |
| 08-XML-JAXB-T02 | Regression | Legacy- und Modern-Ergebnis für denselben Golden-Master-Vektor vergleichen. | Vergleichsreport |
| 08-XML-JAXB-T03 | Negative | Fehlerhafte, leere und grenzwertige Eingaben prüfen. | Negativtest |
| 08-XML-JAXB-T04 | Operations | Start, Health, Shutdown und Konfigurationsfehler prüfen. | Deployment-/Startprotokoll |
| 08-XML-JAXB-T05 | Security | XXE, externe Entitäten und malformed XML negativ testen. | Security-Test |
| 08-XML-JAXB-F01 | Fokus | round-trip, invalid XML, encoding and XXE-negative tests | Modulspezifischer Testreport |
| Risiko | Auswirkung | Gegenmaßnahme | Gate |
|---|---|---|---|
| namespace and schema compatibility | NIEDRIG | round-trip, invalid XML, encoding and XXE-negative tests | vor Cutover |
| Neue Framework-/Library-Laufzeitabhängigkeiten | MITTEL | SBOM, Lizenz-, CVE- und transitive Dependency-Prüfung im Online-Build | vor Release |
| Legacy-Verhalten war implizit an entfernte Library gekoppelt | MITTEL | Contract-/Golden-Master-Tests und gezielte Fehlerpfade | vor Abschaltung |
Keine zusätzlichen Ressourcen.
Beide Mapper können hinter einer gemeinsamen Schnittstelle anhand Dokumentversion oder Feature Flag ausgewählt werden.