16.4 Java Architecture for XML Binding (JAXB)
Java Architecture for XML Binding (JAXB) ist eine API zum Übertragen von Objektzuständen auf XML-Dokumente und umgekehrt. 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, die Entwickler selbst an die JavaBeans setzen können, aber JavaBeans werden gleich zusammen mit den Annotationen von einem Werkzeug aus einer XML-Schema-Datei generiert.
Java 6 integriert JAXB 2.0, und das JDK 6 Update 4 – sehr ungewöhnlich für ein Update – aktualisiert auf JAXB 2.1. Java 7 aktualisiert auf JAXB 2.2.
16.4.1 Bean für JAXB aufbauen

Wir wollen einen Player deklarieren, und JAXB soll ihn anschließend in ein XML-Dokument übertragen:
Listing 16.6: com/tutego/insel/xml/jaxb/Player.java, Player
@XmlRootElement
class Player
{
private String name;
private Date birthday;
public String getName()
{
return name;
}
public void setName( String name )
{
this.name = name;
}
public void setBirthday( Date birthday )
{
this.birthday = birthday;
}
public Date getBirthday()
{
return birthday;
}
}
Die Klassen-Annotation @XmlRootElement ist an der JavaBean nötig, wenn die Klasse das Wurzelelement eines XML-Baums bildet. Die Annotation stammt aus dem Paket javax.xml.bind.annotation.
16.4.2 JAXBContext und die Marshaller

Ein kleines Testprogramm baut eine Person auf und bildet sie dann in XML ab – die Ausgabe der Abbildung kommt auf den Bildschirm:
Listing 16.7: com/tutego/insel/xml/xml/jaxb/PlayerMarshaller.java, main()
Player johnPeel = new Player();
johnPeel.setName( "John Peel" );
johnPeel.setBirthday( new GregorianCalendar(1939,Calendar.AUGUST,30).getTime() );
JAXBContext context = JAXBContext.newInstance( Player.class );
Marshaller m = context.createMarshaller();
m.setProperty( Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE );
m.marshal( johnPeel, System.out );
Nach dem Lauf erscheint auf dem Schirm:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<player>
<birthday>1939-08-30T00:00:00+01:00</birthday>
<name>John Peel</name>
</player>
Alles bei JAXB beginnt mit der zentralen Klasse JAXBContext. Die statische Methode JAXBContext.newInstance() erwartet standardmäßig eine Aufzählung der Klassen, die JAXB behandeln soll. Der JAXBContext erzeugt den Marshaller zum Schreiben und den Unmarshaller zum Lesen. Die Fabrikmethode createMarshaller() liefert einen Schreiberling, der mit marshal() das Wurzelobjekt in einen Datenstrom schreibt. Das zweite Argument von marshal() ist unter anderem ein OutputStream (wie System.out in unserem Beispiel), Writer oder File-Objekt.
JAXB beachtet standardmäßig alle Bean-Properties, also birthday und name, und nennt die XML-Elemente nach den Properties.
class javax.xml.bind.JAXBContext |
- static JAXBContext newInstance(Class... classesToBeBound) throws JAXBException
Liefert ein Exemplar vom JAXBContext mit Klassen, die als Wurzelklassen für JAXB verwendet werden können. - abstract Marshaller createMarshaller()
Erzeugt einen Marshaller, der Java-Objekte in XML-Dokumente konvertieren kann.
abstract Unmarshaller createUnmarshaller()
Erzeugt einen Unmarshaller, der XML-Dokumente in Java-Objekte konvertiert.
class javax.xml.bind.Marshaller |
- void marshal(Object jaxbElement, File output)
- void marshal(Object jaxbElement, OutputStream os)
- void marshal(Object jaxbElement, Writer writer)
Schreibt den Objektgraph von jaxbElement in eine Datei oder einen Ausgabestrom. - void marshal(Object jaxbElement, Node node)
Erzeugt vom Objekt einen DOM-Knoten. Der kann dann in ein XML-Dokument gesetzt werden. - void marshal(Object jaxbElement, XMLEventWriter writer)
- void marshal(Object jaxbElement, XMLStreamWriter writer)
Erzeugt für ein jaxbElement einen Informationsstrom für den XMLEventWriter beziehungsweise XMLStreamWriter. Die StAX-Klassen werden später genauer vorgestellt. - void setProperty(String name, Object value)
Setzt eine Eigenschaft der Marshaller-Implementierung. Eine Einrückung etwa setzt das Paar Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE.
16.4.3 Ganze Objektgraphen schreiben und lesen
JAXB bildet nicht nur das zu schreibende Objekt ab, sondern auch rekursiv alle referenzierten Unterobjekte. Wir wollen den Spieler dazu in einen Raum setzen und den Raum in XML abbilden. Dazu muss der Raum die Annotation @XmlRootElement bekommen, und bei Player kann sie entfernt werden, wenn nur der Raum selbst, aber keine Player als Wurzelobjekte zum Marshaller kommen:
Listing 16.8: com/tutego/insel/xml/xml/jaxb/Room.java, Room
@XmlRootElement( namespace = "http://tutego.com/" )
public class Room
{
private List<Player> players = new ArrayList<Player>();
@XmlElement( name = "player" )
public List<Player> getPlayers()
{
return players;
}
public void setPlayers( List<Player> players )
{
this.players = players;
}
}
Zwei Annotationen kommen vor: Da Room der Start des Objektgraphen ist, trägt es @XmlRootElement. Als Erweiterung ist das Element namespace für den Namensraum gesetzt, da bei eigenen XML-Dokumenten immer ein Namensraum genutzt werden soll. Weiterhin ist eine Annotation @XmlElement am Getter getPlayers() platziert, um den Namen des XML-Elements zu überschreiben, damit das XML-Element nicht <players> heißt, sondern <player>.
Kommen wir abschließend zu einem Beispiel, das einen Raum mit zwei Spielern aufbaut und diesen Raum dann in eine XML-Datei schreibt. Statt allerdings JAXBContext direkt zu nutzen und einen Marshaller zum Schreiben und Unmarshaller zum Lesen zu erfragen, kommt im zweiten Beispiel die Utility-Klasse JAXB zum Einsatz, die ausschließlich statische überladene marshal()- und unmarshal()-Methoden anbietet:
Listing 16.9: com/tutego/insel/xml/jaxb/RoomMarshaller.javal, main()
Player john = new Player();
john.setName( "John Peel" );
Player tweet = new Player();
tweet.setName( "Zwitscher Zoe" );
Room room = new Room();
room.setPlayers( Arrays.asList( john, tweet ) );
File file = new File( "room.xml" );
JAXB.marshal( room, file );
Room room2 = JAXB.unmarshal( file, Room.class );
System.out.println( room2.getPlayers().get( 0 ).getName() ); // John Peel
file.deleteOnExit();
Falls etwas beim Schreiben oder Lesen misslingt, werden die vorher geprüften Ausnahmen in einer DataBindingException ummantelt, die eine RuntimeException ist.
Die Ausgabe ist:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:room xmlns:ns2="http://tutego.com/">
<player>
<name>John Peel</name>
</player>
<player>
<name>Zwitscher Zoe</name>
</player>
</ns2:room>
Da beim Spieler das Geburtsdatum nicht gesetzt war (null wird referenziert), wird es auch nicht in XML abgebildet.
class javax.xml.bind.JAXB |
- static void marshal(Object jaxbObject, File xml)
- static void marshal(Object jaxbObject, OutputStream xml)
- static void marshal(Object jaxbObject, Result xml)
- static void marshal(Object jaxbObject, String xml)
- static void marshal(Object jaxbObject, URI xml)
- static void marshal(Object jaxbObject, URL xml)
- static void marshal(Object jaxbObject, Writer xml)
Schreibt das XML-Dokument in die angegebene Ausgabe. Im Fall von URI/URL wird ein HTTP-POST gestartet. Ist der Parametertyp String, wird er als URL gesehen und führt ebenfalls zu einem HTTP-Zugriff. Result ist ein Typ für eine XML-Transformation und wird später vorgestellt. - static <T> T unmarshal(File xml, Class<T> type)
- static <T> T unmarshal(InputStream xml, Class<T> type)
- static <T> T unmarshal(Reader xml, Class<T> type)
- static <T> T unmarshal(Source xml, Class<T> type)
- static <T> T unmarshal(String xml, Class<T> type)
- static <T> T unmarshal(URI xml, Class<T> type)
- static <T> T unmarshal(URL xml, Class<T> type)
Rekonstruiert aus der gegebenen XML-Quelle den Java-Objektgraph.
Performance-Tipp |
Den JAXBContext aufzubauen, kostet Zeit und Speicher. Er sollte daher für wiederholte Operationen gespeichert werden. Noch eine Information: Marshaller und Unmarshaller sind nicht thread-sicher; es darf keine zwei Threads geben, die gleichzeitig den Marshaller/Unmarshaller nutzen. |
Ihr Kommentar
Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.