Your SlideShare is downloading. ×
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
JAX B
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

JAX B

4,807

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,807
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
99
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Michaelis/Schmiesing JAXB 2.0 Ein Programmiertutorial für die Java Architecture for XML Binding              
  • 2. Samuel Michaelis Wolfgang Schmiesing JAXB 2.0 Ein Programmiertutorial für die Java Architecture for XML Binding
  • 3. Die Autoren: Samuel Michaelis, Software-Architekt Wolfgang Schmiesing, Berater und Projektleiter Beide Autoren sind für die Innovations Softwaretechnologie GmbH in Immenstaad tätig. Alle in diesem Buch enthaltenen Informationen, Verfahren und Darstellungen wurden nach bestem Wissen zusammengestellt und mit Sorgfalt getestet. Dennoch sind Fehler nicht ganz auszuschließen. Aus diesem Grund sind die im vorliegenden Buch enthaltenen Informationen mit keiner Verpflich- tung oder Garantie irgendeiner Art verbunden. Autoren und Verlag übernehmen infolgedessen keine juristische Verantwortung und werden keine daraus folgende oder sonstige Haftung übernehmen, die auf irgendeine Art aus der Benutzung dieser Informationen – oder Teilen davon – entsteht. Ebenso übernehmen Autoren und Verlag keine Gewähr dafür, dass beschriebene Verfahren usw. frei von Schutzrechten Dritter sind. Die Wiedergabe von Gebrauchsnamen, Handelsnamen, Warenbe- zeichnungen usw. in diesem Buch berechtigt deshalb auch ohne besondere Kennzeichnung nicht zu der Annahme, dass solche Namen im Sinne der Warenzeichen- und Markenschutz-Gesetzgebung als frei zu betrachten wären und daher von jedermann benutzt werden dürften. Bibliografische Information Der Deutschen Nationalbibliothek Die Deutsche Nationalbibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über http://dnb.d-nb.de abrufbar. Dieses Werk ist urheberrechtlich geschützt. Alle Rechte, auch die der Übersetzung, des Nachdruckes und der Vervielfältigung des Buches, oder Teilen daraus, vorbehalten. Kein Teil des Werkes darf ohne schriftliche Genehmigung des Verlages in irgendeiner Form (Fotokopie, Mikrofilm oder ein anderes Verfahren) – auch nicht für Zwecke der Unterrichtsgestaltung – reproduziert oder unter Verwendung elektronischer Systeme verarbeitet, ver- vielfältigt oder verbreitet werden. © 2007 Carl Hanser Verlag München Wien Lektorat: Fernando Schneider Sprachlektorat: Sandra Gottmann, Münster-Nienberge Herstellung: Monika Kraus Umschlagdesign: Marc Müller-Bremer, Rebranding, München Umschlaggestaltung: MCP · Susanne Kraus GbR, Holzkirchen Datenbelichtung, Druck und Bindung: Kösel, Krugzell Ausstattung patentrechtlich geschützt. Kösel FD 351, Patent-Nr. 0748702 Printed in Germany ISBN-10: 3-446-40753-7 ISBN-13: 978-3-446-40753-4 www.hanser.de/computer
  • 4. Inhalt Vorw Java Architecture for XML Binding 2.0.................................................................................XI Technologieeinführung ........................................................................................................ XII Programmiertutorials............................................................................................................ XII Referenz ............................................................................................................................... XII Feedback ............................................................................................................................. XIII 1 JAXB im Überblick................................................................................................... 1 1.1 Ziele .........................................................................................................................................1 1.2 Entstehung................................................................................................................................4 1.3 Architektur ...............................................................................................................................5 1.3.1 Annotationen ..............................................................................................................7 1.3.2 Der Schema-Compiler ................................................................................................8 1.3.3 Der Schema-Generator ...............................................................................................9 1.3.4 Das Binding Framework...........................................................................................10 1.4 1.0 + 1.0 = 2.0? ......................................................................................................................14 2 Basistechnologien ................................................................................................. 17 2.1 XML-Schema.........................................................................................................................17 2.1.1 Namespaces verwenden............................................................................................21 2.1.2 Elementdeklarationen in XML-Schema ...................................................................24 2.1.3 Vererbung.................................................................................................................35 2.1.4 Kardinalitäten ...........................................................................................................37 2.1.5 Offene Schemas definieren.......................................................................................38 2.1.6 Namespaces importieren und referenzieren..............................................................40 2.1.7 Eindeutigkeit durch ID und IDREF ..........................................................................43 2.1.8 Dokumentation mit Annotationen ............................................................................45 2.1.9 Das fertige Beispielschema ......................................................................................46 V
  • 5. Inhalt 2.2 XPath......................................................................................................................................48 2.2.1 Die XPath-Sicht auf XML........................................................................................49 2.2.2 XPath-Ausdrücke verwenden ...................................................................................50 2.2.3 Beispiele ...................................................................................................................51 2.2.4 XPath in Java............................................................................................................53 2.3 ANT .......................................................................................................................................55 2.3.1 ANT-Übersicht .........................................................................................................55 2.3.2 Installation und Aufruf .............................................................................................56 2.3.3 Häufig verwendete Elemente....................................................................................57 2.3.4 Benutzerdefinierte Tasks ..........................................................................................58 2.3.5 xjc und schemaGen Tasks ........................................................................................58 2.3.6 Ein Beispiel ..............................................................................................................59 3 Hallo JAXB! ............................................................................................................ 61 3.1 Systemvoraussetzungen .........................................................................................................61 3.2 Die Entwicklungsumgebung einrichten..................................................................................62 3.2.1 JAXB-Referenzimplementierung installieren...........................................................62 3.2.2 Die JAXB-Bibliotheken einbinden...........................................................................62 3.2.3 Die Struktur des Beispielprojekts .............................................................................63 3.3 Am Anfang steht immer: Hallo Welt! ....................................................................................64 3.3.1 Der Weg von Java zu XML ......................................................................................64 3.3.2 Der Weg von XML zu Java ......................................................................................67 3.4 Zusammenfassung..................................................................................................................69 4 JAXB-API ................................................................................................................ 71 4.1 Die ersten Schritte ..................................................................................................................72 4.1.1 Am Anfang war der JAXBContext...........................................................................72 4.1.2 Die Klasse JAXBIntrospector verwenden ................................................................75 4.1.3 Objekte erzeugen mit der ObjectFactory ..................................................................77 4.1.4 Zusammenfassung ....................................................................................................78 4.2 Marshalling ............................................................................................................................79 4.2.1 Das Marshaller-Objekt anlegen ................................................................................79 4.2.2 Den Marshalling-Prozess starten ..............................................................................80 4.2.3 Den Marshalling-Prozess konfigurieren ...................................................................81 4.2.4 Das fertige Beispiel ..................................................................................................83 4.2.5 Marshalling beliebiger Objekte ................................................................................85 4.2.6 Zusammenfassung ....................................................................................................86 4.3 Unmarshalling ........................................................................................................................87 4.3.1 Das Unmarshaller-Objekt anlegen............................................................................87 4.3.2 Den Unmarshalling-Prozess starten..........................................................................88 4.3.3 Den Unmarshalling-Prozess konfigurieren...............................................................89 4.3.4 Das fertige Beispiel ..................................................................................................89 4.3.5 Das xsi:type-Attribut beim Unmarshalling verwenden.............................................90 4.3.6 Elemente ohne @XMLRootElement verarbeiten .....................................................91 4.3.7 Unmarshalling von Teilen eines XML-Dokuments ..................................................93 4.3.8 Flexibles Unmarshalling nutzen ...............................................................................95 VI
  • 6. Inhalt 4.3.9 Zusammenfassung ................................................................................................... 97 4.4 Validierung............................................................................................................................ 97 4.4.1 Beim Unmarshalling validieren ............................................................................... 98 4.4.2 Beim Marshalling validieren.................................................................................... 99 4.4.3 Benutzerdefinierte Validierung.............................................................................. 101 4.4.4 Zusammenfassung ................................................................................................. 107 4.5 Callback-Mechanismen einsetzen ....................................................................................... 107 4.5.1 Die Listener-Klasse verwenden ............................................................................. 108 4.5.2 Callback-Methoden auf Klassenebene definieren.................................................. 110 4.5.3 Zusammenfassung ................................................................................................. 112 4.6 Die Binder-Komponente verwenden ................................................................................... 112 4.6.1 Eine DOM-Sicht erstellen...................................................................................... 113 4.6.2 Die Klasse javax.xml.bind.Binder ......................................................................... 113 4.6.3 Transformation mit unmarshal und marshal .......................................................... 114 4.6.4 Navigation mit getXMLNode und getJAXBNode................................................. 115 4.6.5 Synchronisation mit updateXML und updateJAXB .............................................. 116 4.6.6 Konkrete Anwendungsfälle ................................................................................... 117 4.6.7 Zusammenfassung ................................................................................................. 123 5 XML-Schema zu Java .......................................................................................... 125 5.1 Bindungskonfigurationen .................................................................................................... 125 5.1.1 Eine Bindungskonfiguration definieren ................................................................. 126 5.1.2 Bindungskonfigurationen per xjc-Task einbinden ................................................. 130 5.1.3 Den XJC-Schema-Compiler programmatisch starten ............................................ 130 5.1.4 Externe Bindungskonfigurationen auf der Kommandozeile .................................. 134 5.1.5 Ein Wort zu Versionen .......................................................................................... 134 5.1.6 Der Sichtbarkeitsbereich........................................................................................ 134 5.1.7 Zusammenfassung ................................................................................................. 135 5.2 Die erste Bindungskonfiguration......................................................................................... 136 5.2.1 Zusammenfassung ................................................................................................. 138 5.3 Fünf Bindungsdeklarationen für den Alltag ........................................................................ 138 5.3.1 Aufzählungen anpassen mit jaxb:collectionType................................................... 138 5.3.2 Paketnamen anpassen mit jaxb:package ................................................................ 140 5.3.3 Generierte Klassen anpassen mit jaxb:class........................................................... 142 5.3.4 Änderungen auf Komponentenebene mit jaxb:property ........................................ 145 5.3.5 Dokumentieren mit jaxb:javadoc ........................................................................... 152 5.3.6 Zusammenfassung ................................................................................................. 155 5.4 XML-Bezeichner anpassen.................................................................................................. 155 5.4.1 Einzelne Namenskonflikte auflösen....................................................................... 156 5.4.2 Präfixe und Suffixe mit jaxb:nameXmlTransform................................................. 157 5.4.3 Unterstriche verarbeiten mit jaxb:underScoreBinding........................................... 159 5.4.4 Bezeichner in Enumerationen ................................................................................ 160 5.4.5 Verwenden von Java-Schlüsselwörtern als Bezeichner ......................................... 166 5.4.6 Java-Namenskonventionen .................................................................................... 168 5.4.7 Zusammenfassung ................................................................................................. 168 5.5 Datentypen anpassen ........................................................................................................... 168 VII
  • 7. Inhalt 5.5.1 Datentypen explizit angeben mit jaxb:baseType ....................................................169 5.5.2 Datentypen konvertieren mit jaxb:javaType...........................................................173 5.5.3 Zusammenfassung ..................................................................................................181 5.6 Deklarationen überlagern .....................................................................................................182 5.7 Noch mehr Bindungsdeklarationen ......................................................................................185 5.7.1 Ableiten von einer Oberklasse mit xjc:superClass..................................................186 5.7.2 Ein Wurzelinterface angeben mit xjc:superInterface ..............................................187 5.7.3 Erweiterung von jaxb:javaType mit xjc:javaType ..................................................189 5.7.4 Das Experiment: xjc:simple....................................................................................191 5.7.5 Zusammenfassung ..................................................................................................192 6 Java zu XML-Schema .......................................................................................... 193 6.1 JAXBContext und JAXBElement ganz ohne Schema..........................................................194 6.2 Einfache Elementkonfigurationen ........................................................................................201 6.2.1 Wurzelelemente mit @XmlRootElement definieren ..............................................201 6.2.2 Der „Standardmodus“.............................................................................................205 6.2.3 Abbildung als XML-Element explizit konfigurieren ..............................................210 6.2.4 Java-Eigenschaften an XML-Attribute binden .......................................................216 6.2.5 Java-Eigenschaften an XML-Elementinhalte binden..............................................221 6.2.6 Bindung an XML unterdrücken..............................................................................223 6.2.7 Reihenfolge der XML-Elemente beeinflussen........................................................225 6.2.8 Namen und Verschachtelung des XML-Typs einstellen.........................................230 6.2.9 XML-Elemente referenzieren .................................................................................234 6.2.10 Namespace konfigurieren .......................................................................................237 6.3 Listen und Elementmischungen ...........................................................................................243 6.3.1 Der „Standardmodus“ für Java-Arrays und Java-Listen .........................................244 6.3.2 Listen und Arrays an simpleType/list-Deklarationen binden..................................249 6.3.3 Mehrere Elemente im gleichen Feld speichern.......................................................251 6.3.4 Elementlisten verpacken.........................................................................................263 6.3.5 Mischungen von Elementen und Text ....................................................................266 6.4 Enumerationen .....................................................................................................................270 6.4.1 Enumerationen an XML binden: Standardverhalten...............................................271 6.4.2 Bindung von Enumerationen konfigurieren............................................................272 6.5 Eigene Typbindungen definieren .........................................................................................275 6.5.1 Basisdatentyp als Speicherdatentyp........................................................................277 6.5.2 Komplexe Datentypen als Speicherdatentypen.......................................................280 6.6 Unbekannte Attribut- und Elementwerte binden ..................................................................284 6.6.1 Wildcard-Attribute mit @XmlAnyAttribute definieren..........................................284 6.6.2 Wildcard-Elemente per @XmlAnyElement deklarieren ........................................286 6.6.3 Lax fischen .............................................................................................................288 6.7 Objektgraphen in XML abbilden..........................................................................................290 6.8 Elemente über Factory-Klassen definieren...........................................................................295 7 JAXB-Referenz..................................................................................................... 299 7.1 XJC Kommandozeilenbefehl ...............................................................................................299 7.2 XJC ANT-Task ....................................................................................................................301 VIII
  • 8. Inhalt 7.3 schemaGen-Kommandozeilenbefehl ................................................................................... 303 7.4 schemaGen-ANT-Task........................................................................................................ 304 7.5 JAXB-Annotationen............................................................................................................ 306 7.5.1 XmlAccessorOrder ................................................................................................ 306 7.5.2 XmlAccessorType ................................................................................................. 307 7.5.3 XmlAnyAttribute................................................................................................... 311 7.5.4 XmlAnyElement .................................................................................................... 312 7.5.5 XmlAttachmentRef................................................................................................ 314 7.5.6 XmlAttribute.......................................................................................................... 314 7.5.7 XmlElement........................................................................................................... 316 7.5.8 XmlElementDecl ................................................................................................... 318 7.5.9 XmlElementRef ..................................................................................................... 320 7.5.10 XmlElementRefs.................................................................................................... 321 7.5.11 XmlElements ......................................................................................................... 323 7.5.12 XmlElementWrapper ............................................................................................. 324 7.5.13 XmlEnum .............................................................................................................. 325 7.5.14 XmlEnumValue ..................................................................................................... 326 7.5.15 XmlID.................................................................................................................... 327 7.5.16 XmlIDREF............................................................................................................. 328 7.5.17 XmlInlineBinaryData............................................................................................. 330 7.5.18 XmlList.................................................................................................................. 330 7.5.19 XmlJavaTypeAdapter ............................................................................................ 331 7.5.20 XmlJavaTypeAdapters........................................................................................... 332 7.5.21 XmlMimeType ...................................................................................................... 333 7.5.22 XmlMixed.............................................................................................................. 333 7.5.23 XmlNs.................................................................................................................... 334 7.5.24 XmlRegistry........................................................................................................... 334 7.5.25 XmlRootElement ................................................................................................... 335 7.5.26 XmlSchema ........................................................................................................... 336 7.5.27 XmlSchemaType ................................................................................................... 338 7.5.28 XmlSchemaTypes.................................................................................................. 339 7.5.29 XmlTransient ......................................................................................................... 340 7.5.30 XmlType................................................................................................................ 341 7.5.31 XmlValue............................................................................................................... 342 7.6 Typkonversionen Java zu XML-Schema............................................................................. 343 7.7 Typkonversionen XML-Schema zu Java............................................................................. 345 7.8 XML-Elemente der Bindungskonfiguration ........................................................................ 346 7.8.1 Globale Einstellungen............................................................................................ 346 7.8.2 Schemaspezifische Einstellungen .......................................................................... 359 7.8.3 Komponentenspezifische Einstellungen ................................................................ 363 Register............................................................................................................................ 381 IX
  • 9. Vorwort Das Buch wendet sich an Entwickler mit guten Java-Kenntnissen, die in ihrem Arbeitsall- tag oft mit Java und XML arbeiten. In diesem Buch stellen wir mit Suns Java Architecture for XML Binding, kurz JAXB, eine tolle Lösung vor, wie wir dieser Herausforderung effek- tiv begegnen können. Java Architecture for XML Binding 2.0 Wer frühere Versionen der JAXB (1.x) eingesetzt oder evaluiert hat, dem mag die JAXB damals vielleicht verschroben vorgekommen sein. Tatsächlich war die technologische Hürde zum Einsatz von JAXB 1.x sehr hoch. Zum einen waren da die Verwirrungen mit den „endorsed“ XML-Bibliotheken, die Laufzeitfehler verursachten, wenn der Code auf unterschiedlich konfigurierten JVMs ausgeführt wurde – das gute, alte Java-Motto write once, run everywhere traf hier nicht mehr ohne Einschränkungen zu. Zudem waren die JAXB 1.x-Versionen noch nicht inspiriert vom jüngsten Trend zu den POJOs, den Plain Old Java Objects. Hier wurde stattdessen viel mit Factory-Methoden und Schnittstellen herumhantiert, die aus einem Schema ein unnatürliches und unhandliches Java- Datenmodell erzeugten. Von praktischer Bedeutung war in den Versionen bisher nur der Weg von einem XML- Schema zu einem Java-Datenmodell. Ergebnis ist, dass bisherige JAXB-Versionen keine besondere Unterstützung durch Hersteller oder Open-Source-Projekte erfahren haben. Statt dessen entstanden Projekte, die einen natürlicheren Ansatz zur Umwandlung von XML in Java jenseits des JAXB-Standards gesucht und gefunden haben und heute zu den Werk- zeugen der Wahl gehören. Mit der JAXB 2.0 fließen nun diese Ansätze in die JSE zurück: Die Nachteile der bisheri- gen JAXB-Versionen sind wie weggeblasen. Übrig bleibt eine sehr komfortable Art und Weise, aus XML-Schema ein POJO-Datenmodell bzw. aus POJOs ein präzise anpassbares XML-Format zu generieren. Wir sind überzeugt, dass mit der JAXB 2.0 eine Architektur entstanden ist, die für Entwickler eine langfristige und befriedigende Lösung des „XML- und Java“-Themas bringt und durch alle wesentlichen Hersteller und Projekte unterstützt XI
  • 10. Vorwort werden wird. Wir möchten mit diesem Buch einen kleinen Beitrag leisten, diese feine Technologie für alle Entwickler leicht zugänglich machen. Das Buch teilt sich in drei wesentliche Teile auf: Technologieeinführung, Programmiertu- torials und Referenz. Technologieeinführung Der erste Teile beschreibt die der JAXB-Spezifikation zugrunde liegenden Technologien XML-Schema, XPath und Ant im Überblick. Den wichtigsten Anteil übernimmt dabei ein Überblick auf wesentliche Konzepte von XML-Schema. Wir haben im Alltag die Erfah- rung gemacht, dass viele Entwickler XML-Schema zwar sehr gut als „Format zur Be- schreibung von XML-Formaten“ einordnen können und einfache Schemata auch ohne wei- teres verstehen, im konkreten Fall aber gerne nachschlagen, welche Bedeutung einzelne Schemadeklarationen und -konzepte besitzen. Daher bieten wir in diesem Buch eine kleine Einführung in XML-Schema mit dem Ziel, Antworten für die wesentlichen Fragen zu bie- ten, die im Rahmen der Tutorials aufkommen können. Zu den Technologien, die in den Beispielen dieses Buches verwendet werden, gehört auch XPath, das SQL der XML-Welt, und Ant. Auch für diese beiden Technologien bieten wir jeweils eine kleine Darstellung der wesentlichen Möglichkeiten. Programmiertutorials Der zweite Teil des Buches besteht aus vier klassischen Programmiertutorials, welche die verschiedenen Aspekte der JAXB in Beispielen von steigender Komplexität beleuchten. Nach dem obligatorischen „Hallo Welt“-Beispiel folgt eine Einführung in die Laufzeitbib- liothek der JAXB. In Kapitel 5 behandeln wir den Weg von einem XML-Schema zu einem Java-Datenmodell, in Kapitel 6 den Weg von einem Java-Datenmodell zu einem XML- Dokument. Referenz Der dritte Teil ist die Referenz. Wir haben uns zum Ziel gesetzt, dass die Referenz im We- sentlichen für sich alleine stehen kann – so dass ein Entwickler mit guten JAXB- Kenntnissen (die er sich in Programmiertutorial aneignen kann) alle im Alltag aufkom- menden Fragen schnell und insbesondere vollständig anhand der gut strukturierten Refe- renz klären kann. Das hat zur Folge, dass einzelne Informationen in diesem Buch eventuell redundant im Programmiertutorial und in der Referenz vorkommen. Von einem Kommunikationsprofi habe ich mir aber versichern lassen, dass Redundanz, die wir Entwickler im Programmier- XII
  • 11. Vorwort alltag als Code Duplication verteufeln, richtig angewendet im Bereich der Didaktik eine der gerne zitierten Best Practices ist. Wir möchten uns an dieser Stelle bei Ihnen als Leser bedanken, dass Sie dieses Buch und viele weitere durch Ihren beherzten Griff ins Regal Ihres Buchhändlers möglich gemacht haben, und hoffen an dieser Stelle, dass Ihnen die Lektüre dieses Buchs viel Spaß macht und Ihnen interessante, neue Ansätze für Ihre alltägliche Arbeit bieten kann. Feedback Kein Prozess kann sich ohne Feedback sinnvoll verbessern! Beachten Sie diesen schlauen Spruch bitte nicht nur in Ihrem Arbeitsalltag, sondern schicken Sie uns gerne Ihr Feedback zu diesem Buch an jaxbtransparent2@rmiregistry.de. Vielen Dank! XIII
  • 12. 1 JAXB im Überblick Im folgenden Kapitel werden wir die Java Architecture for XML Binding 2.0 aus der Vo- gelperspektive betrachten. Hier gilt es, die wesentlichen Teile der JAXB-Spezifikation an- schaulich und im Überblick darzustellen. Insbesondere werden wir hier die Begriffe prä- gen, mit denen wir die Komponenten der JAXB im weiteren Verlauf des Buches und der Tutorials referenzieren werden. Wir werden darauf eingehen, welche Ziele mit der JAXB- Spezifikation 2.0 insgesamt angestrebt wurden. Um die Hintergründe der JAXB zu verstehen, darf ein Blick auf die Entstehung der JAXB- Spezifikation nicht fehlen. Mit diesem Grundverständnis über den Aufbau und das Zu- sammenspiel der einzelnen Architekturkomponenten gerüstet, wird es uns leichter fallen, die später im Programmiertutorial vorgestellten Funktionen zu verstehen. Für Anwender, die bereits mit der Version 1.0 der JAXB gearbeitet haben, werden wir abschließend die Unterschiede und Neuerungen in der Version 2.0 vorstellen. 1.1 Ziele Eine High-Level-XML-API bieten Die Java Architecture for XML Binding ermöglicht dem Applikationsentwickler, seine Ja- va-Anwendung optimal mit XML interagieren zu lassen. JAXB hat dabei den Anspruch, eine API auf weit abstrakterer Ebene zu bieten, als das bisher mit parser-basierten Ansät- zen wie SAX und DOM möglich war. Auch Entwickler, die nicht mit diesen Parsern ver- traut sind, sollen die Möglichkeit haben, XML in ihre Anwendungen zu integrieren. Die JAXB-Spezifikation bemüht sich daher um eine möglichst einfache, für Java- Entwickler intuitiv nutzbare Schnittstelle für den Zugriff auf XML-Daten. Doch was eignet sich als intuitive Schnittstelle? Java Beans sind wohl eines der Konzepte, die jedem Java- Entwickler vertraut sind. Daher liegt es nahe, Bindungsinformation und Daten durch Klas- sen im Java Beans-Stil zu repräsentieren. Und genau das ist das primäre Ziel der JAXB, die Bindung von XML an Java über portable Java Beans, im Fachjargon auch Pojos, kurz 1
  • 13. 1 JAXB im Überblick für plain old Java objects, genannt. Auf diese Weise können wir bequem über die vertrau- ten Java-Programmiermethoden mit schemabasierten XML-Daten arbeiten. Die konsequente Einführung des Pojo-Konzepts in die JAXB-Spezifkation und die einfa- che Konfiguration dieser Objekte mit Annotationen vereinfachen die Erstellung dieses Typs von Datenbindung ungemein. Java 5-Spracherweiterungen nutzen Um diese Bindung bei Bedarf individuell anzupassen, enthält JAXB Konfigurationsme- chanismen, welche die Struktur der erzeugten Klassen bzw. des erzeugten Schemas beein- flussen können. Dafür werden u.a. Java-Annotationen verwendet, die eine der Erweiterungen darstellen, die mit der Java Standard Edition 5 eingeführt wurden. Die JAXB-Spezifikation macht aber auch regen Gebrauch von den weiteren Neuerungen der JSE 5 wie den typsicheren Enumerationen und den sogenannten Generics. Diese Spracherweiterungen machen die generierten Klassen und XML-Schemas einfacher und vor allem auch deren Verwendung sicherer (insbesondere typsicherer). Die Struktur der erzeugten Klassen und XML-Schemas wird durch Standardkonfiguratio- nen der JAXB und benutzerdefinierte Konfigurationen fest vorgegeben. Oft ist es aber auch nötig, die generierten Klassen um benutzerdefinierten Code zu erweitern. Auch hier- für müssen Mechanismen definiert werden, um die generierten Klassen so flexibel wie möglich zu machen. XML-Schema vollständig unterstützen Um die JAXB in realen Anwendungen einsetzbar zu machen, ist außerdem eine vollstän- dige Unterstützung der W3C XML-Schemasprache ein weiteres primäres Ziel der JAXB 2.0. Denn nur durch eine vollständige Unterstützung von XML-Schema wird sich JAXB als Standard durchsetzen können. Bidirektionale Bindung unterstützen Ein weiteres wichtiges Ziel der Spezifikation ist die Unterstützung einer bidirektionalen Datenbindung, d.h., sowohl die Generierung von Java Beans aus einem bestehenden Schema als auch der umgekehrte Weg, die Generierung eines Schemas aus einem beste- henden Java Beans-Datenmodell, soll durch die JAXB 2.0 unterstützt werden. Dabei soll auch ein Round Trip möglich sein. Das bedeutet, dass für den Weg Java–XML– Java, also eine Generierung eines Schemas aus einem Java-Datenmodell und die erneute Ableitung eines Datenmodells aus diesem Schema, Eingabe und Ausgabe äquivalent sind. Unterstützung von Webservices Die Generierung eines Java-Datenmodells aus einem XML-Schema, um eine Anwendung mit XML-Dokumenten interagieren zu lassen, ist sicherlich vielen ein Begriff. Aber auch 2
  • 14. 1.1 Ziele der umgekehrte Weg gewinnt im Zeitalter der Webservices mehr an Bedeutung. Wird eine Anwendung beispielsweise als Webservice veröffentlicht, so wird das existierende Daten- modell der Anwendung durch ein WSDL-Dokument beschrieben. Dies kann durch JAXB 2.0 automatisiert werden, indem aus dem existierenden Datenmodell ein XML-Schema generiert wird, das dann bei der Kommunikation über XML und SOAP verwendet wird. In diesem Zusammenhang sollten wir nicht verschweigen, dass die JAXB 2.0- Spezifikation die Grundlage für die Bindung von WSDL an Java-Datentypen in der Java API für XML Web Services (JAX-WS 2.0) bildet. Damit soll JAXB zum Standard für Da- tenbindungen bei Java-basierten Webservices werden. Validierung jederzeit ermöglichen Auch die Validierung von XML-Dokumenten ist eins der Themen, die durch JAXB adres- siert werden sollen. Sowohl beim Unmarshalling, also der Transformation von XML- Inhalten in Java-Objekte, als auch beim Marshalling, der Transformation von Java- Objekten in XML-Dokumentstrukturen, kann eine Validierung anhand eines XML- Schemas durchgeführt werden. Die Validierung soll dabei so gestaltet sein, dass flexibel auf ungültige Inhalte reagiert werden kann. Um das Rad nicht neu zu erfinden, wird bei der Validierung auf bereits bestehende Technologie anderer Java-Spezifikationen zurückge- griffen. Schemaevolution unterstützen Ein großes Problem bei der Entwicklung von Datenbindungen an XML-Schema ist die Weiterentwicklung des XML-Schemastandards. Ein Ziel der JAXB ist daher die Unter- stützung des Umgangs mit dieser sog. Schemaevolution. Portabilität zwischen JAXB-Implementierungen Um die JAXB als einen De-facto-Standard für XML-Datenbindungen zu etablieren, soll die Spezifikation in die kommende Java-Version 6.0, Codename „Mustang“, einfließen. Daher muss die Portabilität der generierten Klassen auf Quellcode- und Binärcode-Ebene sichergestellt werden. Portabilität bedeutet hier, dass die generierten Klassen einer be- stimmten JAXB-Implementierung von jeder anderen Implementierung genutzt werden können. Portabilität des Quellcodes bedeutet, dass durch JAXB erstellter Quellcode von allen JAXB-Implementierungen verstanden wird. Der erstellte Quellcode darf außerdem keine Abhängigkeiten zu einer bestimmten Implementierung besitzen. Die Portabilität des Binär- codes macht eine erneute Kompilierung dieses Quellcodes bei einem Wechsel der Imple- mentierung überflüssig. Dieser Ansatz unterscheidet sich von bisherigen Frameworks, die sich des Mittels des By- tecode Enhancements bedienen, um eine einfache Javabean nach dem Kompilieren um Framework-spezifische Funktionalitäten zu erweitern. Solchermaßen erweiterter Bytecode ist dann nicht mehr portierbar. 3
  • 15. 1 JAXB im Überblick 1.2 Entstehung Spezifizierung durch JSR 222 JAXB ist aus dem Java Community Process 1 , kurz JCP, hervorgegangen. Im JCP entwi- ckeln Expertengruppen Spezifikationen im Bereich der Java-Entwicklung. Diese Spezifi- kationen werden als Java Specification Requests (JSR) betrieben und veröffentlicht. Einige bekannte JSRs sind etwa die Java 5 Generics aus JSR 14 oder typsichere Enumerationen in JSR 201. Auch für die JAXB gibt es eine Expertengruppe, deren Hauptaufgabe natürlich die Weiter- entwicklung der JAXB-Spezifikation ist. Neben dieser Spezifikation in Papierform besteht ein JSR in der Regel noch aus einer Codebasis, nämlich einer Referenzimplementierung (RI) und einem Technology Compatibility Toolkit (TCK). Die Referenzimplementierung dient dazu, den aktuellen Stand der Spezifikation als Imp- lementierung widerzuspiegeln und zu validieren. Weitere solcher Implementierungen der Spezifikation durch andere Anbieter sind natürlich möglich, sogar erwünscht. So wird mit JAX-Me2 2 eine alternative Implementierung der JAXB von der Apache Group 3 betrieben. Das TCK stellt die Kompatibilität einer JAXB-Implementierung zum JAXB-Standard si- cher. Es besteht aus einer Reihe von Tests, die eine JAXB-Implementierung erfolgreich durchlaufen muss, um sich für den JAXB Standard zu zertifizieren. Entwicklung durch das JAXB Project Die Entwicklung und Verwaltung der Referenzimplementierung wird durch das JAXB Pro- ject betrieben. Das JAXB Project wurde bei Sun als Open-Source-Projekt veröffentlicht. Diese Entwicklergruppe realisiert neben der oben beschriebenen Referenzimplementierung und dem TCK noch weitere Tools zur Unterstützung rund um JAXB. Das JAXB Project ist wiederum Teil des Projekts Glassfish, das eine Referenzimplementierung der neuen Java Enterprise Edition 5 darstellt.Veröffentlichung Erstmals veröffentlicht wurde JAXB in der Version 1.0 durch den JSR 31. Seit dieser Ver- sion ist JAXB auch Bestandteil des Java Web Service Developer Packages (Java WSDP, aktuell in der Version 2.0). In diesem Buch werden wir uns ausschließlich der neuen JAXB in der Version 2.0 widmen, die einige bedeutende Neuerungen umfasst und damit einen großen Schritt in Richtung Projekttauglichkeit macht. Die JAXB 2.0 wurde im April 2006 als Final Release des JSR 222 verabschiedet. Getragen wird die Spezifikation dabei hauptsächlich von Sun Microsystems. Die Expertengruppe 1 http://www.jcp.org 2 http://ws.apache.org/jaxme 3 http://www.apache.org 4 https://jaxb.dev.java.net 4
  • 16. 1.3 Architektur wird jedoch noch von vielen weiteren Industriegrößen wie BEA, Oracle und SAP unter- stützt. Ziel dabei ist, die JAXB-Spezifikation in Zukunft in die Java Standard Edition zu integrieren. Damit wäre JAXB die Standardlösung für Java-XML-Datenbindungen. Doch genug der Geschichte, es ist an der Zeit, einen Blick auf die Architektur von JAXB zu werfen. 1.3 Architektur Als erster Überblick sind hier die einzelnen Komponenten der JAXB-Architektur gelistet. In den folgenden Abschnitten werden wir die genannten Komponenten dann etwas näher beschreiben. Architekturkomponenten Annotationen: Die JAXB ist ein annotationsgetriebenes Framework (annotation driven). Annotationen werden dazu verwendet, die Abbildung von Java- auf XML- Repräsentation zu konfigurieren. Schema-Compiler: Der Schema-Compiler bindet ein existierendes Schema an ein gene- riertes Java-Datenmodell. Diese Erzeugung einer Java-Repräsentation aus einem XML-Schemadokument ist ein häufig verwendeter Weg, die Java- und XML-Welten zu verbinden. Er eignet sich besonders für dokumentgetriebene Anwendungsszenarien. Schema-Generator: Der Schema-Generator bindet ein existierendes Java-Datenmodell an ein generiertes XML-Schema. Die Information für die Abbildung der Java- Elemente auf ein XML-Schema definiert der Entwickler durch Annotationen im exis- tierenden Datenmodell. Dieser Weg eignet sich am besten für modellgetriebene An- wendungsszenarien. Binding Framework: Das Binding Framework stellt die Schnittstelle zur Anwendung dar. Es bietet eine Reihe von API-Klassen und -Funktionen, die zur Laufzeit aufgeru- fen werden: Die wichtigsten Funktionen sind das Marshalling und Unmarshalling. Das Unmarshalling realisiert die Transformation von XML zu Java. Das Marshalling hin- gegen überführt Java-Objekte in XML-Dokumentinstanzen. Begleitend zu diesen Ope- rationen kann automatisch eine Validierung der XML-Inhalte anhand eines XML- Schemas erfolgen. Mit dem Binder schließlich kann eine transparente Bearbeitung ei- nes XML-Dokuments über ein gebundenes Java-Datenmodell erfolgen – Marshalling und Unmarshalling finden hier im Hintergrund statt. 5
  • 17. 1 JAXB im Überblick Compile-Zeit- vs. Laufzeitkomponenten Grundsätzlich können wir die Architekturkomponenten in zwei Bereiche aufteilen: Komponenten der Compile-Zeit: Schema-Compiler und Schema-Generator werden zu- sammen mit den Annotationen zur Compile-Zeit, d.h. vor Ausführung der Anwendung, benötigt. Sie stellen die Bindung durch Generieren eines Java-Datenmodells bzw. eines Schemas her. Komponenten der Laufzeit: Das Binding Framework wird zur Laufzeit von der An- wendung selbst benutzt, um XML-Inhalte zu verarbeiten. Das Zusammenspiel dieser Komponenten zeigt die folgende Architekturübersicht. XML-Schema Bindungsdeklarationen Portable Java Beans JAXB-Annotationen JAXB Annotationen Compile-Zeitkomponenten Laufzeitkomponenten <f:foo ... <element ... Unmarshalling Binding-Framework Unmarshalling </element> </f:foo> JAXB API Marshalling Marshalling Validierung XML-Dokument Java Beans-Instanzen Abbildung 1.1 Komponenten der JAXB-Architektur 6
  • 18. 1.3 Architektur 1.3.1 Annotationen Annotationen werden, wie bereits erwähnt, durchgängig durch die JAXB verwendet, so- wohl vom Schema-Compiler als auch vom Entwickler selbst. Sie werden sowohl in den generierten Java Beans-Klassen verwendet als auch im XML-Schema. Wir unterscheiden daher zwei Arten von Annotationen: Mapping-Annotationen: Bei der Generierung eines Java-Datenmodells aus einem exis- tierenden XML-Schema versieht eine JAXB-Implementierung die generierten Klassen mit Java-Annotationen, die Informationen über die Java-XML-Bindung enthalten. Ja- va-Annotationen sind im JSR 175 5 beschrieben und eine der Spracherweiterungen der Java Standard Edition 5. Diese Mapping-Annotationen beschreiben in JAXB die Ab- bildung der XML-Elemente des Schemas auf die Elemente des generierten Java- Datenmodells (z.B. Klassen, Eigenschaften etc.). Dadurch beinhaltet das generierte Da- tenmodell neben den Java-Klassen gleichzeitig eine Repräsentation des zugrunde lie- genden Schemas. Das XML-Schema selbst wird daher zur Laufzeit nicht mehr gebraucht, da alle benö- tigten Informationen bereits in den Annotationen gespeichert werden. Der eigentliche Vorteil der Annotationen zeigt sich jedoch erst im umgekehrten Fall, der Bindung von XML-Daten an ein existierendes Java-Datenmodell. Hier kann der Entwickler jetzt selbst seine existierenden Java-Klassen mit Mapping-Annotationen versehen. Diese Mapping-Annotationen definieren die Bindung der Java-Klassen an die XML-Daten. Sie stellen dann implizit ein XML-Schema dar. Werden keine Mapping-Annotationen vom Entwickler angegeben, greift JAXB auf Defaultkonfigurationen zurück. Die Refe- renz enthält in Kapitel 7.5 eine detaillierte Auflistung aller möglichen Mapping- Annotationen und ihre Auswirkung auf den erzeugten Code. Bindungskonfigurationen: Auch bei der Erzeugung eines Datenmodells aus einem exis- tierenden XML-Schema kann die Bindung individuell konfiguriert werden. Dazu kann der Entwickler Annotationen für das XML-Schema angeben. Diese Annotationen wer- den Bindungsdeklarationen genannt und sind selbst wieder in XML formuliert. Da- durch kann z.B. definiert werden, dass alle generierten Java-Klassen für ein XML- Schema das Interface  implementieren. Bindungskonfigurationen kön- nen definiert werden, indem ein existierendes XML-Schemadokument mit Annotatio- nen versehen wird. Diese Annotationen werden dann nicht über Java-Annotationen, sondern direkt in XML durch das -Element formuliert. Sie können entwe- der im Schema selbst oder über eine externe XML-Datei übergeben werden. Wir sehen also, dass Annotationen ein grundlegendes Konzept der JAXB sind. Sie tragen zur Konfigurierbarkeit und Portabilität der Java-XML-Bindung bei. 5 http://www.jcp.org/en/jsr/detail?id=175 7
  • 19. 1 JAXB im Überblick 1.3.2 Der Schema-Compiler Um eine Bindung von XML-Schema nach Java zu erstellen, generiert der Schema- Compiler portable Java-Objekte aus einem bestehenden Schema. <xs:schema ... <xs:element ... <xs:attribute ...> <xs:annotation> ... </xs:annotation> </xs:schema> @XmlRootElement public class { XML-Schema @XmlElement ... Schema-Compiler String element ... @XmlAttribute <jaxb:bindings ... <jaxb:class... Java Beans mit <jaxb:property ...> JAXB-Annotationen </jaxb:bindings> Bindungs- konfiguration Abbildung 1.2 Der Schema-Compiler Woher weiß der Schema-Compiler nun, wie das generierte Java-Datenmodell aussehen soll? Die JAXB-Spezifikation definiert dazu für jede Komponente der W3C XML- Schemasprache eine entsprechende Java-Repräsentation, z.B. eine Java-Klasse, eine Ei- genschaft oder eine Enumeration. Jedem dieser Java-Sprachelemente werden zusätzlich Mapping-Annotationen hinzugefügt, welche die entsprechende Schemakomponente beschreiben. Diese Abbildung zwischen XML-Schema und Java stellt die Standardbindung des Schema-Compilers dar. In den meisten Fällen genügt diese Standardbindung den Anforderungen einer Applikatio- nen. In manchen Fällen sind allerdings Anpassungen der generierten Java-Klassen nötig. Hier kommen die im vorigen Abschnitt erwähnten Bindungsdeklarationen zum Einsatz. Sie überschreiben die Standardbindung des Schema-Compilers und erlauben benutzerdefi- nierte Abbildungen von Schemakomponenten auf Java. Formuliert werden diese Bin- dungsdeklarationen ebenfalls in XML. Auf die einzelnen Konfigurationsmöglichkeiten ge- hen wir im Rahmen des Programmiertutorials genau ein. Die folgende Tabelle gibt uns einen Überblick über die Abbildung der Schemakomponen- ten auf Java-Programmelemente. 8
  • 20. 1.3 Architektur Tabelle 1.1 Abbildungsbeziehungen zwischen XML-Schema und Java-Elementen XML-Schemakomponente Java-Komponente Namespace Java-Paket   Komplexer Datentyp Benutzerdefinierte Java-Klasse       Einfacher Datentyp Java-Datentypen und Wrapper-Klassen    Einfacher Datentyp mit Enumeration Facet Java-Enumeration                 Unterelemente eines komplexen XML-Typ Java-Eigenschaften der gebundenen Klasse       Das bedeutet, dass wir nach dem Ausführen des Schema-Compilers eine Ansammlung von Java-Klassen bekommen, die der Schema-Compiler in dem angegebenen Paket ablegt. Der Schema-Compiler erzeugt zusätzlich dazu noch eine Klasse . Mit dieser Klasse wird dem Programmierer, der Name verrät es bereits, eine Factory-Klasse an die Hand gegeben. Mit dieser Klasse können nun bequem Instanzen der generierten JAXB Klassen erzeugt werden. Wir werden uns die  im Zusammenhang mit dem Marshalling von XML-Dokumenten noch genauer ansehen. 1.3.3 Der Schema-Generator Der Schema-Generator verwendet die in Tabelle 1.1 definierten Abbildungsregeln im um- gekehrten Sinne, um ein Schema aus einem bestehenden Java-Datenmodell zu erzeugen. 9
  • 21. 1 JAXB im Überblick <f:foo ... <element ... </element> </f:foo> @XmlRootElement public class ... { XML-Dokument @XmlElement ... String element ... <xs:schema ... @XmlAttribute <xs:element ... <xs:attribute ...> Java Beans mit <xs:annotation> JAXB-Annotationen ... </xs:annotation> </xs:schema> XML-Schema Abbildung 1.3 Der Schema-Generator Auch híer gibt es Standardbindungen, die z.B. aus einer benutzerdefinierten Klasse einen komplexen Typen im XML-Schema erzeugen. Für die Default-Bindungen müssen keine expliziten Annotationen im Datenmodell angegeben werden, die JAXB-Spezifikation setzt in diesem Fall die Standardbindung voraus. Ein Java-Datenmodell kann auf diese Weise mit der Angabe von nur einigen wenigen An- notationen vollständig auf ein Schema abgebildet werden. Die Standardbindungen können aber durch die Angabe der oben erwähnten Mapping-Annotationen ergänzt bzw. über- schrieben werden, um die Bindung entsprechend anzupassen. Der Vorteil ist, dass diese Annotationen direkt in ein existierendes Datenmodell eingefügt werden können. Wann und wie wir ein Datenmodell mit Mapping-Annotationen versehen, wird ausführlich im Programmiertutorial behandelt. Eine detaillierte Auflistung der mögli- chen Annotationen findet sich in der Referenz. 1.3.4 Das Binding Framework Wie bereits erwähnt, vereint das Binding Framework die API-Funktionen der JAXB zur Verarbeitung von XML-Dokumenten zur Laufzeit. Es befindet sich im Paket   der JAXB-Laufzeitbibliothek. Es bietet die folgenden Funktionalitäten, die wir in diesem Abschnitt im Detail darstellen: Umarshalling: Laden von XML. Marshalling: Speichern von XML. 10
  • 22. 1.3 Architektur Event-Callbacks: Nachrichten im Rahmen des Unmarshallings bzw. Marshallings ver- arbeiten. Validierung: Die Gültigkeit von verarbeiteten XML-Dokumenten sicherstellen. Binder: Modifizieren eines XML-Dokuments ohne explizites Laden oder Speichern. 1.3.4.1 Unmarshalling Beim Unmarshalling wird eine XML-Schemainstanz, d.h. ein XML-Dokument, das ein gegebenes Schema als Formatbeschreibung referenziert, in einen Graph aus Java-Objekten transformiert. Dieser Objektgraph besteht aus Instanzen von Java Beans, die mit Mapping- Annotationen versehen sind. Der Inhalt unseres XML-Dokuments ist somit nach erfolgtem Unmarshalling im Speicher präsent. Unsere Anwendung kann dann ohne den Einsatz einer zusätzlichen XML-API auf die Java Beans wie auf normale Objekte zugreifen. Klingt einfach, oder? Ist es auch, wie wir später im Programmiertutorial sehen werden. Ein häufiges Problem, auf das wir beim Unmarshalling stoßen, sind ungültige XML- Inhalte. Es ist zwar möglich, bereits vorher über die Validierung Dokumente mit ungülti- gen Inhalten auszuschließen. Aber nicht immer wollen wir uns den Overhead einer Vali- dierung leisten. Oft besitzen die XML-Dokumente auch keine besonders hohe Datenquali- tät, sie sind z.B. unvollständig oder fehlerhaft ausgefüllt. Trotzdem muss die Anwendung mit diesen Inhalten umgehen können. Daher wurde in JAXB 2.0 die Möglichkeit vorgese- hen, ein Unmarshalling von ungültigen Inhalten vorzunehmen. Generell existieren nämlich zwei unterschiedliche Verfahren des Unmarshallings. Structural Unmarshalling: Dieses Verfahren implementiert das strikte Unmarshalling eines XML-Dokuments. Die Reihenfolge der Elemente im XML-Dokument muss ex- akt übereinstimmen mit der im XML-Schema definierten Reihenfolge. Trifft dies nicht zu, wird das Unmarshalling mit einer Fehlermeldung abgebrochen. Das Unmarshalling basiert also auf der Struktur des XML-Dokuments. Eventuelle Abweichungen vom zugrunde liegenden Schemadokument werden sofort aufgedeckt. Dieser Ansatz wurde in früheren Versionen der JAXB verfolgt. Er eignet sich nicht besonders für die Be- handlung von ungültigen oder veränderten Inhalten. Flexible Unmarshalling: Dieses Verfahren ist weniger strikt und lässt uns auch Doku- mente verarbeiten, deren Elementreihenfolge nicht hundertprozentig mit dem Schema übereinstimmt. Die Elemente werden dem Namen nach transformiert statt nach ihrer Position im Dokument. Dadurch können Dokumente verarbeitet werden, die zwar vom Schema abweichen, deren Inhalte aber dennoch ausreichende Information besitzen. Dies gilt z.B. für XML-Dokumente mit abweichender Elementreihenfolge, fehlenden oder unbekannten Elementen. JAXB 2.0 verfolgt standardmäßig ein flexibles Unmars- halling, um beispielsweise die Evolution, also die Weiterentwicklung von XML- Schemas und XML-Dokumenten zu unterstützen. Denn immer häufiger unterliegen XML-Dokumente einer ständigen Weiterentwicklung, so dass der Bedarf für ein fehler- 11
  • 23. 1 JAXB im Überblick tolerantes, flexibles Unmarshalling ständig größer wird. Ein konkretes Beispiel hierzu findet sich im Unmarshalling-Abschnitt des Tutorials. 1.3.4.2 Marshalling Das Marshalling geht nun den umgekehrten Weg. Ein im Speicher vorhandener Objekt- graph wird serialisiert, d.h., in ein XML-Dokument überführt. Der Objektgraph besteht dabei wieder aus Instanzen von Java Beans, die mit JAXB-spezifischen Annotationen ver- sehen sind. Durch diese Annotationen werden die Objekte auf die zugehörigen XML-Elemente abge- bildet. Die Zielstruktur, in die Objekte überführt werden, kann dabei verschiedene Formate besitzen. So kann eine JAXB-Implementierung das XML in Standardausgabeströme der Java Core API wie  oder  schreiben, aber auch höhere Ausgabeschnittstellen und Standards wie SAX, DOM, StAX nutzen und sogar mit Transformationen per XSL kombinieren. 1.3.4.3 Event Callbacks Sowohl für das Marshalling als auch das Unmarshalling kann der Entwickler sog. Call- back-Methoden einfügen. Diese Methoden arbeiten nach dem Hollywood-Prinzip („don’t call us we’ll call you“), das u.a. durch das Spring Framework 6 populär geworden ist. Da- durch kann während des Marshallings/Unmarshallings applikationsspezifische Logik aus- geführt werden. Mit der Implementierung dieser Callback-Mechanismen werden wir uns später im Programmiertutorial noch näher beschäftigen. 1.3.4.4 Validierung Eine Validierung von Inhalten kann eine JAXB-Implementierung automatisch sowohl beim Unmarshalling als auch beim Marshalling durchführen. Diese Validierung ist jedoch bewusst optional gehalten, um Anwendungsszenarien behandeln zu können, die keine Va- lidierung benötigen oder wo eine Validierung der Daten nicht regelmäßig möglich ist. Beim Unmarshalling wird das zu verarbeitende XML-Dokument überprüft. Beim Marshal- ling dagegen muss der im Speicher existierende Objektgraph auf Gültigkeit überprüft wer- den. Wer jetzt denkt, die Validierung beim Unmarshalling sollte doch auch genügen, der sollte sich das Fail-fast-Prinzip ins Gedächtnis rufen. Nach diesem Entwurfsprinzip für Pro- grammierschnittstellen sollten Fehler so früh wie möglich aufgedeckt und an die Anwen- dung kommuniziert werden. Diesem Prinzip folgt auch die JAXB. Das bedeutet, dass un- gültige Daten bereits beim Marshalling aufgedeckt werden sollten, also noch bevor die Da- ten eventuell an eine andere Komponente einer Architektur weitergegeben werden. 6 http://www.springframework.org 12
  • 24. 1.3 Architektur Denkbar wäre z.B. eine Anfrage an einen Webservice, bei der XML-Daten einem WSDL- Dokument gemäß versendet werden. Eine Validierung der Daten vor der Absendung der Anfrage, beim Marshalling, hilft, Fehler dort aufzudecken, wo sie entstehen. Die Validierung führt also die Überprüfung der im XML-Schema definierten Einschrän- kungen und Formatvorgaben durch. Dabei können die Einschränkungen in zwei Katego- rien unterteilt werden. Statische Einschränkungen: Dies sind z.B. Einschränkungen auf Datentypen wie ,  oder . Solche Einschränkungen werden später durch die por- tablen Java Beans aufrechterhalten. Verletzungen dieser Einschränkungen werden be- reits durch die Java-Typüberprüfung erkannt und können zur Laufzeit bei der Um- wandlung von und in XML theoretisch nie auftreten. Dynamische Einschränkungen: Einschränkungen auf Wertebereiche oder die Definition von komplexen Typen mit bestimmten Kindelementen können erst zur Laufzeit über- prüft werden. Diese Validierungen können durchaus sehr aufwendig werden, da unter Umständen der gesamte Objektgraph überprüft werden muss, z.B. um die Eindeutigkeit einer XML-Element-ID zu überprüfen. Tritt nun ein Verstoß gegen eine der oben genannten Einschränkungen auf, so wird ein Fehlerereignis generiert. Das Fehlerereignis besitzt Informationen zu der Art des Fehlers und dem Ort, an dem der Fehler aufgetreten ist. Solche Fehlerereignisse können entweder sofort an die aufrufende Anwendung weitergegeben oder zunächst gesammelt und nach erfolgter Validierung als Liste weitergereicht werden. Zur Durchführung der Validierung muss im einfachen Fall ein XML-Schema angegeben werden. Die eigentliche Validierung wird dabei seit JAXB 2.0 durch die in der Java Stan- dard Edition 5 enthaltene JAXP 1.3 API übernommen. JAXP 1.3 definiert eine Standard- API zur Validierung von XML-Dokumentinstanzen. Dieses „Outsourcing“ der Validie- rung hat den zusätzlichen Vorteil einer kompakteren Implementierung. Die Verwendung der JAXP Validation API bietet weit mehr Flexibilität und Konfigurier- barkeit als die JAXB-eigene Validierung der Version 1.0. So können beispielsweise neben den Standardmechanismen zur Behandlung der Validierung auch eigene Implementierun- gen der sog. Validation-Event-Handler-Interfaces verwendet werden. Dadurch kann indi- viduell auf ganz bestimmte Fehler reagiert werden, z.B. um eine gewisse Fehlertoleranz einer Anwendung zu gewährleisten. Die Validierung ist dabei nicht auf XML-Schema festgelegt – so können über entspre- chende Schnittstellen auch ganz eigene Implementierungen für eine XML-Validierung beigesteuert werden. 1.3.4.5 Binder Die -Komponente der JAXB-API kann zwei verschiedene Sichten auf ein XML- Dokument gleichzeitig verwalten. Angenommen, es existiert in einer Anwendung bereits 13
  • 25. 1 JAXB im Überblick eine Sicht auf ein XML-Dokument, z.B. als DOM 7 . Ein DOM-Modell repräsentiert ein XML-Dokument durch Objekte, die Knoten, Elemente und Attribute darstellen. Mithilfe des Binders kann zusätzlich dazu für das gesamte Dokument oder auch nur für Teile eine zweite Sicht erstellt werden. Diese Sicht besteht aus den bereits bekannten JAXB-Klassen. Wird nun von der Anwendung eine dieser beiden Sichten verändert, kann der Binder die jeweils andere Sicht mit den Änderungen aktualisieren und so beide Sichten synchron hal- ten. Ein häufiger Anwendungsfall ist hier die Darstellung eines Ausschnitts aus dem XML- Dokument durch JAXB-Klassen. Diese JAXB-Klassen stellen die zu verändernden Teile des Dokuments dar. Das gesamte Dokument ist weiterhin als DOM-Modell verfügbar, wird aber vielleicht nur lesend verwendet. Schreibzugriffe erfolgen aufgrund der einfache- ren Verwendbarkeit durch JAXB. Der modifizierbare Ausschnitt des Dokuments kann dabei z.B. durch einen XPath- Ausdruck dargestellt werden. Die folgende Abbildung soll die Funktion der - Komponente etwas veranschaulichen. unmarshal Binder update customer <response ... <customer ... load <address .../> </customer> JAXB </response> save Mapping <customer> address XML-Dokument DOM-Baum Java Beans-Instanzen Abbildung 1.4 Die Binder-Komponente 1.4 1.0 + 1.0 = 2.0? Die Neuerungen der JAXB 2.0 Was hat sich nun seit der Version 1.0 bei der JAXB-Spezifikation getan? Lohnt es sich, meine Anwendung zu migrieren? Ist JAXB noch komplizierter geworden als in der Vor- gängerversion? Diese Fragen werden sich diejenigen stellen, die bereits mit JAXB in Be- rührung gekommen sind. 7 Document Object Model 8 http://www.w3.org/TR/1999/RECxpath-19991116 14
  • 26. 1.4 1.0 + 1.0 = 2.0? Java nach XML-Schemaabbildung Die JAXB hat sich mit der Version 2.0 fundamental verändert. Die größte Änderung dürfte die Einführung der Bindung existierender Java-Datenmodelle an XML sein. Während in JAXB 1.0 im Wesentlichen ein XML-Schema in ein Java-Datenmodell umgewandelt wur- de, ist jetzt eine elegante Art der Datenbindung durch die Annotation von existierenden Klassen entstanden. In JAXB 2.0 kann eine Java-XML-Bindung konfiguriert werden, ohne dass hierbei aus ei- nem XML-Schema mithilfe des Schema-Compilers JAXB-spezifische Klassen generiert werden müssen. Die aus Sicht der Datenbindung bestehende Einbahnstraße in JAXB 1.0 wurde sozusagen zu einer bidirektionalen Autobahn in JAXB 2.0 ausgebaut. Portabilität JAXB geht außerdem in der Version 2.0 einen fundamentalen Schritt weiter in Richtung Portabilität. In JAXB 1.0 werden aus den Komponenten eines Schemas Interfaces und de- ren Implementierungsklassen generiert. Diese vom Schema abgeleiteten Klassen gingen eine enge Kopplung mit der jeweiligen Implementierung der JAXB und mit der JAXB- Laufzeitbibliothek selbst ein. Für die Abwärtskompatibilität werden diese Interfaces zwar weiterhin unterstützt, jedoch geht man offiziell einen anderen Weg. In JAXB 2.0 sind es die mit Annotationen versehe- nen portablen Klassen, die an Schemakomponenten gebunden werden. Da diese Klassen im Wesentlichen Java Beans darstellen, sind sie an keine spezifische Implementierung der JAXB gebunden. Als Entwickler arbeitet man daher mit konkreten Klassen statt der bisherigen Interfaces. Es ist möglich, ein Java-Datenmodell nachträglich und ohne wesentliche Änderung von einer JAXB-Implementierung auf eine andere zu portieren, aber auch von einer XML- Datenbindung beispielsweise an eine Datenbank-Datenbindung. Volle Unterstützung von XML-Schema Ein weiteres Manko der JAXB 1.0 ist die unvollständige Unterstützung der XML- Schemasprache. Mit der Version 2.0 ist in JAXB die volle Unterstützung der W3C XML- Schemaspezifikation angestrebt. Es können jetzt alle in W3C XML-Schema vorhandenen Konzepte in einem Java-Datenmodell abgebildet werden. Hinzugefügt wurde unter ande- rem die fehlende Unterstützung von Wildcards und Typsubstitutionen. Java 5-Unterstützung Dem allgemeinen Trend folgend, setzt auch JAXB 2.0 voll auf die Spracherweiterungen der Java Standard Edition 5. Zum einen sind das die erwähnten Annotationen. Aber auch Generics werden unterstützt, was eine erhöhte Typsicherheit zur Folge hat, da z.B. alle ge- nerierten Listen bereits den korrekten Typ besitzen. Auf der anderen Seite bedeutet dies 15
  • 27. 1 JAXB im Überblick aber auch, dass Anwendungen mit JAXB 2.0 die Verwendung der JSE 5 oder höher vor- aussetzen. Redesign der Validierung Auch was die Validierung angeht bietet JAXB 2.0 einige Neuerungen. Um eine flexiblere Behandlung der Validierung von XML-Dokumenten zu ermöglichen, wird in der Version 2.0 die Validierungskomponente der JAXP 1.3 API verwendet. Damit wurde die bisherige On-Demand-Validierung beim Unmarshalling ersetzt. Die Validierung kann nun optional sowohl beim Unmarshalling als auch beim Marshalling durchgeführt werden. Die neue Validierungskomponente ist wesentlich flexibler und er- laubt nun auch das Unmarshalling von teilweise ungültigen XML-Dokumenten. Dadurch wurden auch Performance-Aspekte in JAXB 2.0 adressiert. So konnte die Anzahl der generierten Klassen gesenkt und die Größe der Laufzeitbibliotheken verringert werden. Umstieg von JAXB 1.0 nach 2.0 Doch was passiert nun mit Applikationen, die auf der Version 1.0 der JAXB basieren? JAXB 2.0 beinhaltet alle nötigen Bibliotheken, die für die Ausführung von existierenden JAXB 1.0-Applikationen benötigt werden. Der Schema-Compiler  der Version 2.0 ist auch in der Lage, JAXB 1.0-kompatiblen Code zu generieren. Um eine auf der JAXB 1.0 basierende Applikation auf die JAXB 2.0 zu portieren, muss allerdings das Schema mit der neuen Version des  Schema-Compilers kompiliert und die Anwendung mit den generierten Klassen aktualisiert werden. Außerdem muss natürlich beachtet werden, dass JAXB 2.0 nur ab der Java-Version 5 eingesetzt werden kann. Wobei im Rahmen der Spezifikation darauf geachtet wurde, dass eine JAXB-Implementierung potenziell über entsprechende „Retro-Translatoren“ zumindest zur Laufzeit Java 1.4- Kompatibilität bieten können. 16
  • 28. 2 Basistechnologien In diesem Kapitel gehen wir auf die im Rahmen der JAXB verwendeten Basistechnologien XML-Schema, XPath und ANT ein. 2.1 XML-Schema XML ist seit langem eins der Standardformate, wenn es um die plattformunabhängige Repräsentation von Daten geht. Das Besondere an XML: Es werden nicht nur die reinen Daten, sondern auch die Metadaten in einem XML-Format gespeichert. Also nicht nur die Information „Müller“, sondern auch die Information „Müller ist der Nachname eines Kun- den“. Rein technisch betrachtet ist XML ein sehr redundantes und aufgeblähtes Format, als Datenaustauschformat hat es den großen Vorteil, dass jeder Entwickler ein XML- Dokument öffnen und lesen kann, ohne dass die Daten zusätzlich aufbereitet werden müss- ten. Besonders vielseitig wird XML durch die Möglichkeit, die erwarteten Daten in Form einer DTD oder eines XML-Schemas zu spezifizieren. Über solche Formatbeschreibungen las- sen sich Form und Gültigkeit eines Datensatzes beschreiben: „Jeder Kundendatensatz muss einen Namen angeben, eine Adressangabe ist optional möglich.“ In diesem Kapitel möchten wir auf die wesentlichen Möglichkeiten von XML-Schema eingehen, das sich zu dem umfangreichsten und genauesten Format zur Beschreibung von Formaten gemausert hat. Mit XML-Schema können wir Grammatiken definieren, also Einschränkungen und Regeln zu den Daten in einem XML-Dokument. Ein mit XML-Schema beschriebenes Dokument kann anhand der Grammatik auf seine Gültigkeit überprüft werden. Eine solche Validie- rung wird von einem Schema-Validierer durchgeführt. So lassen sich z.B. Daten beschreiben, die dem Nachrichtenaustausch zwischen verschie- denen Anwendungen dienen. Durch Verwendung eines XML-Schemas wird den einzelnen Komponenten ein einheitliches, überprüfbares Format bereitgestellt. 17
  • 29. 2 Basistechnologien Im Zusammenhang mit XML-Schema werden oft die Begriffe Schemadokument und Schemainstanz verwendet. Ein XML-Schemadokument definiert die oben genannte Grammatik zu den XML- Daten und legt so deren Struktur für alle Beteiligten fest. Eine XML-Schemainstanz hingegen ist ein XML-Dokument, das ein Schemadokument verwendet, um XML-Daten konform zu einer Grammatik zu beschreiben. XML-Schema wird heute von vielen XML-basierten Standards und APIs verwendet wie z.B. der Web Service Description Language (WSDL). Ursprünglich vorgeschlagen von Microsoft, wurde die Sprache schließlich 2001 als Emp- fehlung durch das Webkonsortium W3C 1 offiziell veröffentlicht. Im Gegensatz zu anderen Grammatikdefinitionen wie DTD , die mittels einer zusätzlichen Sprache definiert werden, basiert XML-Schema selbst auch auf XML. Weitere Vorzüge sind die Erweiterbarkeit und eine Vielzahl an vordefinierten Datentypen. Außerdem wer- den objektorientierte Konzepte wie Namensräume und Vererbung unterstützt. Aus diesen Gründen hat sich XML-Schema mittlerweile gegen DTD durchgesetzt. Aber auch XML- Schema hat natürlich Konkurrenz, der wichtigste Standard ist hier wohl RelaxNG, für den in JAXB bereits experimentelle Unterstützung zu finden ist. Bei der Arbeit mit JAXB wird uns XML-Schema ein ständiger Begleiter sein. Es gibt eine ganze Reihe toller Bücher zum Thema XML-Schema. Daher wird dieses Kapitel sich dar- auf beschränken, einen Überblick über die wichtigsten Konzepte zu geben, die wir für das unmittelbare Verständnis der Beispiele in diesem Buch für notwendig halten. Um ein XML-Schema definieren zu können, benötigen wir natürlich ein Grundverständnis für den Aufbau eines XML-Schemas. Daher wird zunächst der Schemaaufbau unter Ver- wendung von Namensräumen erläutert. Danach werden wir uns ausführlich der Definition von Datentypen widmen, da wir diese später mit JAXB an unsere Java-Klassen binden wollen. Ein weiteres wichtiges Thema in diesem Zusammenhang ist die Formulierung von Einschränkungen auf diesen Datentypen. Da wir natürlich mit objektorientierten Datenmodellen arbeiten wollen, darf auch die Ver- erbung von Datentypen in XML-Schema nicht fehlen. Vererbung ist aber nur ein Mittel zur Erweiterbarkeit von Schemas. Wir werden uns daher noch mit weiteren Mitteln zur Definition von erweiterbaren, offenen Schemas befassen. In dieser Hinsicht betrachten wir abschließend das Zusammensetzen eines Schemas aus mehreren Teilschemas, was uns ei- ne komponentenbasierte Definition der Daten ermöglicht. Die genannten Konzepte werden wir anhand eines Objektmodells darstellen, das sukzessi- ve im Verlauf des Kapitels aufgebaut wird. Auf diesem Domänenobjektmodell, im Engli- schen das Domain Object Model, werden dann alle weiteren Programmierbeispiele im Ver- lauf des Buches aufbauen. 1 http://www.w3.org 2 Document Type Definitions 18
  • 30. 2.1 XML-Schema Da eine erschöpfende Behandlung von XML-Schema weit über den Rahmen dieses Kapi- tels hinausgeht, sei für weitere Informationen auf das Buch XML Schema von Eric van der Vlist verwiesen. Ein XML-Schemadokument bildet also die Grundlage einer Java-XML-Bindung mit JAXB. Ein solches Schemadokument beschreibt dabei sowohl Struktur als auch Datenty- pen einer Schemainstanz. Im einfachsten Fall besteht ein Schemadokument aus der Defini- tion der gültigen Elemente sowie deren Reihenfolge und Anordnung. Es lassen sich aber auch komplexe Strukturen aufbauen, die sich über mehrere Schemas erstrecken und ganze Datentyphierarchien aufbauen. Im Verlauf dieses Kapitels werden wir mehrere Schemas entwickeln und diese zu einer komplexen Struktur zusammenfügen. Zunächst aber konzentrieren wir uns auf ein einfaches Beispiel: Stellen wir uns einen Online-Banking-Service vor, der auf eintreffende XML-Requests von Clients eine entsprechende Response im XML-Format zurückliefert. Im Request wird eine Kunden-ID mitgeliefert. Als Antwort liefert der Service dann entsprechende Informationen über die Stammdaten, die Kontodaten sowie über ein evtl. vorhandenes Aktienportfolio des Kunden. Diese Daten werden z.B. aus einer Datenbank gewonnen. Die Struktur der vom Service zurückgelieferten Daten wird durch die folgenden XML-Schemas definiert. response: Enthält die Antwort des Service auf einen eingehenden Request. customerElement: Enthält die Stammdaten eines Kunden. accountElement: Enthält alle kontorelevanten Daten eines Kunden. portfolioElement: Repräsentiert das Aktienportfolio eines Kunden. Das Schema  nutzt dabei die in den Schemas ,  und   erstellten Datentypen, um eine Datenstruktur für die Ausgabe an den Client zusam- menzustellen. Abbildung 2.1 Das response-Schema Um nicht gleich die Übersicht zu verlieren, sehen wir uns zunächst nur die Stammdaten eines Kunden an. 19
  • 31. 2 Basistechnologien Abbildung 2.2 Stammdaten eines Kunden Für diese Daten sieht ein einfaches Schemadokument nun so aus:                Das Dokument oben legt für den Kunden also ein Element mit den entsprechenden Unter- elementen für die Stammdaten an. Das schema-Element Sehen wir uns zunächst den Kopf dieses Dokuments ein wenig genauer an. Ein Schemado- kument beginnt immer mit dem einleitenden Wurzelelement . Im obigen Beispiel sind in diesem -Element zwei weitere Attribute definiert, die beide jeweils eine URL als Wert enthalten.      20
  • 32. 2.1 XML-Schema Diese Attribute definieren verschiedene Namensräume in unserem Schemadokument. Die- se werden gewöhnlich im einleitenden -Element definiert. Ihre Verwendung wird im nächsten Abschnitt behandelt. Sehen wir uns zunächst noch der Vollständigkeit halber ein entsprechendes XML-Dokument zu unserem Schemadokument an.         Dieses Dokument nutzt also das vorher definierte -Element, um einen Kundendatensatz zu beschreiben. 2.1.1 Namespaces verwenden In der Einleitung wurde erwähnt, dass durch XML-Schema Grammatiken definiert werden. Eine Grammatik setzt grundsätzlich auf einem bestimmten Vokabular auf. Solche Vokabu- lare können wir in XML-Schema durch Definition von Elementen frei bestimmen. Was aber, wenn sich unsere Datentypen mit den Definitionen anderer Vokabulare überschnei- den? Das Problem solcher Namenskonflikte wird in XML-Schema durch die Verwendung von Namensräumen, den Namespaces, gelöst. Die XML-Spezifikation definiert einen Na- mespace wie folgt: An XML namespace is a collection of names, identified by a URI reference [RFC2396], which are used in XML documents as element types and attribute names. Ein Namespace schafft also einen gemeinsamen Kontext für eine Menge von Elementen, Attributen und Datentypen. Ziel dabei ist es, eine einheitliche und eindeutige Bezeichnung der Elemente zu ermöglichen. Vergleichbar zu einem XML-Namespace ist ein Java-Paket, in dem Java-Klassen gruppiert werden, um Namenskonflikte zu verhindern und den Klas- sen einen gemeinsamen Kontext zu geben. Das Standardvokabular von XML-Schema besitzt z.B. den Namespace http://www.w3.org/2001/XMLSchema, der auch schon im einleitenden Beispiel verwendet wurde. Dieser Namespace enthält die grundlegenden Elemente zur Definition neuer Ele- mente, Attribute und Typen. Wenn wir nun weitere Elemente definieren, können wir diese einem anderen, von uns gewählten Namespace zuordnen. Bei der Benennung unserer Ele- mente bleiben wir dadurch völlig frei. 2.1.1.1 Namespaces definieren Eine Namespace-Definition wie beispielsweise  setzt sich zusammen aus: 21
  • 33. 2 Basistechnologien Dem Schlüsselattribut ; dieses Attribut kennzeichnet eine Namespace-Definition. Einem optionalen Präfix, z.B. ; das Präfix kennzeichnet die Zugehörigkeit eines lements zu einem bestimmten Namespace, z.B. gehört das Element  zum oben angegebenen XML-Schema-Namespace. Ein Präfix stellt also eine Art Abkür- zung für den URI eines Namespace dar. Einem URI 3 , z.B. http://jaxb.transparent/customer, der dem Präfix zugewiesen wird. Dieser URI stellt einen eindeutigen Bezeichner für den Namespace dar. 2.1.1.2 XML-Schema und Target-Namespace Es steht uns frei, eigene Namespaces in einem Dokument zu definieren.. Wir können auch ein Schemadokument erstellen, das keine benutzerdefinierten Namespaces enthält, ein so- genanntes „stand-alone schema“. Ein Schemadokument muss jedoch zumindest auf den XML-Schema-Namespace verweisen: Dieser Namespace definiert nämlich die Standardelemente von XML-Schema, die wir zur Definition eines Schemadokumentes nutzen können, z.B. , , , , ,  etc. Nach allgemeiner Konvention erhält er zumeist das Präfix  oder . Da wir später in unserer Anwendung mit mehreren verschiedenen Schemas arbeiten, bietet es sich jedoch an, für jedes Schema stets einen eigenen Namespace zu definieren. Dies hilft, später Elemente eindeutig voneinander abzugrenzen. Um die in einem Schemadoku- ment definierten Elemente, Attribute und Datentypen mit einem bestimmten Namespace zu verknüpfen, deklarieren wir diesen Namespace als sog. Target-Namespace im Wurzel- element. Der Target-Namespace lautet für unser Kundenschema beispielsweise http://jaxb.transparent/customer. Definitionen von Datentypen in einem Schemadokument beziehen sich immer auf genau einen Namespace, den Target-Namespace. Ein Schema darf daher genau einen Target- Namespace definieren. Elemente, die dieses Schema neu definiert, werden automatisch mit diesem Namespace assoziiert. Geben wir keinen Target-Namespace an, so landen die hier definierten Schemaelemente im Standard-Namespace und können von anderen Schemas nicht mehr eingebunden werden. Auf das obige Beispiel bezogen bedeutet dies, dass das Element  auto- matisch dem Namespace http://jaxb.transparent/customer zugeordnet wird. 2.1.1.3 Namespaces in XML-Dokumenten verwenden Bisher haben wir im Schemadokument einen eigenen Namespace durch den Target- Namespace definiert. Wie können wir nun angeben, dass die Elemente in einer Schema- 3 Uniform Resource Identifier 22
  • 34. 2.1 XML-Schema instanz diesen Target-Namespace verwenden? In unserem Kundenbeispiel sieht das fol- gendermaßen aus:           Im öffnenden Tag des Kundenelements  geben wir den URI des Na- mespace an.  Als Präfix ist hier  angegeben, d.h., Elemente mit dem Präfix  werden diesem Na- mespace zugeordnet. Solche Namespace-Deklarationen können für Elemente an beliebiger Stelle in einem XML-Dokument vorgenommen werden. Durch das einleitende Element  und das dazugehörende Attribut  haben wir das -Element mit dem Namespace http://jaxb.transparent/customer assozi- iert. Nun müssen wir noch den Ort des Schemadokuments angeben, auf das sich Elemente aus dem Namespace http://jaxb.transparent/customer beziehen. Dazu deklarieren wir zu- nächst den XMLSchema-instance-Namespace. Dieser Namespace erlaubt uns, ein existie- rendes Schemadokument zu referenzieren.  Das Element  dieses Namespace gibt den Ort des Schemadokuments an. Es kann sich hier wie im Beispiel um einen lokalen Ort handeln oder auch um eine Inter- netadresse.  Mehrere Definitionen werden einfach durch Leerzeichen getrennt, die Anzahl der hier de- finierten Elemente muss daher gerade sein (Namespace + Schemadokument). Wird ein Schemadokument in einem XML-Dokument wie oben beschrieben referenziert, kann die- ses Dokument gegen das angegebene Schema validiert werden. Der Schema-Validierer versucht bei der Validierung, das Schemadokument vom angegebenen Ort zu laden und die Schemainstanz gegen dieses Dokument auf Gültigkeit zu überprüfen. 2.1.1.4 Einen Default-Namespace verwenden Bisher haben wir für jeden Namespace ein Präfix vergeben, so auch für den XML-Schema- Namespace das Präfix . Wir können jedoch auch einen Namespace ohne Präfix definie- ren, dieser ist dann der Default-Namespace für das aktuelle Dokument. Im folgenden Bei- 23
  • 35. 2 Basistechnologien spiel definieren wird den XML-Schema-Namespace als Default-Namespace. Wir können daher das Präfix  vor den -, - und Tags weglassen, da präfixlose Tags mit dem Default-Namespace assoziiert werden.                Noch einmal zum Merken: Mit dem Default-Namespace werden alle präfixlosen Tags verknüpft. Mit dem Target-Namespace werden alle Definitionen von Elementen, Datentypen und Attributen eines Schemas verknüpft. Das obige Schemadokument ist komplett äquivalent zum folgenden Schemadokument, das allerdings keinen Default-Namespace verwendet. Es ist hier eher eine Frage des Stils, wel- che Variante verwendet wird. Bei der Verwendung mehrerer Namespaces in einem Doku- ment ist es jedoch übersichtlicher, alle Namespaces mit einem Präfix zu versehen.                2.1.2 Elementdeklarationen in XML-Schema Bisher haben wir uns mit der allgemeinen Definition und den Namespaces eines Schema- dokuments beschäftigt. Um die in unserer Anwendung verwendeten XML-Daten auf ihre Gültigkeit prüfen zu können, müssen wir erst einmal die Struktur der Daten in unserem Schemadokument festlegen. Innerhalb des -Elements werden wir daher die Ele- mente und Attribute definieren, aus denen sich ein Kundendatensatz zusammensetzt. Dabei soll die Adresse des Kunden noch in Straße, PLZ, Ort und Land unterteilt werden. 24
  • 36. 2.1 XML-Schema 2.1.2.1 Elemente Für unseren Kundendatensatz verwenden wir zunächst Elemente einfachen Typs, d.h. E- lemente, die keine anderen Elemente oder Attribute beinhalten können. Diese Elemente können direkt wie folgt definiert werden.         Ein Element wird also über seinen Namen und Datentyp definiert. Dabei können als Da- tentyp sowohl vordefinierte XML-Schema-Datentypen (mit dem Präfix ) verwendet werden als auch beliebige benutzerdefinierte Datentypen. Oben haben wir bereits einige der gängigen XML-Schema-Datentypen benutzt wie z.B. ,  und . Darüber hinaus stellt XML-Schema noch eine Vielzahl weiterer Datentypen bereit. Diese können in der Datentypreferenz der XML-Schema Recommendation 4 des W3C nachge- schlagen werden. Die zu unserem Schemadokument gültigen Elemente einer Schemainstanz sehen wie folgt aus:         Standardwerte Es lassen sich auch Standardwerte für Elemente definieren. Wird einem solchen Element kein Wert zugewiesen, so trägt es den im Attribut  angegebenen Wert. Ein Beispiel:  Wenn also das so deklarierte Element in einer Instanz dieses Schemas nicht vorhanden sein sollte, so wird an dessen Stelle ein Element mit dem Wert „Germany“ angenommen. 2.1.2.2 Attribute Die Elemente in einem Schema können natürlich auch Attribute definieren. Die Definition eines Attributs gleicht der eines Elements einfachen Typs: 4 z.B. unter http://www.w3.org/TR/xmlschema-2/ 25
  • 37. 2 Basistechnologien  Beispielsweise könnte ein Attribut  für das Element  existieren, das die zu einer Straße gehörige Hausnummer angibt. Die Definition im Schemadokument lautet fol- gendermaßen:       Innerhalb des Elements  geben wir ein Element  an, das unsere Attri- butdefinition enthält. Als Typ des Attributs  ist eine positive Ganzzahl angegeben.  bezeichnet eine benutzerdefinierte Struktur, die weitere Elemente und Attri- bute enthalten kann. Wir werden dieses Konstrukt im nächsten Abschnitt noch näher be- leuchten. Wir sehen aber, dass Elemente mit Attributen 1. immer durch das -Konstrukt beschrieben werden. 2. Attribute selbst als einfache Typen definiert sind. Da das Element  einerseits eine Zeichenkette mit dem Straßennamen enthalten soll, zusätzlich aber auch noch ein XML-Attribut, müssen wir das Attribut  bei der Defi- nition des  setzen. Setzen von  gibt an, dass der komplexe Typ sowohl Text als auch Attribute enthält. Das Attribut  In der obigen Attributdefinition ist außerdem noch das Attribut  gesetzt. Dieses Attribut spezifiziert, dass das Element  auf jeden Fall ein Attribut  enthalten muss. Mögliche Werte für  sind: required: Das Attribut muss für dieses Element vorhanden sein. optional: Das Attribut kann für dieses Element vorhanden sein. prohibited: Das Attribut darf in diesem Element nicht auftreten. Hinweis Das -Attribut kann nur gesetzt werden, wenn – wie oben – ein Attribut innerhalb eines E- lements definiert wird. Nur hier ergibt es auch einen Sinn, da  sich immer auf das äußere Element bezieht. Im XML-Dokument sieht unser Element  mit dem neuen Attribut nun wie folgt aus:  26
  • 38. 2.1 XML-Schema 2.1.2.3 Komplexe Datentypen Bisher haben wir für unseren Kundendatensatz eine flache Struktur aus einfachen Elemen- ten mit vordefinierten Datentypen benutzt. Da unsere Anwendung aber Objekte verwendet, um Daten zu repräsentieren, z.B. ein Adressobjekt mit Straße, PLZ, Ort und Land, erwei- tern wir diese flache Datenstruktur durch einen benutzerdefinierten, komplexen Typ. An- genommen, wir wollen ein XML-Format definieren, bei dem ein Kunde einen komplexen Typ  definiert. Die verschachtelten XML-Elemente sehen dann wie folgt aus:             Durch Definition entsprechender komplexer Typen können wir diese verschachtelte Struk- tur darstellen.                    In diesem Listing haben wir die einzelnen Adressenelemente durch ein Element  ersetzt, das die Adressdaten in einem komplexen Element vom Typ  kapselt. Der komplexe Typ  ist im gesamten Schemadokument wiederverwendbar, da er auf der Hauptebene mit dem -Konstrukt definiert wurde. Strukturierte Typen per complexType deklarieren Solche komplexen Typen, d.h. Elemente, die andere Elemente oder Attribute enthalten können, werden durch das Element  definiert.    27
  • 39. 2 Basistechnologien      Der Typ wird durch einen Namen eindeutig identifiziert. Innerhalb des Elements  können beliebig viele weitere Elemente und Attribute definiert werden. Komplexe Elemente können auch weiter verschachtelt werden. In unserem Beispiel ver- wenden wir außerdem noch ein weiteres Element , das die Ordnung der Unterelemente in unserem Adressobjekt bestimmt. Ordnung mit sequence, all, choice Durch Angabe eines der Schlüsselwörter ,  oder  können wir bestim- men, wie die Elemente eines komplexen Typs verwendet werden sollen. Im obigen Bei- spiel wird durch Angabe des Sequenzindikators  zum Beispiel die Reihenfolge bestimmt, in der die Elemente eines Adressobjekts im XML-Dokument auftreten müssen. Tabelle 2.1 zeigt die möglichen Schlüsselwörter und ihre Auswirkung auf die Ordnung komplexer Typen. Tabelle 2.1 Ordnen von Elementen mit sequence, all und choice Schlüsselwort Effekt  Im XML-Dokument müssen die Elemente in der hier angegebenen Reihenfolge auftreten.  Im XML-Dokument müssen alle Unterelemente dieses Elements auftreten. Die Reihenfolge ist jedoch beliebig.  Im XML-Dokument darf eines dieser Elemente auftreten, nicht jedoch mehrere. In unserer Beispielanwendung können wir diese Indikatoren nutzen, um die Konsistenz der Kundendaten zu gewährleisten. Beispielsweise möchten wir festlegen, dass in einem Kun- dendatensatz alle Adressdaten, d.h. Straße, PLZ, Ort und Land, vorhanden sein müssen, während die Angabe eines Wertes für E-Mail oder Telefon genügen soll. Außerdem soll der Name des Kunden immer am Anfang stehen, gefolgt von den Adressdaten und den üb- rigen Kontaktdaten. Das passende Schemadokument zu diesen Anforderungen sieht folgendermaßen aus:          28
  • 40. 2.1 XML-Schema                Wir haben hier also den Indikator  für die Reihenfolge der Kundendaten ver- wendet. Der Indikator  legt fest, dass alle Adresselemente ausgefüllt sein müssen, wäh- rend der Indikator  die Angabe eines der Elemente  oder  verlangt. Eine gültige Schemainstanz zeigt das folgende Listing.               Das Schemadokument im vorigen Listing weist allerdings noch eine Besonderheit im Ver- gleich zu den bisherigen Dokumenten auf. In XML-Schema gibt es verschiedene Arten, einen Datentyp zu definieren. Lokale vs. globale Definition Bisher haben wir unser Kundendatenelement  folgendermaßen definiert:      Der komplexe Typ wurde einfach innerhalb des Elements  definiert. Dies nennt man lokale Definition oder auch Inlining. Dieser anonyme, komplexe Typ ist nur innerhalb des Elements  sichtbar. Im letzten Schemadokument wurde das Element  jedoch so definiert: 29
  • 41. 2 Basistechnologien     In diesem Fall wird ein komplexer Typ mit dem Namen  in der Wurzel des Schemadokumentes definiert und bei der Definition des Elements über das Attribut  referenziert. Diese globale Definition ermöglicht es, den Typ  auch in anderen Elementen zu verwenden. Das Gleiche gilt natürlich auch für Elemente, die Attribute ent- halten, wie in Abschnitt 2.1.2.2 beschrieben. Die Definition der Datenstruktur für die Stammdaten der Kunden sei damit abgeschlossen. Nun brauchen wir eine weitere Datenstruktur, die Informationen über das Konto eines Kunden darstellt. Hier kommt eine weitere Möglichkeit ins Spiel, Datentypen zu definie- ren: die verfeinerten Basisdatentypen oder Simple Types. 2.1.2.4 Basisdatentypen verfeinern XML-Schema bietet die Möglichkeit, auch für einfache Datentypen weitergehende Typin- formationen zu definieren – die sogenannten „Simple Types“. Diese definieren also keine Unterelemente im Sinne eines strukturierten Datentyps, sondern schränken die möglichen Werte eines der Basisdatentypen wie ,  etc. ein. Beispielsweise können wir hier festlegen, dass für ein Feld nur eine Zahl zwischen 3 und 13 angegeben werden darf oder etwa dass ein Wert nur A, B oder C sein darf. Solche Re- striktionen auf einem der Basisdatentypen können wir mit einer Simple-Type-Deklaration in einem XML-Schema definieren. Die Informationen, die unsere Beispielanwendung über ein Kundenkonto liefert, definiert Daten wie Kontonummer, Kontotyp, das aktuelle Saldo und einen eingeräumten Dispokre- dit. Das zu definierende -Schema für die Kontoinformationen hat also die folgen- de Struktur: Abbildung 2.3 Konto-Datenstruktur Diese Konto-Datenstruktur definieren wir durch ein komplexes Element . Die entsprechende Schemadefinition lautet: 30
  • 42. 2.1 XML-Schema           Zur Abbildung dieser Datenstruktur reichen eigentlich einige Elemente mit vordefinierten Typen wie  oder . Allerdings möchten wir gerne die einzelnen Elemente mit Einschränkungen versehen. Bei- spielsweise soll der Kontotyp nur eine der folgenden Zeichenketten STUDENT, BASIC o- T der PREMIUM enthalten. Daher definieren wir den Datentyp  als   und fügen ein -Element hinzu. Mit dem -Element können wir dann später die benötigten Einschränkungen auf dem angegebenen Basisdatentyp defi- nieren. Zunächst geben wir nur den Basisdatentyp für den Kontotyp mit  an.    Definition Sehen wir uns zunächst die allgemeine Definition einer -Deklaration an.        Wie im ersten Beispiel bereits gezeigt, können wir bei der Definition dieses Datentyps Ein- schränkungen auf einem Basisdatentyp über das -Element definieren. Statt eines vordefinierten Typs wie  ist hier auch die Erweiterung eines anderen benut- zerdefinierten Datentyps möglich. Im -Element werden durch Einfügen so- genannter Facets die Einschränkungen definiert. Im Folgenden wollen wir uns einige die- ser Facets näher anschauen. 2.1.2.5 Einschränkungen mit Facets In XML-Schema besitzt jeder einfache Datentyp eine Reihe von typischen Facets. Der Da- tentyp  z.B. besitzt die Facets   . Im Folgenden sehen wir uns beispielhaft einige dieser Fa- cets an. 31
  • 43. 2 Basistechnologien Enumeration Für die Einschränkung des Kontotyps können wir das -Facet verwenden. Die oben beschriebene Definition des Kontotyps sieht im Schemadokument jetzt folgenderma- ßen aus:        Die drei gültigen Werte für den Kontotyp werden also als Einschränkung des Basistyps  definiert. Eine gültige Schemainstanz kann in einem Element vom Typ   daher nur einen der angeführten Werte angeben. Reguläre Ausdrücke Eine weitere Einschränkung auf den Kontodaten gilt für die Kontonummer. Sie ist als ganzzahliges Attribut des Kontoelements folgendermaßen definiert:      Nun reicht die einfache Restriktion auf eine ganze Zahl nicht aus, üblicherweise sind Kon- tonummern in Deutschland maximal neunstellig und nie negativ. Die Kontonummer soll daher genau neun Stellen mit Ziffern zwischen 0 und 9 besitzen. Dies kann durch eine Ein- schränkung mit dem -Facet erreicht werden.         Das -Facet definiert beliebige reguläre Ausdrücke auf einem Basisdatentyp wie z.B.  oder . Es kann daher sehr flexibel zur Definition von Wertemengen genutzt werden. Die folgenden Beispiele sollen die vielseitige Nutzbarkeit dieser Ausdrü- cke illustrieren. 32
  • 44. 2.1 XML-Schema Tabelle 2.2 Reguläre Ausdrücke Regulärer Ausdruck Beispiel  Chapter 1  b, ab, aab, aaab …  b, ab  xb, yb, zb Wertebereiche Eine weitere gebräuchliche Einschränkung ist die Angabe eines Wertebereiches. Für den Dispokredit legen wir daher einen Wertebereich von 0–10000 Euro fest.       Mit diesen simplen Datentypen für Kontonummer, Kredit und Kontotyp ist unsere einfache Konto-Datenstruktur definiert. Hier noch einmal das gesamte Schemadokument in der Ü- bersicht:                                    33
  • 45. 2 Basistechnologien Es sei noch einmal auf die Möglichkeit hingewiesen, dass auch Attribute global definiert werden können. Das Attribut  für die Kontonummer wird hier inline definiert. Es könnte aber genauso auf oberster Ebene definiert werden.  Dies ermöglicht eine Wiederverwendung des Attributes, indem auf das global definierte Attribut mit dem -Tag verwiesen wird.  Eine gültige Schemainstanz zu unserem -Schemadokument sieht nun folgender- maßen aus:          34
  • 46. 2.1 XML-Schema 2.1.3 Vererbung Abbildung 2.4 Das Aktienportfolio Vererbung und Aufbau von Typhierarchien sind heute in objektorientierten Programmier- sprachen sehr verbreitet. Auch in XML-Schema können wir Datentypen definieren, die hierarchisch aufeinander aufbauen. Sehen wir uns dazu einen weiteren Aspekt unserer Bei- spielanwendung an. Bisher liefert unser Online-Banking-Service die Stammdaten und Kontoinformationen zu einem Kunden. Besitzt ein Kunde zusätzlich noch ein Aktienportfolio, wird auch dieses 35
  • 47. 2 Basistechnologien ausgegeben. Dabei enthält das – zugegeben sehr einfache – Portfolio Wertpapiere und Op- tionen sowie den Gesamtwert aller im Portfolio enthaltenen Wertpapiere und Optionen. Die Datentypen  und  in Abbildung 2.4 repräsentieren die Optionen und Wertpapiere. Eine Wertpapierposition besitzt grundsätzlich einen Namen, eine Wertpa- pierwährung sowie die Anzahl der vorhandenen Stücke und den daraus resultierenden Wert. Eine Option soll die gleichen Elemente besitzen mit dem Unterschied, dass für Opti- onen ein zusätzlicher Optionstyp  und ein Auslaufdatum  angegeben ist. Der Optionstyp gibt an, ob die Option auf einem Wertpapier, einer Währung oder einem Index (z.B. DAX, NASDAQ etc.) definiert ist. Da eine Option damit eine Spezialisierung eines Wertpapiers darstellt, bietet es sich an, dem Datentyp  die Elemente aus  zu vererben, indem wir  von  ableiten. Den Datentyp  für ein Wertpapier definieren wir wieder mit einem .         Um die Elemente dieses Datentyps für den Datentyp  wiederverwenden zu können, geben wir als Basis des Typs  den Datentyp  an. Ausgehend von dieser Basis kann dann die Erweiterung mit zusätzlichen Elementen erfolgen.           Im obigen Listing wurde mit dem Element angege- ben, dass dieser Datentyp eine Erweiterung des Datentyps  darstellt. Innerhalb eines -Elements können wie in einem normalen  weitere Elemen- te definiert werden. In unserem Fall sind dies die Elemente  und . Der Opti- onstyp  stellt dabei wiederum eine Enumeration dar.        36
  • 48. 2.1 XML-Schema 2.1.4 Kardinalitäten Nachdem nun die erforderlichen Datentypen für das Aktienportfolio definiert sind, muss noch definiert werden, wie diese im Portfolio verwendet werden. Abbildung 2.4 ist zu ent- nehmen, dass das Portfolio eine beliebige Anzahl an Optionen und Wertpapieren enthalten kann. Dies wird durch Angabe der Kardinalität  angegeben. In unserem Schemado- kument definieren wir daher jeweils ein Element für Optionen und Wertpapiere.     Durch die Angabe der Attribute  und  bei der Elementdeklaration geben wir eine Unter- und Obergrenze für die Anzahl der erlaubten Elemente an. Der Wert für  wird standardmäßig auf 1 gesetzt, falls das Attribut nicht angegeben wird. Nach Deklaration der Elemente für Wertpapiere und Optionen sieht das gesamte Schema- dokument für unser Aktienportfolio wie folgt aus:                                          37
  • 49. 2 Basistechnologien 2.1.5 Offene Schemas definieren Ein XML-Schema als Datenbeschreibung definieren wir häufig zu Beginn der Anwen- dungsentwicklung. Da wir als Schemaentwickler aber nicht zwangsläufig auch Hellseher sind, können wir unmöglich sofort ein Schema entwickeln, das allen später auftretenden Anforderungen gewachsen ist. Der Nutzer unseres Schemas sollte idealerweise die Mög- lichkeit haben, seine Instanzdokumente mit zusätzlichen Elementen und Attributen zu er- weitern, die nicht zum Schema gehören. Das Schema muss also ein offenes Design besit- zen. Für die Entwicklung offener Schemas eignen sich die im Folgenden beschriebenen Elemente  und , die im XML-Schema-Sprachgebrauch Wild- cards genannt werden. 2.1.5.1 Beliebige Elemente mit xs:any Das Element  definiert eine Art Platzhalter für ein beliebiges Element aus einem angegebenen Namespace. Stellen wir uns vor, wir möchten in einer XML- Dokumentinstanz zu unserem -Schema einen dritten, noch nicht genau definier- ten Wertpapiertyp erlauben. Dieser Typ kann durch ein -Element dargestellt werden. Im Schemadokument für das Portfolio würde das so aussehen.             Der Nutzer unseres Schemadokuments kann jetzt das -Element in seinem In- stanzdokument mit irgendeinem weiteren Element neben den schon definierten Options- und Wertpapierelementen erweitern. Die einzige Beschränkung ist, dass er für das zusätz- liche Element ebenfalls ein Schema angeben muss. Das könnte für ein zusätzliches Ele- ment , das ein Rentenpapier darstellt, so aussehen.                 38
  • 50. 2.1 XML-Schema               Damit das neue Element vom Schema-Validierer akzeptiert wird, geben wir hier also ein entsprechendes Schema unter dem Namespace  an. Doch nicht immer haben wir ein solches Dokument zur Verfügung. Wenn wir das neue Element ohne die Angabe des Schemadokuments einfügen wollen, müssen wir für das - Element das Attribut  setzen. Dieses Attribut steuert das Verhalten der Schema-Validierung für das -Element wie folgt.  "": Dies ist die Standardeinstellung. Das für  an- gegebene Element muss auf jeden Fall gegen ein Schema validiert werden. "": In diesem Fall wird validiert, wenn ein Schema gefunden werden kann, ansonsten wird dieses Element bei der Validierung übersprungen.   "": Hier wird das Element gar nicht validiert, daher kann ein völlig beliebiges Element ohne Schemaangabe deklariert werden. Die folgende Definition lässt also eine beliebige Anzahl Elemente aus irgendeinem Na- mespace zu.  2.1.5.2 Beliebige Attribute mit xs:anyAttribute Das Gegenstück zu  ist bei den Attributen die Wildcard . Es definiert eine Wildcard zur Ersetzung durch beliebige Attribute. Das Attribut   können wir hier analog benutzen, wie für  oben beschrieben. Ein Bei- spiel wäre die Definition beliebiger Attribute für unsere Kundendatensätze. Die Attribute werden in diesem Beispiel nicht validiert, da wir  angeben.             39
  • 51. 2 Basistechnologien Ein gültiges XML-Dokument für diesen Kundentyp ist beispielsweise das folgende.                  Hier definieren wir die Attribute  und  für unsere Kunden. Das erste Attribut de- finiert eine Kundengruppe und das zweite Attribut, ob es sich um einen Neukunden han- delt. 2.1.5.3 any-Erweiterungen auf Namespaces einschränken Die erlaubten Elemente und Attribute innerhalb einer - bzw. - Deklaration lassen sich auch feiner einstellen. Mit dem Attribut  können wir die innerhalb der Deklaration erlaubten Namespaces einschränken. Haben wir eine solche Ein- schränkung definiert, dann wird bei der Schema-Validierung überprüft, ob die hier vor- kommenden Elemente innerhalb der angegebenen Namespaces definiert sind. Der Wert von  ist eine Liste von URI-Bezeichnern der erlaubten Namespaces. Es gibt je- doch einige Schlüsselwörter, die ebenfalls angegeben werden können. : Bezeichnet den Target-Namespace des aktuellen Schemadoku- ments. : Nur lokale Elemente/Attribute ohne Namespace dürfen angegeben werden. : Ein beliebiger Namespace ist möglich. : Ein beliebiger Namespace mit Ausnahme des Target-Namespace darf ver- wendet werden. Die Werte  und  können dabei zusammen mit expliziten URI-Bezeichnern angegeben werden, während die Werte  und  als Ersatz für eine URI-Liste angegeben werden. 2.1.6 Namespaces importieren und referenzieren Bisher haben wir die einzelnen Datentypen unserer Anwendung isoliert voneinander be- trachtet: Kundendaten, Kontodaten und Aktienportfolio wurden in separaten Schemas de- finiert. Als Antwort soll unser Service die gesamten Daten in einem einzigen XML- Dokument liefern. Dazu wollen wir ein Schemadokument definieren, das alle bisher defi- nierten Schemas einbezieht, um die Struktur dieser Antwort festzulegen. 40
  • 52. 2.1 XML-Schema Was wir hier aufbauen wollen, ist also ein „Überschema“, das eine Komposition der bisher definierten Schemadokumente darstellt. Abbildung 2.5 zeigt eine Übersicht über ein sol- ches Schema. Abbildung 2.5 Schemadokument der Antwort des Online-Banking-Service Im Folgenden werden wir uns zwei verschiedene Wege anschauen, wie eine solche Kom- position von Schemas erstellt wird. 41
  • 53. 2 Basistechnologien 2.1.6.1 Komposition eines Schemas mit include Der einfachste Weg, um auf Elemente anderer Schemadokumente zuzugreifen, ist die Verwendung des Elements . Dieses Element erwartet lediglich die Angabe des Ortes, an dem sich das Teilschema befindet.  Mit dem folgenden Codefragment könnten wir unsere Teilschemas in das Antwortschema der Anwendung integrieren:       Elemente und Datentypen der angegebenen Schemas können wir nun genauso verwenden, als hätten wir alle Elemente in einem einzigen Schemadokument definiert. Diese Definition funktioniert jedoch nur, wenn alle Dokumente den gleichen Namespace verwenden, nämlich den des Gesamtschemas http://jaxb.transparent/response. Daher er- wartet das -Element auch keine Angabe eines eigenen Namespace für das ein- zufügende Schemadokument. Für einfache Szenarien ist die Verwendung von  ausreichend. Schemadokumente mit verschiedenen Namespaces müssen allerdings über den -Befehl zusammenge- fügt werden. 2.1.6.2 Komposition eines Schemas mit import In XML-Schema bietet uns das -Tag die Möglichkeit, ein Schemadokument aus Elementen und Datentypen anderer Schemadokumente zusammenzusetzen. Dabei werden die Teilschemas im Gesamtschema referenziert. Auf diese Weise stehen im Gesamtschema alle Elemente und Datentypen der Teilschemas zur Verfügung.   Für unsere Anwendung geben wir daher je ein -Element für Kunden-, Konto- und Portfolioschema an. Neben dem Namespace, der importiert werden soll, geben wir auch den Ort des Schemadokumentes an.       Das folgende Schemadokument zeigt, wie wir die importierten Elemente aus den Teil- schemas nutzen können. Dazu legen wir im Element je ein Präfix für die impor- 42
  • 54. 2.1 XML-Schema tierten Namespaces an. Über diese Präfixe können wir dann die importierten Typen refe- renzieren, z.B. , . Das Dokument definiert also ein Element , das einen Kundendatensatz, Kontoinformationen und ein Portfolio enthält. Die Reihenfolge der Elemente wird dabei wieder über ein Element festgelegt.                       Hinweis - und -Elemente müssen immer vor den Typdefinitionen und Elementde- klarationen eines Schemadokuments stehen. 2.1.7 Eindeutigkeit durch ID und IDREF Das Konzept der Eindeutigkeit von Datensätzen ist aus dem Bereich der Datenbanken hin- länglich bekannt. Beim Erstellen eines Datenbankschemas verwenden wir Schlüsselattri- bute, mit denen wir einen Datensatz eindeutig referenzieren können. Auch in XML- Dokumenten gibt es die Möglichkeit, die Eindeutigkeit von Datensätzen zu gewährleisten. Im DTD-Format gibt es dafür die Datentypen  und , die nur auf Attributebene de- finierbar sind. Die W3C XML-Schemaspezifikation hat diese Datentypen sozusagen ge- erbt, allerdings mit dem Unterschied, dass wir dort sowohl Attribute und Elemente mit den Datentypen  und  definieren können. Bevor wir diese Elemente einzeln näher beschreiben, hier noch einige Eigenschaften, die sie gemeinsam besitzen: Ihr Wertebereich ist der gleiche wie der des Datentyps , d.h., Ziffern am Anfang und das Auftreten von Leerzeichen sind innerhalb der Elemente  und  verboten. Nachteil hierbei: Häufig gibt es Nummern, z.B. Kontonummern, die von Na- tur aus eindeutig sind, diese können allerdings nicht direkt als  verwendet werden. Die Werte von  und  müssen global eindeutig sein, d.h., ein ID-Wert darf nicht im selben Dokument zur Identifikation von zwei Elementen verwendet werden. 43
  • 55. 2 Basistechnologien xs:ID Ein Element oder Attribut vom Typ  stellt einen eindeutigen Bezeichner für das zu- gehörige Element dar. Das folgende Schemafragment definiert ein Element  mit einem Unterelement , das einen Kunden eindeutig identifiziert.          Die folgende Tabelle zeigt dazu jeweils eine gültige und eine ungültige Schemainstanz. Tabelle 2.3 Schemainstanzen mit xs:ID Gültiger Inhalt Ungültiger Inhalt   John John         Johnny John       xs:IDREF Elemente oder Attribute dieses Typs definieren eine Referenz auf ein Element, das wieder- um eine ID mittels  definiert. Im Folgenden definieren wir daher ein Schemafrag- ment, das den eben definierten Kunden um eine Liste mit Freunden erweitert. Diese Freunde sind wiederum vom Typ  und werden durch die ID-Referenz referen- ziert.            Die folgende Tabelle zeigt dazu jeweils eine gültige und eine ungültige Schemainstanz. 44
  • 56. 2.1 XML-Schema Tabelle 2.4 Schemainstanzen mit xs:IDREF Gültiger Inhalt Ungültiger Inhalt       Johnny Johnny John John           Johnny Ben   2.1.8 Dokumentation mit Annotationen Die in unseren Beispielen immer wieder verwendeten XML-Schemadokumente des virtu- ellen Online-Banking-Service sind in diesem Kapitel ausführlich beschrieben. Wie be- kommen aber nun Entwickler, welche die hier definierten XML-Formate in ihren Anwen- dungen einsetzen wollen, Informationen über den Aufbau der gelieferten Daten? Zum ei- nen könnten wird die Schemadokumente veröffentlichen. Dies würde jedoch nur Informa- tionen über die technische XML-Struktur liefern. Es wäre sehr praktisch, wenn wir das XML-Format auch mit weiteren Informationen versehen könnten: Beispielsweise mit Kommentaren, aber auch mit Informationen, die eine spätere technische Verarbeitung der XML-Dokumente beeinflussen. Auch dies kann in ein XML-Schemadokument integriert werden. Über sogenannte Annotationen können wir Dokumentation für Mensch und Ma- schine in ein Schema einfügen.       Das -Element erlaubt das Einfügen von natürlichsprachlicher Dokumentation über das -Element. Im Element  dagegen werden Informationen für Programme angegeben, die ein Schema verarbeiten. Annotationen können allerdings nicht an jeder beliebigen Stelle in ein Schemadokument eingefügt werden. Gültige Orte für Annotationen sind: vor oder nach einer globalen Komponente bei lokalen Komponenten (z.B. innerhalb eines Elements) nur am Anfang      45
  • 57. 2 Basistechnologien         Das -Element werden wir später bei der Verwendung von JAXB noch häufi- ger benötigen. Für JAXB können wir nämlich im -Tag einer Annotation benutzer- definierte Konfigurationseinstellungen vornehmen, welche die Bindung eines Java- Datenmodells an ein XML-Schema näher definieren. Im obigen Beispiel ist bereits eine solche Einstellung dargestellt. 2.1.9 Das fertige Beispielschema In den vorangegangenen Abschnitten haben wir alle nötigen Datenstrukturen für den in unseren Beispielen immer wieder verwendeten Online-Banking-Service durch XML- Schemadokumente definiert. Dabei sind wir ausführlich auf die für uns wichtigen Elemen- te von XML-Schema eingegangen. An dieser Stelle wollen wir noch einmal alle Schema- dokumente auflisten. Diese Auflistung wird uns während der restlichen Kapitel als Refe- renz dienen. 2.1.9.1 Das response-Schemadokument                       2.1.9.2 Das customer-Schemadokument      46
  • 58. 2.1 XML-Schema                     2.1.9.3 Das account-Schemadokument                                   2.1.9.4 Das portfolio-Schemadokument      47
  • 59. 2 Basistechnologien                                      2.2 XPath Der Begriff XPath lässt uns sicher an Dateisysteme denken, die Pfade verwenden, um Da- teien zu lokalisieren. XPath verfolgt ein ganz ähnliches Prinzip, nur dass mit den Pfaden hier Knoten in XML-Dokumenten lokalisiert werden. Denn oft stehen wir vor Fragen wie: „Wo befindet sich das Element X mit der Eigenschaft Y in den 100 Datensätzen meines XML-Dokuments?“ Eine Möglichkeit wäre, mit einer der XML-APIs das gesamte XML-Dokument zu traver- sieren, bis wir auf den gewünschten Knoten stoßen. Das ist allerdings sehr mühsam und in einer Welt von 1001 APIs auch reine Zeitverschwendung. XPath bietet nämlich eine recht intuitive und vor allem mächtige Schnittstelle zur Beschreibung von Elementen und Wer- ten in XML-Dokumenten. Daher ist XPath mittlerweile in einer ganzen Reihe von XML- APIs präsent. So finden wir XPath in den Standards XSLT, XML-Schema und XQuery 5 wieder – und auch in der JAXB. In den folgenden Seiten wollen wir einen kleinen Über- 5 http://www.w3.org/XML/Query 48
  • 60. 2.2 XPath blick über den Standard XPath geben. In JAXB werden nämlich XPath-Ausdrücke bei der Konfiguration der Datenbindung von XML nach Java verwendet. Wie seine großen Geschwister XML und XML-Schema ist auch XPath ein Standard des Webkonsortiums W3C 6 . Mit XPath können wir in deskriptiver Form Informationen über XML-Elemente in einem Dokument abfragen („Wie viele Elemente vom Typ B?“) als auch die Inhalte der Elemente/Attribute selbst („Textinhalt von Element B?“). In dieser Hinsicht besitzt XPath eine gewisse Ähnlichkeit zu den -Statements in SQL, mit denen Inhalte einer Tabelle abgefragt werden können. XPath alleine ist jedoch bei weitem nicht so mächtig wie SQL – dessen Mächtigkeit erreicht vielleicht die Abfragesprache XQuery, die ihrerseits wiederum auf XPath-Ausdrücken basiert. Im folgenden Abschnitt beschränken wir uns auf die Konzepte von XPath, die wir für die sinnvolle Verwendung in JAXB kennen und anwenden müssen. 2.2.1 Die XPath-Sicht auf XML Ein XML-Dokument wird in XPath als eine Baumstruktur angesehen, die aus miteinander verknüpften Knoten besteht. Knoten können aus XML-Konstrukten wie Elementen, Attri- buten und Namensräumen bestehen. Die Knoten wiederum besitzen Werte, die als Text dargestellt sind. Ein Beispiel:             Im obigen Dokument gibt es die folgenden Knoten: Dokumentknoten:  bildet das Wurzelelement des Dokuments Elementknoten: , Wert  Attributknoten: , Wert  Namespace-Knoten: , Wert  Die Knoten besitzen Beziehungen untereinander, wie wir sie aus einem Stammbaum ken- nen. Der Knoten  besitzt z.B. die Kinder (children nodes) , ,  und . Er selbst stellt den Elternteil (parent node) für diese Knoten dar. Außerdem gibt es noch die Geschwisterknoten (sibling nodes), die im Fall des Knotens  z.B. ,  und  sind. Generationsübergreifend gibt es dann 6 http://www.w3.org 49
  • 61. 2 Basistechnologien noch Vorfahren (node ancestors}, das sind für den -Knoten  und  . Umgekehrt sind die Knoten  und  Nachfahren des - Knotens. Mit dieser Sicht auf ein XML-Dokument wollen wir uns jetzt den XPath- Ausdrücken zuwenden. 2.2.2 XPath-Ausdrücke verwenden Mit Xpath-Ausdrücken können wir Knoten in einem solchen XML-Baum beschreiben. Die Syntax von Xpath-Ausdrücken ähnelt der Syntax zur Beschreibung von Dateien in den gängigen Dateisystemen. Gültige XPath-Ausdrücke für das obige Dokument sind bei- spielsweise die folgenden:    Auch wenn die Syntax zunächst vertraut scheint, gibt es einige semantische Unterschiede zwischen der Lokalisierung von XML-Knoten in einem XML-Dokument und der Lokali- sierung von Dateien im Dateisystem. Im ersten Teil eines XPath-Ausdrucks wählen wir einen oder mehrere Knoten aus dem XML-Dokument aus. Knotenauswahl Die folgende Tabelle zeigt die Elemente der XPath-Syntax, die uns für die Knotenselekti- on zur Verfügung stehen. Tabelle 2.5 Elemente der XPath-Syntax Element Bedeutung Beispiel  Selektiert alle Kindknoten des  liefert die Knoten angegebenen Knotens , ,  und .  Bezeichnet den Wurzelknoten  liefert den des Dokuments. Wurzelknoten zurück. Stellt im- mer einen absoluten Pfad dar.  Selektiert alle passenden Knoten  liefert alle Adress- unabhängig von ihrem Ort. knoten, die unterhalb des aktuel- len Knotens liegen.  Bezeichnet den aktuellen Kno- . liefert z.B. , falls dies ten. der aktuelle Knoten ist.  Bezeichnet den Elternknoten  ist wie- des aktuellen Knotens der der -Knoten.  Selektiert ein Attribut.  liefert die Hausnummer zurück. 50
  • 62. 2.2 XPath Bedingungen formulieren mit Prädikaten Die oben dargestellten Syntaxelemente liefern alle Knoten mit einem bestimmten Namen zurück, doch in manchen Fällen wollen wir einen Knoten präziser beschreiben – bei- spielsweise wollen wir nur den ersten Knoten einer Liste abfragen oder nur Knoten, auf die eine bestimmte Bedingung zutrifft. Mit sogenannten Prädikaten können wir aus einer Menge von Knoten eine Teilmenge selektieren. Prädikate werden durch einen booleschen Ausdruck in eckigen Klammern definiert. Zurückgeliefert werden dann alle Knoten, auf die der boolesche Ausdruck zutrifft. Tabelle 2.6 XPath-Ausdrücke mit Prädikaten Ausdruck Bedeutung  Liefert den ersten Kunden aus einer Kundenliste.  Liefert den Kunden mit der E-Mail-Adresse   Liefert den Straßennamen mit dem Hausnummer- Attribut 44 zurück. In unserem Fall „BeerStreet“.  Liefert die Kunden mit Postleitzahlen größer 4000 zurück. Wildcards Wildcards können angegeben werden, wenn wir den genauen Elementnamen nicht kennen oder einfach alle Elemente, Attribute oder sonstige Knoten auswählen wollen. Tabelle 2.7 Wildcard-Ausdrücke Wildcard Bedeutung  Listet alle Adresselemente.  Listet alle Attributknoten im aktuellen Pfad.  Listet alle beliebigen Knoten, dazu gehören auch Namespace-Angaben, Kommentare etc. 2.2.3 Beispiele Da wir immer am schnellsten durch konkrete Beispiele lernen, führen wir hier die gängigs- ten XPath-Ausdrücke auf, die wir für die Arbeit mit JAXB benötigen werden. Die Ausdrü- cke beziehen sich dabei auf das folgende XML-Schemadokument, denn auch Schemas sind wiederum XML-Dokumente, die wir im Verlauf des Buches sogar hauptsächlich be- arbeiten werden. 51
  • 63. 2 Basistechnologien Das Schemadokument                         Auswahl des Wurzelknotens XPath-Ausdruck:  (absoluter Pfad) Selektion:      Auswahl aller global definierten, komplexen Typen XPath-Ausdruck:  (absoluter Pfad) Selektion:           Auswahl aller Elemente XPath-Ausdruck:  (relativer Pfad) Selektion: 52
  • 64. 2.2 XPath                        Auswahl des Elements zipcode XPath-Ausdruck:  (relativer Pfad) Selektion:              2.2.4 XPath in Java Bisher haben wir uns XPath als W3C-Standard angesehen. Der Standard ist zunächst un- abhängig von einer bestimmten Integration in eine Programmiersprache. Wie sieht es nun aus, wenn wir XPath in einem Java-Programm einsetzen wollen? Im Java-Umfeld haben wir eine ganze Reihe von XPath-Implementierungen zur Auswahl. Einige Beispiele sind Xalan 7 , Saxon 8 und Jaxen 9 , die allesamt Open-Source-Projekte darstellen. Seit Java 5 stellt aber auch Sun mit der JAXP 1.3 eine XPath-API bereit, die den Vorteil besitzt, dass 7 http://xalan.apache.org 8 http://saxon.sourceforge.net 9 http://www.jaxen.org 53
  • 65. 2 Basistechnologien wir keine zusätzlichen Bibliotheken benötigen, um XPath-Ausdrücke zu benutzen. Daher stellen wir hier nur diese Variante vor. Eine Baumsicht erstellen Um XPath-Ausdrücke in Java anzuwenden, benötigen wir zuerst eine Java-Sicht auf unser XML-Dokument. Am einfachsten erreichen wir dies durch Parsen des Dokuments in eine DOM-Struktur, wie im folgenden Beispiel dargestellt.      Hier wird also das oben gezeigte XML-Schemadokument in ein Objekt vom Typ   überführt, das unseren XML-Baum darstellt. Auf diese Baumstruktur können wir jetzt XPath-Ausdrücke anwenden. XPath-Abfragen erzeugen und ausführen Für eine simple XPath-Abfrage mit JAXP 1.3 genügt der folgende Vierzeiler.      Wir erzeugen also auch hier eine Factory, die uns ein XPath-Abfrageobjekt bereitstellt. Diesem Objekt übergeben wir dann das XML-Dokument, den XPath-Ausdruck sowie den Typ, den wir als Rückgabe erwarten. Die Methode  wertet die Abfrage aus und gibt die Ergebnisse zurück. In diesem Fall besteht das Ergebnis aus dem Wurzelknoten. Namespace-Präfixe auflösen Eine Zeile haben wir im vorigen Beispiel noch nicht beachtet.  Die Methode  übergibt eine Kontextklasse, die eventuell im Do- kument vorhandene Namespace-Präfixe, wie im obigen Beispiel z.B. das Präfix , in den korrekten Namespace auflöst bzw. umgekehrt. Eine solche Klasse erstellen wir, indem wir das Interface  implementieren. Ein Beispiel für die Implementierung einer solchen Kontextklasse sehen wir hier.       54
  • 66. 2.3 ANT                        Ohne einen solchen Namespace-Kontext kann die XPath-Implementierung keine Na- mespace-übergreifenden Dokumente auswerten. 2.3 ANT ANT ist eine Java-basierte XML-Sprache zur Erstellung von Build-Skripten. Ein Build- Skript nimmt dem Entwickler die alltäglichen Aufgaben wie Kompilieren, Packen und Verteilen von Quellcode ab. Damit lässt sich der Build-Prozess, also der Prozess von der Kompilation des Quellcodes bis zum Deployment und Test der gesamten Anwendung vollständig automatisieren. Vielleicht denken einige jetzt an das -Tool in Unix- Umgebungen. ANT ist genau das, nur ist es nicht an eine bestimmte Plattform gebunden, da es vollständig auf Java basiert. Was hat das nun alles mit JAXB zu tun? Nun, eine Bindung von XML nach Java wird bei JAXB durch die Generierung von Java-Klassen realisiert. Im umgekehrten Fall, der Bin- dung von Java nach XML, kann das zugehörige XML-Schema generiert werden. Diese Generierung passiert zumeist vor der Laufzeit unserer Anwendung und gehört damit zum Build-Prozess. Um nicht jedes Mal mühsam die Generierung durch Aufruf der JAXB- Kommandos in einer Shell anzustoßen, nutzen wir ein ANT-Plugin, das diese Arbeit für uns übernimmt. Aber zunächst sehen wir uns die allgemeine Funktionsweise von ANT an. 2.3.1 ANT-Übersicht Ähnlich wie bei anderen Build-Werkzeugen wird auch bei ANT ein Skript aufgerufen, das den gesamten Build-Prozess abarbeitet. Dieses Skript wird entsprechend auch Build-Skript 55
  • 67. 2 Basistechnologien genannt und ist, wie könnte es anders sein, in XML geschrieben. Neben dem Build-Skript sollten wir noch einige andere Begriffe kennen: Projekt: Jedes Build-Skript definiert ein Projekt, das den Build-Prozess für eine be- stimmte Anwendung darstellt. Das Projekt definiert ein Standard-Target (Default Tar- get). Falls kein anderes Target beim Aufruf angegeben ist, wird dieses Target aufgeru- fen. Target: Ein Projekt enthält also mindestens ein Target, das beim Ausführen des Build- Skriptes gestartet wird. Ein Target compile kann beispielsweise die Kompilierung des Quellcodes übernehmen, ein anderes Target deploy den kompilierten Quellcode in ein JAR-Archiv verpacken. Targets sind so konfiguriert, dass sie sich untereinander aufru- fen. So können wir Abhängigkeiten zwischen den Targets definieren, etwa dass das Target deploy von dem Target compile abhängt. So kann z.B. das Verpacken des Codes erst nach einer vorherigen Kompilation der Quellen stattfinden. Man sagt hier „die Verpackung ist abhängig von der Kompilierung“. Dabei werden die einzelnen Targets möglichst nur ausgeführt, wenn sich relevante Quellen geändert haben. Task: Die Funktionen, die innerhalb eines Targets aufgerufen werden, sind in Tasks definiert. Ein Task kann z.B. den Java-Compiler aufrufen, den JAXB Schema- Compiler oder den Schema-Generator. Es gibt viele bereits in ANT eingebaute Tasks, die von einem Target aus aufgerufen werden können. Benutzerdefinierte Tasks, wie z.B. die JAXB Tasks, müssen erst im Build-Skript definiert werden, bevor sie benutzt werden können. 2.3.2 Installation und Aufruf ANT kann entweder im Binärformat oder als Quellcode von der ANT-Webseite 10 herun- tergeladen werden. Der Einfachheit halber werden wir im Folgenden die Existenz eines fertig kompilierten Binärpakets voraussetzen. Dies liegt zumeist in gepackter Form z.B. als ZIP-Archiv vor. Dieses ZIP-Archiv besitzt die folgende Verzeichnisstruktur: bin: Enthält die ANT-Kommandozeilenskripte. docs: Umfangreiches Benutzerhandbuch und API-Dokumentation etc: Enthält XSL-Erweiterungen. lib: Optionale ANT-Tasks und Abhängigkeiten Installation Unabhängig vom verwendeten Betriebssystem sind zur Installation von ANT die folgen- den Schritte notwendig: 1. Entpacken des ANT-Archivs in ein beliebiges Verzeichnis. 2. Das Unterverzeichnis bin in den Pfad aufnehmen. 10 http://ant.apache.org 56
  • 68. 2.3 ANT 3. Eine Umgebungsvariable mit dem Namen ANT_HOME erstellen, die auf das Installati- onsverzeichnis zeigt. 4. Falls noch nicht vorhanden, eine Umgebungsvariable JAVA_HOME erstellen, die auf das Installationsverzeichnis des JDK zeigt. Aufruf Per Kommandozeile können wir nun den ANT-Befehl aufrufen. Die folgende Syntax führt das unter [] angegebene Target des Projekts in der Datei build.xml aus.  Wenn das Build-Skript den Standardnamen  trägt, kann der Parameter  auch weggelassen werden. 2.3.3 Häufig verwendete Elemente 2.3.3.1 Properties definieren Es ist häufig sinnvoll, in einem Build-Skript Variablen als Platzhalter zu definieren, da z.B. Verzeichnisnamen an vielen Stellen im Skript benötigt werden. Um Redundanz zu vermeiden, können diese Verzeichnisnamen mit einer -Deklaration als Variablen in einem ANT-Skript definiert werden:  Dieses Beispiel definiert eine Property , die auf das Verzeichnis  zeigt. Im gesamten Skript kann diese Variable nun durch Angabe von  referenziert wer- den. 2.3.3.2 javac-Task Um Quellcode zu kompilieren, existiert in ANT der -Task, dem ein Quell- und ein Zielverzeichnis sowie ein Klassenpfad übergeben werden. Der Task kompiliert Java- Quellcode und legt diesen im Zielverzeichnis ab.   2.3.3.3 Der Klassenpfad Für einige Tasks, wie oben bei , muss in ANT ein Klassenpfad definiert werden. Da- für kann zum einen explizit das -Element mit einem verschachtelten  Element benutzt werden: 57
  • 69. 2 Basistechnologien    Eine andere Möglichkeit ist die Referenzierung eines existierenden Pfades. Das folgende Beispiel legt einen Pfad mit dem -Element an und verweist bei der Definition des Klassenpfades auf den vorher definierten Pfad. Dadurch kann die redundante Definition von Klassenpfaden vermieden werden:      2.3.4 Benutzerdefinierte Tasks Eines der mächtigen Merkmale von ANT ist, dass wir die verfügbaren Elemente durch ei- gene Task-Implementierungen nach dem Baukastenprinzip erweitern können. Um ANT mit benutzerdefinierten Tasks zu erweitern, muss der betreffende Task im aktuellen Pro- jekt erst definiert werden. Dies kann über die folgenden zwei Definitionen geschehen:         Bei der Task-Definition werden ein Name für den Task, der vollständige Klassenname der Implementierung und der zugehörige Klassenpfad angegeben. Im obigen Beispiel wird einmal ein Klassenpfad innerhalb der Definition angelegt und beim anderen Mal ein exis- tierender Pfad verwendet. Damit ist der Task vollständig definiert und kann im weiteren Verlauf unter dem angegebenen Namen verwendet werden. 2.3.5 xjc und schemaGen Tasks Für die komfortable Integration der JAXB-Funktionalität in einen ANT-basierten Build- Prozess gibt es zwei Tasks: den -Task und den -Task. Ersterer integriert den Schema-Compiler und Letzterer den Schema-Generator von JAXB in ANT. Wie diese Tasks definiert werden, ist in der Referenz genau beschrieben. Sie werden bei der Refe- renzimplementierung der JAXB in einem eigenen JAR-Archiv  mitgelie- fert. Sehen wir uns daher ein Beispiel an, das diese Task-Definition in einem Gesamtkon- text verwendet. 58
  • 70. 2.3 ANT 2.3.6 Ein Beispiel                                      Das obige Listing zeigt ein Projekt mit dem Namen , das ein Standard-Target  definiert. Dieses Target automatisiert den gesamten Build-Prozess vom Aufruf des Schema-Compilers über das Kompilieren der Anwendung bis zum Archivieren der An- wendung in einer JAR-Datei. Dabei sind die Targets über Abhängigkeiten per  verknüpft, d.h., zuerst wird das -Target aufgerufen, dann  und erst zuletzt . Zu Beginn des Skripts werden einige Variablen definiert, die Verzeichnisse darstel- len, die in den einzelnen Targets benutzt werden. Außerdem wird der Klassenpfad zu den JAXB-Bibliotheken global definiert, da der Java-Compiler und Schema-Compiler beide diesen Pfad benötigen. Das Skript führt nun die folgenden Aktionen aus: Generieren der JAXB-Java Beans aus dem Schema in das Verzeichnis  Kompilieren der JAXB-Klassen und des übrigen Anwendungscodes in das Verzeichnis  59
  • 71. 2 Basistechnologien Verpacken der kompilierten Klassen in ein JAR-Archiv namens  Als Datei  abgespeichert, lässt sich dieses Skript nun von der Kommandozeile mit dem folgenden Befehl aufrufen:  Nutzer der weitverbreiteten integrierten Entwicklungsumgebung Eclipse können solche Build-Skripte natürlich auch bequem mit der in Eclipse integrierten ANT-Unterstützung starten. Für weiterführende Informationen über die Verwendung von ANT sei auf die sehr ausführ- liche Dokumentation in der ANT-Distribution verwiesen. Der Aufruf des Schema- Generators funktioniert ähnlich. Hier nur ein kurzes Listing mit dem entsprechenden Auf- ruf.                  60
  • 72. 3 Hallo JAXB! In den vorangegangenen Kapiteln haben wir uns mit den Voraussetzungen und den theore- tischen Grundlagen zur JAXB beschäftigt. Jetzt wenden wir uns endlich der Praxis zu. Dieses Kapitel zeigt, wie wir eine funktionierende JAXB-Entwicklungsumgebung aufset- zen, mit der wir die Beispiele in dem folgenden Programmiertutorial erstellen und nach- vollziehen können. Anhand des allseits bekannten „Hallo Welt!“-Beispiels probieren wir diese Entwicklungsumgebung gleich aus. Das „Hallo Welt!“-Beispiel wird uns gleichzei- tig einen ersten Überblick über die Vorgehensweise bei der XML-Java-Datenbindung mit JAXB geben. Die dabei verwendeten API-Komponenten sind im folgenden Programmier- tutorial detailliert erklärt. Wir werden daher in diesem ersten Beispiel nicht näher darauf eingehen, sondern uns nur auf einen Round-Trip, also eine Bindung von Java nach XML und zurück, konzentrieren. 3.1 Systemvoraussetzungen Bevor wir loslegen können, brauchen wir einige Softwarepakete auf unserem System: Java Standard Edition 5: JAXB 2.0 benötigt die Java Standard Edition 5 (JSE5) oder besser, da JAXB intensiven Gebrauch von den in Java 5 eingeführten Annotationen und Generics macht. Die aktuelle Version der JSE5 ist unter der folgenden URL erhält- lich: http://java.sun.com/javase/downloads/index.jsp Apache ANT: Für den Schema-Compiler und den Schema-Generator existiert in der JAXB-Referenzimplementierung eine Unterstützung durch ANT-Tasks. Diese müssen in einem Projekt nicht zwangsläufig genutzt werden, sind aber wesentlich komfortabler als die Kommandozeilenvariante. Daher ist es ratsam, in der JAXB- Entwicklungsumgebung mit ANT zu arbeiten. ANT ist erhältlich unter der folgenden URL: http://ant.apache.org/. Wir haben dem Thema ANT im vorigen Kapitel eine kurze Einführung gewidmet. Dort ist auch die Installation ausführlich beschrieben. JAXB Reference Implementation: In diesem Buch setzen wir auf der zurzeit aktuellen JAXB Reference Implementation 2.0.2 von Sun auf. Diese bietet die momentan voll- 61
  • 73. 3 Hallo JAXB! ständigste Implementierung der JAXB-Spezifikation und ist erhältlich unter der fol- genden URL: https://jaxb.dev.java.net/ Eine alternative JAXB-Implementierung gibt es von Apache mit JaxMe2, die unter un- ten stehender URL bezogen werden kann. Hier kann es im Detail zu Unterschieden zwischen den in diesem Buch beschriebenen Funktionalitäten und denen der durch die JaxMe2-Implementierung gebotenen Funktionalität. Die Implementierung erhalten Sie unter http://ws.apache.org/jaxme/ 3.2 Die Entwicklungsumgebung einrichten 3.2.1 JAXB-Referenzimplementierung installieren Nachdem wir die aktuelle Referenzimplementierung von Sun bezogen haben, sollten wir eine Datei in der Form  in Händen halten, metaphorisch wohlgemerkt. Dieses JAR-Archiv enthält die komplette JAXB-Distribution. Installiert wird dieses Paket mit einem Aufruf von der Kommandozeile, z.B.  Nach Akzeptieren der Lizenzvereinbarung wird der Inhalt in die folgende Verzeichnis- struktur des aktuellen Verzeichnisses entpackt. jaxb-ri-20060607 bin: Enthält die Kommandozeilenskripte für Schema-Compiler/-Generator docs: Dokumentation und Javadoc der API lib: JAXB-Bibliotheken und Quellcode-Archive samples: Beispielanwendungen mit JAXB 3.2.2 Die JAXB-Bibliotheken einbinden Für die Arbeit mit der JAXB-Referenzimplementierung müssen sich die JAR-Bibliotheken aus dem lib-Verzeichnis der Installation auf dem Klassenpfad unserer Anwendungen be- finden. Die JAXB-Referenzimplementierung enthält die folgenden JAR-Bibliotheken. jaxb-api.jar: API-Klassen der JAXB-Spezifikation jaxb-impl.jar: Klassen der JAXB-Referenzimplementierung jsr173_1.0_api.jar: XML Streaming API, z.B.  activation.jar: Abhängigkeit zur Java Beans Activation API jaxb-xjc.jar: XJC Schema-Compiler und Schema-Generator jaxb1-impl.jar: JAXB 1.0-Kompatibilitätsklassen Für unsere Beispielanwendungen benötigen wir die folgenden Bibliotheken zur Laufzeit. 62
  • 74. 3.2 Die Entwicklungsumgebung einrichten jaxb-api.jar jaxb-impl.jar jsr173_1.0_api.jar activation.jar Um Klassen und Schemas zu generieren, benötigen wir die folgende Bibliothek zur Com- pile-Zeit auf dem Klassenpfad. jaxb-xjc.jar Für Anwendungen, die auf der Version 1.0 der JAXB aufsetzen, muss noch die Bibliothek jaxb1-impl.jar hinzugefügt werden. Wir fügen also im Standardfall die ersten fünf Bibliotheken der Umgebungsvariablen CLASSPATH hinzu. Damit sind wir auf der sicheren Seite. Hinweis Wenn wir mit einer Entwicklungsumgebung wie Eclipse arbeiten, ist es hilfreich, die ebenfalls im lib-Verzeichnis enthaltenen Quellcode-Archive auf den Klassenpfad zu legen. Dadurch können bequem die Javadoc-Kommentare zu den einzelnen Komponenten eingesehen werden. 3.2.3 Die Struktur des Beispielprojekts Wir empfehlen sehr, die in diesem Buch enthaltenen Beispiele praktisch auszuprobieren. Der dafür erforderliche Quellcode kann in Form eines Beispielprojekts auf der Webseite dieses Buchs heruntergeladen werden. An dieser Stelle sei daher kurz der Aufbau des Bei- spielprojekts dargestellt. Die Codebeispiele sind nach Kapiteln in einzelne Pakete unter- teilt. Unter den Kapitelpaketen sind die Beispiele zu einzelnen Abschnitte in eigenen Un- terpaketen zusammengefasst. Das Java-Paket, in dem sich der Quelltext befindet, ist im Quelltextauszug stets mit abgedruckt. Die Ordner des Beispielprojekts besitzen den folgenden Inhalt. src: Quellcode nach Kapiteln unterteilt src-gen: durch den Schema-Compiler generierte Klassen lib: JAXB-Bibliotheken schema: Verzeichnis mit XML-Schemas und XML-Dokumenten schema-gen: durch den Schema-Generator erzeugte XML-Schemas build.xml: Build-Skript für das Banking-Service-Schema buildHelloWorld.xml: Build-Skript für das „Hallo Welt!“-Beispiel Hinweis Eclipse-Nutzer können das Beispielprojekt ganz einfach importieren und direkt verwenden, ohne den Klassenpfad verändern zu müssen. Auch ist hier die ANT-Unterstützung schon ein- gebaut, so dass dem Entwickler einiges an Konfiguration abgenommen wird. 63
  • 75. 3 Hallo JAXB! 3.3 Am Anfang steht immer: Hallo Welt! Nachdem die Entwicklungsumgebung jetzt rein technisch lauffähig ist, können wir unser erstes JAXB-Beispiel in Angriff nehmen. Dazu bedienen wir uns des Klassikers der In- formatikliteratur, nämlich einer Variante des „Hallo Welt!“-Beispiels. Es dreht sich bei diesem Beispiel schlicht und ergreifend um ein XML-Dokument, das ein  Element mit einer entsprechenden Nachricht  enthält. Anhand dieses Beispiels werden wir die möglichen Szenarien der Datenbindung durchspielen. Zuerst werden wir eine existierende Java Bean an ein XML-Schema binden. Danach gehen wir den umge- kehrten Weg und erzeugen aus einem bestehenden XML-Schema eine entsprechende Java- Repräsentation. Um den Schema-Compiler bzw. Schema-Generator aufzurufen, bedienen wir uns der entsprechenden ANT-Tasks. 3.3.1 Der Weg von Java zu XML Nehmen wir einmal an, wir besitzen als Ausgangspunkt eine simple Java Bean, die wir gerne an ein XML-Datenformat binden wollen. Die Java Bean heißt  und hat die folgende Struktur.               Das ist so weit nichts Ungewöhnliches. Um diese Java Bean an ein XML-Element binden zu können, müssen wir mit JAXB nur eine einzige Änderung machen. Durch Hinzufügen einer Annotation  lassen wir JAXB wissen, dass es sich bei dieser Klas- se um das Wurzelelement eines XML-Dokuments handelt. Die Klasse sieht jetzt folgen- dermaßen aus.      64
  • 76. 3.3 Am Anfang steht immer: Hallo Welt!           Das ist auch schon alles, was wir verändern müssen. Für die Eigenschaften der Java Bean und die später erzeugten Namen im XML-Dokument vertrauen wir auf die Standardein- stellungen der JAXB-Implementierung. Mit dem folgenden kleinen Beispielprogramm er- zeugen wir jetzt aus einem -Objekt ein entsprechendes XML-Dokument.                   Nachdem wir einige Initialisierungen vorgenommen haben, erzeugen wir hier einfach eine neue Instanz der Klasse , die als Nachricht den Wert „Hello world!“ be- kommt. Diese Instanz übergeben wir einer -Instanz, die für uns die Transfor- mation übernimmt. Das fertige XML-Dokument wird dann auf der Konsole ausgegeben.     Das war ein Kinderspiel oder? Im Prinzip wird aber auch bei komplizierteren Bindungen nach dem gleichen Schema vorgegangen. Existierende Java Bean mit Annotationen versehen Instanz der Java Bean erzeugen Instanz an den  übergeben und XML-Dokument ausgeben 65
  • 77. 3 Hallo JAXB! Apropos Schema, wo ist hier eigentlich die Bindung an ein XML-Schema, von dem vorher gesprochen wurde? Nun, JAXB erzeugt hier aus der Java Bean  ein Schema, das wir uns bei Bedarf auch ausgeben lassen können. Dafür gibt es neben dem programma- tischen Weg über die API oder die Kommandozeile auch einen ANT-Task, den wir an die- ser Stelle kurz vorstellen wollen. Wir geben hier wirklich nur ein kurzes Beispiel an, die einzelnen Konfigurationsmöglichkeiten des -Tasks sind in der Referenz be- schrieben. Schema erzeugen mit dem schemaGen-Task                         Mit diesem kleinen ANT-Skript können wir jetzt das Schema durch Ausführen des Targets  erzeugen und in der angegebenen Datei abspeichern. Das zu unserer kleinen Java Bean passende Schema hat nun die folgende Struktur.           66
  • 78. 3.3 Am Anfang steht immer: Hallo Welt! 3.3.2 Der Weg von XML zu Java Der vorangegangene Abschnitt hat die Bindung einer Java-Klasse an ein XML-Schema gezeigt. Dieser Weg existiert erst seit JAXB 2.0. Jetzt sehen wir uns den klassischen Weg an, nämlich die Bindung eines existierenden XML-Schemas an ein generiertes Java- Datenmodell. Ausgangspunkt ist hier jetzt das XML-Schema statt der Java Bean.             Das Schema beinhaltet die gleiche Information wie zuvor unsere Java Bean. Ein Element  wird als Wurzelelement deklariert und besitzt ein Unterelement , das die eigentliche Nachricht beinhaltet. Aus diesem Schema werden wir jetzt unsere Java- Repräsentation erzeugen. Dazu bemühen wir den Schema-Compiler, der genau wie der Schema-Generator über die API, über die Kommandozeile und einen ANT-Task gestartet werden kann. Das folgende Beispiel zeigt, wie wir den Schema-Compiler mit einem klei- nen ANT-Skript dazu bringen, Java-Code aus dem obigen Schema zu generieren.                        67
  • 79. 3 Hallo JAXB!      Die genaue Funktion des ANT-Tasks ist recht ausführlich in der Referenz beschrieben, da- her wollen wir hier nur kurz darauf eingehen. Mit dem Target  wird der Schema- Compiler für ein gegebenes Schema gestartet. Der Schema-Compiler liest das Schema und leitet daraus die entsprechenden Klassen ab. Führen wir dieses Skript nun aus, erhalten wir die folgende Klasse HelloWorld.                    Wir sehen, dass der Schema-Compiler noch einige weitere Annotationen zu dieser Klasse hinzufügt, als wir das im letzten Abschnitt selbst getan haben. Ansonsten ist die Klasse a- ber identisch mit unserer selbst geschriebenen Java Bean . Daher können wir auch genauso damit umgehen, denn immerhin handelt es sich hier um eine ganz gewöhnli- che Java Bean. Was uns natürlich am meisten interessiert, ist, wie wir die Inhalte aus ei- nem XML-Dokument in eine Instanz dieser Klasse bekommen. Genau dies sehen wir uns jetzt an. Angenommen, wir bekommen wieder das folgende XML-Dokument mit der „Hel- lo world!“-Nachricht als Eingabe.     Dieses Dokument verarbeitet das folgende Listing in eine Instanz vom Typ . Wir führen hier also ein Mini-Unmarshalling durch.   68
  • 80. 3.4 Zusammenfassung                Diese Minianwendung ist ähnlich wie das erste Beispiel aufgebaut. Nach einigen Initiali- sierungen erzeugen wir mit Hilfe des -Objektes aus dem XML-Dokument  eine Instanz vom Typ . Diese Instanz besitzt jetzt den Inhalt der Elemente aus dem XML-Dokument. Die Ausgabe der Nachricht  liefert uns daher wieder die simple Nachricht . 3.4 Zusammenfassung Für die JAXB-Entwicklungsumgebung werden die Bibliotheken jaxb-api.jar, jaxb- impl.jar, jsr173_1.0_api.jar, activation.jar, und jaxb-xjc.jar auf dem Klassenpfad be- nötigt. Die Beispielanwendungen dieses Buches sind auf der Buch-Webseite zum Download erhältlich. Die Bindung von Java nach XML geschieht über Java-Klassen mit JAXB- Annotationen. Die Bindung von XML nach Java geschieht über das Generieren von JAXB-Klassen mit dem Schema-Compiler Für die Ausführung von Schema-Compiler und Schema-Generator gibt es ANT- und Kommandozeilenskripte. 69
  • 81. 4 JAXB-API In diesem Kapitel wird es so richtig losgehen. Stück für Stück werden wir durch praktische Beispiele die Möglichkeiten der JAXB erschließen. Dabei wird die im Kapitel zu XML- Schema vorgestellte Domäne des Online-Banking-Service der rote Faden sein, an dem sich die Beispiele orientieren. Als Erstes werden wir uns der JAXB-API widmen. Die folgende Abbildung zeigt einen typischen Anwendungsfall unseres Online-Banking-Service und die verwendeten JAXB-API-Elemente. Client Online-Banking-Service JAXBContext / Unmarshaller JAXBContext / Marshaller Abbildung 4.1 Aufruf des Online-Banking-Service Die XML-Dokumente, die wir hier verwenden, basieren auf dem gleichen Gerüst aus Schemadokumenten, das bereits im XML-Schema-Kapitel aufgebaut wurde. Die am Schluss des XML-Schema-Kapitels aufgeführte Übersicht über die einzelnen Schemado- kumente soll uns im weiteren Verlauf als Referenz für die benutzten Schemas dienen. Anhand dieses Schemas und der zugehörigen JAXB-Klassen stellen wir die Voraussetzun- gen und Grundlagen vor, die wir brauchen, um die API zu nutzen. Danach widmen wir uns den eigentlichen Funktionalitäten, die uns die JAXB-API bietet, wie z.B. das Unmarshal- ling und Marshalling von XML-Dokumenten. Danach stellen wir die Funktionalitäten und Aspekte vor, die sowohl beim Marshalling als auch beim Unmarshalling verwendet werden wie beispielsweise die Validierung,  71
  • 82. 4 JAXB-API  und . Am Ende des Kapitels sollten wir damit den prakti- schen Einsatz der gesamten JAXB-API kennen. 4.1 Die ersten Schritte Die wichtigen Klassen der Laufzeit-API der JAXB, die wir in den ersten Schritten be- schreiben werden, sind: : Jeder lesende bzw. schreibende Zugriff auf XML erfolgt implizit über eine -Instanz. : Eine Klasse, mit der wir Informationen zur XML-Bindung von Java-Objekten abfragen können. die durch den Schema-Generator angelegte Klasse , mit der wir pro- grammatisch die Java-Objekte eines XML-Dokuments anlegen können. 4.1.1 Am Anfang war der JAXBContext Der  bildet den Einstiegspunkt für die JAXB-API. Eine Applikation, die auf eine Datenbindung mit JAXB zugreifen möchte, muss als Erstes ein Objekt vom Typ  erzeugen. Der  verwaltet nämlich die Informationen über die Datenbindung zwischen einem Java-Modell und einem oder mehreren XML-Schemas. Dazu speichert die -Instanz implizit eine bidirektionale Abbildung zwischen global deklarierten Elementen im Schema und den entsprechenden Java-Klassen. Dies er- möglicht z.B. dem , ein XML-Element auf den korrekten Typ abzubilden. Für unsere Beispielanwendung sollten wir uns dieses Mapping einmal ansehen. Tabelle 4.1 Abbildung von globalen Elementen im JAXBContext XML-Element Namespace Abbildung im JAXBContext <response> http://jaxb.transparent/response Klasse Response <customerElement> http://jaxb.transparent/customer Klasse Customer <accountElement> http://jaxb.transparent/account Klasse Account <portfolioElement> http://jaxb.transparent/portfolio Klasse Portfolio Die Tabelle zeigt, dass nur die global definierten Elemente aus den vier Schemadokumen- ten in der Abbildung vorhanden sind. Nur diese Elemente kommen als Wurzel eines XML- Dokuments für diese Schemadokumente in Frage. Unser Online-Banking-Service muss also als Erstes ein -Objekt definieren, um eine Antwort auf eine Anfrage erstellen zu können. Dieses Objekt bietet ihm dann die Möglichkeit, über Factory-Methoden entsprechende Service-Objekte (,   etc.) für die einzelnen API-Funktionalitäten zu erstellen. Hier eine Übersicht 72
  • 83. 4.1 Die ersten Schritte über die verschiedenen Möglichkeiten, einen  zu erzeugen, sowie die ver- schiedenen Service-Objekte und deren Factory-Methoden:                    4.1.1.1 Einen JAXBContext anlegen Ein -Objekt wird über die Factory-Methode  erzeugt. Die -Klasse selbst ist eine abstrakte Klasse. Welche konkrete Implementierung hier von der -Methode zurückgegeben wird, hängt von der verwendeten JAXB-Implementierung ab und sollte sich nicht auf deren Verwendung auswirken. Sie wird im Fall der Referenzimplementierung aus der Datei  gelesen. Wie aus dem Listing oben zu erkennen ist, gibt es eine ganze Reihe von - Methoden mit verschiedenen Signaturen. Zu den wichtigsten Methoden ist hier jeweils ein Beispiel abgedruckt. JAXBContext unter Verwendung des Paketnamens erzeugen Wir können eine neue -Instanz anhand einer Zeichenkette erzeugen. Die Zei- chenkette beschreibt ein oder mehrere Java-Pakete, deren Klassen über JAXB an XML ge- bunden werden sollen.     73
  • 84. 4 JAXB-API Dieser Methode übergeben wir einen Kontextpfad, der aus einem vollqualifizierten Paket- namen oder aus mehreren Paketnamen besteht, die wir per Doppelpunkt trennen. Diese Pakete enthalten die Java-Klassen, die ein oder mehrere zu bindende XML-Schemas reprä- sentieren. Der  ist nach diesem Aufruf mit allen definierten Klassen initialisiert und kann nun Instanzen dieser Java-Klassen in XML umwandeln und umgekehrt. JAXBContext unter Verwendung eines anderen Classloaders erzeugen Der Aufruf  nutzt den  des aktuellen Threads, um die Klassen im angegebenen Paket zu lokalisieren. Falls eine andere -Instanz benutzt werden soll, kann diese der folgenden Variante der -Methode übergeben werden:    JAXBContext anhand von Java-Klassen erzeugen Besonders im Fall der Bindung eines Schemas an ein existierendes Datenmodell ist die folgende Variante der -Methode zu erwähnen. Diese erwartet anstelle eines Paketnamens die Angabe einer gewöhnlichen Java-Klasse in Form einer -Instanz.   Hier wird z.B. die Klasse  angegeben, die das Wurzelelement für die Antwort des Online-Banking-Service darstellt. Dadurch wird ein  mit der Klasse   und allen von ihr referenzierten Klassen initialisiert. 4.1.1.2 Viele Threads, ein JAXBContext Sicher wird sich der ein oder andere fragen, ob der  für jede Verarbeitung neu angelegt werden muss. Das Erzeugen des -Objektes ist ein recht auf- wendiger Vorgang, da die Bindungsinformationen für alle Klassen, die dem Kontext zuge- ordnet sind, zunächst ermittelt werden müssen. Daher sollte das Objekt nach Möglichkeit wiederverwendet werden. Die JAXB-Spezifikation schreibt vor, dass eine Implementierung der -Klasse threadsafe sein muss. Dadurch kann eine Instanz des  von beliebig vielen Threads genutzt werden. In unserem Beispiel könnte der Online-Banking-Service ein ein- ziges Kontextobjekt benutzen, um beliebig viele Clients zu bedienen. Also statt wie in dem folgenden Quelltextauszug in jedem Methodenaufruf eine neue Instanz anzulegen: 74
  • 85. 4.1 Die ersten Schritte      ist es erlaubt und performanter, diese statisch anzulegen, wie wir das im unten abgedruck- ten Quelltext machen:      4.1.2 Die Klasse JAXBIntrospector verwenden Eine der Klassen, die auf Anfrage durch eine -Implementierung instanziiert wird, ist die Klasse . Diese Hilfsklasse bietet Methoden, mit denen wir unbekannte Java-Objekte auf eine XML-Bindung hin prüfen können.       Den Einsatz der oben genannten Methoden schauen wir uns näher an. Die folgenden Bei- spiele setzen voraus, dass ein XML-Dokument wie folgt per Unmarshalling in ein Objekt  vom Typ  überführt wird.                          75
  • 86. 4 JAXB-API isElement Mit der Methode  können wir feststellen, ob ein beliebiges Objekt ein durch diesen Kontext gebundenes XML-Element darstellt. Objekte, für die dies zutrifft, sind: Objekte vom Typ  Objekte, deren Klasse eine Annotation  besitzt Beispielsweise liefert der Aufruf  den Rückgabewert , weil  als Element auf der Hauptebene in unserem Schema definiert wurde und daher die Annotation  trägt. Der folgende Aufruf  liefert den Wert . Auch das ist korrekt, da der Datentyp  nicht mit der An- notation  markiert wurde und daher auch nicht als Wurzelelement eines XML-Dokuments in Frage kommt. Wir können aber manuell ein Element aus dem   Objekt erzeugen, indem wir es in einen Wrapper vom Typ  verpacken, auf den wir später noch näher eingehen werden:     Das obige Beispiel liefert jetzt auch  als Ausgabe. getElementName Für alle Objekte, für die  den Wert  zurückliefert, kann mit der Methode  der Name des Elements im XML-Dokument bezo- gen werden.  Der Aufruf liefert den Namen des Elements in Form eines -Objekts, dessen - Darstellung so aussieht:  getValue Diese wohlgemerkt statische Methode liefert den „Wert“ eines an XML gebundenen Java- Objekts. Wie oben erwähnt, kann eine solche Bindung in zwei verschiedenen Formen auf- 76
  • 87. 4.1 Die ersten Schritte treten, einmal als Instanz einer Java-Klasse mit -Annotation oder aber als -Instanz. Im ersten Fall stellt die Instanz selbst den Wert dar, die  -Instanz hingegen kapselt den Wert in der Eigenschaft . Falls in einer An- wendung diese beiden Formen vermischt und beliebig auftreten, kann der Zugriff auf die Werte über die Methode  vereinheitlicht werden, statt jedes Mal den einen oder anderen Fall zu überprüfen. Hier ein Beispiel für unsere - und -Objekte.    4.1.3 Objekte erzeugen mit der ObjectFactory Wie wir im Übersichtskapitel zur JAXB bereits erwähnt haben, können wir mit einer durch den Schema-Compiler angelegten Klasse -Instanzen der generierten Java Beans erzeugen. Hierzu bietet diese Klasse eine -Methode für jedes Element des zugrunde liegenden XML-Schemas. Für unseren Online-Banking-Service enthält sie z.B. die Methoden  , ,  etc. Ein Beispiel veranschaulicht die Ar- beit mit der .                               77
  • 88. 4 JAXB-API                    In dem ausführbaren Beispiel erzeugen wir eine Instanz der Klasse . Diese nutzen wir, um Objekte für Kunden-, Konto- und Portfolioinformationen zu erzeugen. Die Objekte werden über die Zugriffsmethoden miteinander verbunden und einer Variablen vom Typ  zugewiesen, welche die gesamte Antwort des Online-Banking-Service darstellt. Dieses Objekt können wir nun in ein XML-Dokument transformieren. Elemente vom Typ JAXBElement erzeugen Die oben erzeugten Instanzen vom Typ , ,  etc. stellen die Java-Repräsentation der im XML-Schema definierten Typen dar. Ein XML-Element z.B. vom Typ  kann jedoch zusätzlich Namespace-Informationen besitzen. Diese zu- sätzlichen Namespace-Informationen werden durch den Typ  abgebildet. Daher bietet die  zusätzlich Methoden, die aus einer Java-Repräsentation ein Objekt vom Typ  erzeugen, das den XML-Namen und Namespace- Informationen enthält. Dadurch entfällt ein manuelles Erzeugen von XML-Elementnamen. Die folgende Definition für das Objekt      kann damit durch diesen Aufruf mit der  ersetzt werden.  4.1.4 Zusammenfassung Ein  kann auf verschiedene Arten angelegt werden: unter Angabe von Paketnamen, Klassenobjekten oder eines alternativen Classloaders. 78
  • 89. 4.2 Marshalling Die Hilfsklasse  liefert uns die Information, ob ein gegebenes Ob- jekt per JAXB an XML gebunden ist. Der Schema-Compiler erzeugt automatisch eine Klasse , mit der sich Instanzen der generierten Java Beans und Elementinstanzen vom Typ  erzeugen lassen. 4.2 Marshalling Mit dem im vorigen Abschnitt erzeugten -Objekt kann der Online-Banking- Service nun zur Tat schreiten und die gewünschten Informationen in einem XML- Dokument an den Client senden. Die Informationen über Kunde, Konto und Portfolio wur- den vom Service z.B. aus einer Datenbank bezogen und liegen jetzt als Objekte im Spei- cher vor. Die Transformation dieser Objekte in ein XML-Dokument, die einem vorgegebenen Schema entspricht, wird nun vom  der JAXB-Implementierung übernommen. Der  ist also in der Lage, Java-Objekte, die an XML gebunden sind, in ihre XML-Repräsentation zu überführen. Die Daten, die in unserem Online-Banking-Service vielleicht aus einer Datenbank gelesen wurden, liegen vielleicht noch nicht als XML- gebundene Java-Klassen vor, was dann? Sehen wir uns dazu die zwei möglichen Szenarien einer JAXB-Bindung an: Bindung eines existierenden Datenmodells: Hier wird ein existierendes Java- Datenmodell mit Annotationen manuell an ein XML-Schema gebunden. Ein solches Datenmodell können wir dem  direkt übergeben. Generieren eines Datenmodells aus einem XML-Schema: In diesem Fall werden Java- Klassen eigens aus einem existierenden Schema heraus erzeugt. Um Instanzen dieser Klassen zu erzeugen, generiert der Schema-Compiler die Klasse , die wir weiter oben bereits im Einsatz gesehen haben. 4.2.1 Das Marshaller-Objekt anlegen Über das Kontextobjekt vom Typ  erzeugen wir nun über die entsprechende Factory-Methode ein -Objekt.   Die Schnittstelle  vereint alle API-Methoden, die für den Marshalling-Prozess von Bedeutung sind. Dazu gehören Methoden, die den Marshalling-Prozess starten, die Registrierung von Event-Handlern, das Einschalten der Validierung etc. 79
  • 90. 4 JAXB-API 4.2.2 Den Marshalling-Prozess starten Durch Aufruf von  wird der Marshalling-Prozess gestartet. Diese Methode erwartet zwei Parameter. Der erste Parameter vom Typ  stellt das zu transformierende Java-Objekt dar. Es wird bewusst nur der Typ  erwartet, da die Java-Klassen einfache POJO1s sein können, daher keinerlei Schnittstellen implementie- ren müssen. Die einzige Einschränkung, die hier gilt, ist, dass nur Objekte verarbeitet werden können, die an ein gültiges Wurzelelement eines XML-Schemas gebunden wurden. Dies wird in- tern durch die bereits vorgestellte Methode  der Klasse  überprüft. Ist das übergebene Objekt kein solches Element, wird der Prozess mit einer  abgebrochen. Der zweite Parameter gibt das Ausgabeformat des Marshalling-Prozesses an. Für jedes der möglichen Ausgabeformate gibt es eine eigene Methode. Tabelle 4.2 Marshalling-Ausgabeformate Marshal-Methode Ausgabeformat  Marshalling der Objektstruktur in einen Writer, z.B. einen  zur Ausgabe in einer Datei.  Ausgabe in eine entsprechende Instanz von .  Ausgabe als Ergebnis einer TrAX2 XSLT- Transformation  Ausgabe in eine DOM-Instanz  Ausgabe in einen ContentHandler für SAX2 vents  Ausgabe mit dem XMLStreamWriter der StAX3- API Diese verschiedenen Ausgabeformate können in zwei Gruppen aufgeteilt werden. Mit den Standard-Java-Ausgabeschnittstellen wie  oder  wird der Inhalt „endgültig“ als XML-Dokument serialisiert. Die anderen Formate ermöglichen die Anbin- dung und Weiterverarbeitung der Ausgabe durch Java-XML-APIs wie TrAX oder StAX. So können Inhalte nach dem Marshalling z.B. durch einen Handler für SAX2-Events mo- difiziert werden. Eine komplette (und insbesondere aktuelle) Auflistung der möglichen Ausgabeformate findet sich in der Javadoc-Dokumentation der Klasse . 1 Plain Old Java Object 2 Transformation API for XML 3 Streaming API for XML 80
  • 91. 4.2 Marshalling XML in Datei schreiben Die im Beispiel mit Hilfe der  erzeugten Java-Objekte können wir auf die folgende Weise als XML-Dokument in einer Datei  abspeichern:  XML in ein W3C-DOM-Dokument schreiben Ein W3C-DOM-Dokument kann ebenfalls erzeugt werden. Statt einer Datei wird hier ein Objektbaum aus W3C-DOM-Knoten erzeugt.       XML auf der Konsole ausgeben Sehr nützlich für Test- und Debugging-Zwecke ist die Ausgabe auf der jeweiligen Konso- le. Dies liefert der folgende Aufruf.   XML als StAX XML-Stream ausgeben Hier wird die StAX-API der JAXP verwendet, um einen XML-Ausgabestrom zu erzeugen.     4.2.3 Den Marshalling-Prozess konfigurieren Der Marshalling-Prozess kann durch das Setzen spezieller Parameter über die Methode  konfiguriert werden. Diese Parameter übergeben wir der - Instanz vor dem eigentlichen Marshalling.  Das obige Beispiel veranlasst den  durch Setzen der Property , die XML-Elemente in der Ausgabe entsprechend einzurücken, um ein für Menschen besser lesbares Dokument mit vielen Leer- und Formatierungszei- chen zu erzeugen. Praktischerweise sind für die einzelnen Property-Bezeichner String- Konstanten in der Klasse  vorhanden. 81
  • 92. 4 JAXB-API Wir wollen einen weiteren Parameter vorstellen, nämlich . Diese Eigenschaft weist den  an, den Ort des übergebenen Schemadokuments in der Ausgabe zu deklarieren. Der Ort wird dabei so angegeben, wie er auch im entsprechenden -Attribut eines XML-Dokuments deklariert werden würde, nämlich Namespace URI + URI des Schemadokuments.   Der Umfang der unterstützten Parameter hängt von der jeweiligen Implementierung der JAXB-Spezifikation ab. In der folgenden Tabelle sind die Standard-Properties, die von je- der -Implementierung der JAXB-Spezifikation unterstützt werden sollen, fett abgedruckt. Tabelle 4.3 Marshalling-Properties Property Bedeutung Datentyp jaxb.encoding Zeichensatz des ausgegebenen XML, java.lang.String falls nicht anders angegeben, ist hier  gesetzt. jaxb.formatted.output Gibt an, ob das ausgegebene XML einge- java.lang.Boolean rückt werden soll:  = Ausgabe eingerückt  (Standard) = Ausgabe nicht ein- gerückt jaxb.schemaLocation Durch diese Eigenschaft kann dem aus- java.lang.String gegebenen XML-Dokument der Ort eines XML-Schemas mit dem -Attribut über- geben werden. Diese Eigenschaft gilt für XML-Dokumente, die einen oder mehrere Namespaces verwenden. jaxb.noNamespaceSchema- Diese Eigenschaft übergibt den Ort eines java.lang.String Location Schemadokuments für Dokumente, die keine Namespaces verwenden. Hier wird das gleichnamige Attribut  verwendet. jaxb.fragment Gibt an, ob der Marshaller Events wäh- java.lang.Boolean rend des Marshalling-Prozesses generie- ren soll. Die Standardeinstellung ist dabei . com.sun.xml.bind.character- Mit dieser Eigenschaft kann ein eigener com.sun.xml.bind.marshaller. EscapeHandler Handler zur Konvertierung von Steuerzei- CharaterEscapeHandler (nur JAXB 2.0 RI) chen (Escape Characters) angegeben werden. 82
  • 93. 4.2 Marshalling Property Bedeutung Datentyp com.sun.xml.bind.namespacePrefix Gibt eine Handlerklasse an, die den com.sun.xml.bind.marshalle Mapper Marshaller veranlasst, benutzerdefi-  nierte Präfixe zu generieren. (nur JAXB 2.0 RI) com.sun.xml.bind.indentString Gibt die Zeichenfolge an, die zur Ein- java.lang.String rückung genutzt werden soll, wenn (nur JAXB 2.0 RI) die Eigenschaft jaxb.formatted.output gesetzt ist. com.sun.xml.bind.xmlHeaders Diese Eigenschaft gibt die Präambel, java.lang.String (nur JAXB 2.0 RI) also das Element  im Kopf eines XML-Dokuments, an. Hier können z.B. Kommentare oder -Deklarationen erfolgen. 4.2.4 Das fertige Beispiel Das folgende Codebeispiel zeigt den gesamten Marshalling-Prozess anhand unseres Onli- ne-Banking-Service. Dieser generiert eine Antwort, indem die vorhandenen Objekte in ein XML-Dokument transformiert werden. Das Ergebnis der Transformation wird dann in ei- ner Datei abgespeichert. In einer realen Anwendung würde diese Antwort natürlich nicht als Datei versendet, sondern eher in eine SOAP-Nachricht verpackt werden, um dann als Antwort eines Webservice über die Netzwerkschnittstelle versendet zu werden.                            83
  • 94. 4 JAXB-API                                  Das resultierende XML-Dokument nach Ausführung des oben stehenden Codes sieht dann folgendermaßen aus:                          84
  • 95. 4.2 Marshalling    Das Listing zeigt, dass der  tatsächlich das entsprechende Schema im -Attribut angibt. Die Präfixe der deklarierten Namespaces werden einfach durchnummeriert. 4.2.5 Marshalling beliebiger Objekte Wie oben bereits erwähnt wurde, verarbeitet der  nur solche Java-Objekte, die Wurzelelemente eines XML-Schemas darstellen, also Elemente, die im Schema auf obers- ter Ebene deklariert sind. Ein solches Element ist z.B. das -Element, welches das Wurzelelement in unserem Online-Banking-Service-Schema darstellt. Das Element  dagegen ist kein solches Wurzelelement. Nun wäre es aber auch denkbar, dass wir statt eines -Objekts auch einmal einen einzelnen Kundenda- tensatz vom Typ  transformieren wollen. Für diesen Fall gibt es zwei mögliche Wege. Die Klasse JAXBElement als Wrapper nutzen Eine einfache Möglichkeit, ein solches Marshalling durchzuführen, ist die Benutzung einer Wrapper-Klasse. Verpacken wir ein Kundenobjekt vom Typ  mit der Wrapper- Klasse , kann das Marshalling problemlos durchgeführt werden. Das Verpacken der Objektinstanz übernimmt wieder die Klasse . Dadurch wird aus dem Objekt ein transformierbares Element vom Typ . Die- ses Element enthält neben dem eigentlichen Objekt zusätzliche Informationen wie z.B. den Elementnamen und Namespace-Informationen. Im Programmcode sieht das folgenderma- ßen aus:                       85
  • 96. 4 JAXB-API                         Die Annotation @XmlRootElement verwenden Falls wir ein bestehendes Java-Datenmodell an ein XML-Schema binden, können wir den Typ  zu einem Wurzelelement machen, indem wir die Klasse  mit der Annotation  versehen. Die Klasse wird dadurch automatisch als JAXB- Element erkannt. Die nötigen Namespace-Informationen sind hier bereits in der Annotati- on enthalten. Dadurch wird ein direktes Marshalling ohne den Umweg über eine Wrapper- Klasse möglich. Hinweis Ein Objektgraph muss nicht zwingend konform zu einem Schema sein, um mit dem   verarbeitet werden zu können. Der  ist daher in der Lage, auch un- gültige Inhalte in ein XML-Dokument zu überführen. 4.2.6 Zusammenfassung Mit dem  lassen sich Java-Objekte in XML-Strukturen transformieren. Eine -Instanz wird über den  angelegt. Der  kann Java-Objekte in verschiedene Ausgabeformate transformieren, darunter Standardschnittstellen wie Dateien oder Streams, aber auch Ausgabeformate anderer XML-APIs wie DOM, StAX oder TrAX. Durch das Setzen von Properties können wir Einfluss nehmen auf den Marshalling- Prozess. 86
  • 97. 4.3 Unmarshalling Es können prinzipiell beliebige Objekte transformiert werden, auch einem XML- Schema nach ungültige XML-Inhalte. 4.3 Unmarshalling Bisher hat unser Online-Banking-Service eine XML-Antwort unter Verwendung von  und  erstellt und an einen Client versendet. Wie können wir nun dieses XML-Dokument in der Clientanwendung verarbeiten? Das Zauberwort heißt hier Unmarshalling. Wir wissen bereits, dass beim Unmarshalling XML-Elemente in einen Graph aus Java-Objekten im Speicher transformiert werden. Die XML-Elemente können dabei ein ganzes Dokument darstellen oder auch nur einen Teil davon. Wichtig ist, dass die Elemente in einem Schema definiert wurden, das dem  vorher bekannt ge- macht wurde. Bei Elementen sollten wir dabei zwischen global und lokal definierten Ele- menten unterscheiden. Globale Elemente und Datentypen (-/) sind in einem Schema auf der obersten Ebene definiert. Der  kennt für jedes globale Element, Da- tentypen ausgenommen, eine Abbildung auf eine Java-Klasse. Ein XML-Dokument mit einem global definierten Wurzelelement an den  zu übergeben, ist wohl der Standardfall. Der  kann solche XML-Dokumente ohne Umwege transformieren. Ein Beispiel für ein globales Element in unserem Schema ist das  -Element. Ein global definierter Datentyp ist z.B. der Datentyp , der im Kundenschema auf oberster Ebene definiert ist. Lokale Elemente werden innerhalb einer anderen Elementdeklaration definiert. Ein XML-Dokument, das ein lokales Element als Wurzelelement besitzt, kann der   nicht mit dem Standardweg über den  auf die korrekte Klasse ab- bilden. Wie das Unmarshalling solcher Teildokumente funktioniert, wird in Abschnitt 4.3.7 näher beschrieben. 4.3.1 Das Unmarshaller-Objekt anlegen Zunächst sehen wir uns den Standardfall an, in dem wir ein global definiertes Element als Wurzel eines XML-Dokuments transformieren. Der Unmarshaller der JAXB- Implementierung verwendet eine -Instanz, um dieses Wurzelelement der richtigen Java-Klasse zuzuordnen. Als Erstes müssen wir daher wieder einen solchen Kon- text erzeugen. Analog zum Marshalling kann dann mit Hilfe des Kontexts ein Service- Objekt vom Typ  erzeugt werden. Die Methode  des  liefert uns eine Implementierung des Interface Unmarshaller zurück.   87
  • 98. 4 JAXB-API 4.3.2 Den Unmarshalling-Prozess starten Die Java-Schnittstelle  bietet uns jetzt analog zu  einige  -Methoden, die das Unmarshalling eines XML-Dokuments durchführen. Die möglichen Eingabeformate entsprechen dabei der Auswahl von Ausgabeformaten beim Marshalling. Eine Ausnahme bildet hier die -Variante, die eine Adresse vom Typ  als Parameter aufnimmt. Als Rückgabe liefern alle Methoden ein Ob- jekt vom Typ . Abhängig von dem gelesenen XML-Dokument kann die Methode beliebige Java-Objekte zurückgeben. Tabelle 4.4 Unmarshalling-Eingabeformate Unmarshal-Methode Eingabeformat  Unmarshalling eines XML-Dokuments im Java-Dateiformat   Angabe einer Dokumentadresse vom Typ   Übergabe eines Eingabestroms, z.B. einer XML-Datei  Übergabe einer Transformationsquelle der TrAX4-API  Ausgabe als DOM-Parsebaum  Übergabe einer SAX-konformen Ein- gabequelle  Übergabe eines XMLStreamReaders der StAX5-API  Ausgabe eines XMLEventReaders der StAX-API Die Eingabeformate unterscheiden sich ebenfalls wieder in die Standard-Java- Eingabeformate wie  oder  und Eingabeformaten, welche die Integrati- on von JAXB mit anderen XML-APIs erlauben. Als Beispiel für die Anwendung der -Methode lesen wir im folgenden Quell- textauszug das XML-Dokument ein, das wir im letzten Abschnitt mit dem Marshaller er- zeugt haben.   4 Transformation API for XML 5 Streaming API for XML 88
  • 99. 4.3 Unmarshalling Der  benutzt den , um das Wurzelelement  auf die Klasse  abzubilden, und liefert uns daher ein Objekt vom Typ  zurück, das genau die Antwort des Online-Banking-Service darstellt und mit dem wir jetzt in unse- rer Clientanwendung weiterarbeiten können. 4.3.3 Den Unmarshalling-Prozess konfigurieren Im Gegensatz zum  sieht die JAXB-Spezifikation 2.0 keine besonderen Para- meter vor, die für den Unmarshalling-Prozess gesetzt werden können. Auch die einzelnen JAXB-Implementierungen bieten hier bisher keine implementierungsspezifischen Eigen- schaften an. 4.3.4 Das fertige Beispiel Hier noch einmal eine komplette Methode, die das Unmarshalling unseres - Dokuments durchführt. Der  wird in diesem Beispiel zur Anschaulichkeit innerhalb des Methodenrumpfes neu erzeugt. In einer realen Anwendung sollte ein bereits bestehender Kontext aus Performancegründen in die Methode hereingereicht werden. Der  nutzt die im  bekannte Abbildung des -Elementes auf die Java-Klasse , um den korrekten Datentyp zurückzuliefern.                          89
  • 100. 4 JAXB-API 4.3.5 Das xsi:type-Attribut beim Unmarshalling verwenden Angenommen, wir bekommen jetzt aus einer unbekannten Quelle ein XML-Dokument mit einem anderen Wurzelelement. Als Basis besitzt es zwar die Struktur des Elements  , es beinhaltet jedoch noch ein zusätzliches Unterelement und heißt auch noch an- ders ...              Nun wollen wir in der Lage sein, ein solches Dokument trotzdem in ein -Objekt zu transformieren. Der Datentyp  muss dazu im Schema allerdings wie folgt glo- bal definiert sein.         Mit dem -Attribut können wir mit Schemamitteln einem Parser den Tipp geben, dass ein Element A vom Typ her einem Element B entspricht. Dieses Attribut wird auch vom Unmarshaller beachtet. Findet der  nämlich keinen passenden Typen für den Namen des Wurzelelements, so versucht er, bei Angabe eines -Attributs den dort spezifizierten Typen im  zu finden. Die Lösung unseres Problems wäre daher, in unserem XML-Dokument eine Typsubstitution mit  vorzuneh- men. &#x