14.8 Java Architecture for XML Binding (JAXB) 

JAXB ist eine API zum Übertragen von Objektzuständen auf XML-Dokumente. Anders als eine manuelle Abbildung von Java-Objekten auf XML-Dokumente oder das Parsen von XML-Strukturen und Übertragen der XML-Elemente auf Geschäftsobjekte, arbeitet JAXB automatisch. Die Übertragungsregeln definieren Annotationen oder eine Schema-Datei. Im Fall von Annotationen bestimmen sie die abzubildenden Elemente, im Fall einer Schema-Datei generiert ein Programm selbstständig die JavaBeans, die die XML-Dokumente repräsentieren. Annotationen unterstützt JAXB 1.0 nicht, aber JAXB 2.0 ist aktuell und Teil von Java 6.
Für das Kapitel wollen wir den Weg über Annotationen wählen – mit Schema-Dateien findet sich eine schöne Dokumentation auf der Webseite http://java.sun.com/developer/technicalArticles/WebServices/jaxb/index.html.
14.8.1 Beans für JAXB aufbauen 

Wir wollen eine Disko mit einem DJ verbinden und den Verbund dann in eine XML-Datei übertragen. Beginnen wir bei der Disko:
Listing 14.29 com/tutego/insel/xml/jaxb/Club.java
package com.tutego.insel.xml.jaxb;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement( namespace = "http://tutego.com/" )
public class Club
{
private DJ dj;
private int numberOfPersons;
public DJ getDj()
{
return dj;
}
public void setDj( DJ dj )
{
this.dj = dj;
}
public int getNumberOfPersons()
{
return numberOfPersons;
}
public void setNumberOfPersons( int numberOfPersons )
{
this.numberOfPersons = numberOfPersons;
}
}
Die nötigen Annotationen für JAXB stammen aus dem Paket javax.xml.bind.annotation. Die Klassen-Annotation @XmlRootElement ist an der JavaBean nötig, wenn sie ein Wurzelelement eines XML-Baums bildet. Optional ist das Element namespace für den Namensraum, den wir aber gesetzt haben, da immer ein Namensraum genutzt werden soll.
JAXB beachtet standardmäßig alle Bean-Eigenschaften, also numberOfPersons und dj, und nennt die XML-Elemente nach den Properties. Für den DJ sehen wir eine zweite Klasse vor, die über die Annotation @XmlElement den Namen des XML-Elements überschreibt, damit der Name des DJs nicht im XML-Element <djName> erscheint, sondern in <name>.
Listing 14.30 com/tutego/insel/xml/jaxb/DJ.java
package com.tutego.insel.xml.jaxb;
import javax.xml.bind.annotation.XmlElement;
class DJ
{
private String djName;
@XmlElement( name = "name" )
public String getDjName()
{
return djName;
}
public void setDjName( String name )
{
this.djName = name;
}
}
14.8.2 JAXBContext und die Marshaller/ Unmarshaller 

Ein kleines Testprogramm soll einen DJ mit einer Disko verbinden und beide speichern. Das Ergebnis wird später so aussehen:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <ns2:club xmlns:ns2="http://tutego.com/"> <dj> <name>John Peel</name> </dj> <numberOfPersons>1234</numberOfPersons> </ns2:club>
Der erste Schritt ist, wie üblich, in Java Objekte aufzubauen und die Assoziation zu bilden.
Listing 14.31 com/tutego/insel/xml/xml/jaxb/ClubMarshaller.java, main()
DJ dj = new DJ(); dj.setName( "John Peel" ); Club club = new Club(); club.setDj( dj ); club.setNumberOfPersons( 1234 );
Alles bei JAXB beginnt bei der zentralen Klasse JAXBContext. Sie erzeugt entweder einen Marshaller zum Schreiben, oder einen Unmarshaller zum Lesen. Die Methode newInstance() erwartet standardmäßig eine Aufzählung der Klassen, die JAXB behandeln soll. Die Fabrikmethode createMarshaller() liefert einen Schreiberling, der mit marshal() das Wurzelobjekt in einen Datenstrom schreibt.
Listing 14.32 com/tutego/insel/xml/xml/jaxb/ClubMarshaller.java, main()
JAXBContext context = JAXBContext.newInstance( Club.class ); Marshaller m = context.createMarshaller(); m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ); m.marshal( club, System.out );
Das zweite Argument von marshal() ist ein OutputStream (wie System.out) oder Writer – andere Typen sind möglich, sind aber hier nicht so relevant. Um in eine Datei zu schreiben, bemühen wir den FileWriter:
Writer w = null;
try {
w = new FileWriter( "club-jaxb.xml" );
m.marshal( club, w );
}
finally {
try { w.close(); } catch ( Exception e ) { }
}
Mit einer XML-Datei können der Unmarshaller und seine Methode unmarshal() das Objekt rekonstruieren:
Unmarshaller um = context.createUnmarshaller(); Club club2 = (Club) um.unmarshal( new FileReader( "club-jaxb.xml" ) ); System.out.println( club2.getDj().getName() ); System.out.println( club2.getNumberOfPersons() );