JAXB Tutorial

mtk-flo

Erfahrenes Mitglied
Hallo
ich arbeite mit Eclipse 3.2.1 und
Java 6 (jdk1.6.0)...

Ich habe nun schon meherere JAXB Tutorials bei Google gefunden, jedoch haben alle Tutorials einen anderen Output als ich.

Bei vielen Tutorials werden noch impl-Ordner angelegt, die bei mir gänzlich fehlen.
Mach ich was falsch oder sind die Tutorials für das "WebPack 2.0" ausgelegt?


Hier sind zwei Tutorials die ich ausprobiert habe:
http://bitrazor.com/content/tivo/hme/howtos/jaxb/
http://www.onjava.com/pub/a/onjava/2004/12/15/jaxb.htmlhttp://java.sun.com/webservices/docs/1.6/tutorial/doc/index.html

Gruß,
Flo
 
du verwendest wahrscheinlich jwsdp 2.0 ....und in den Tutorials dort wurde jwsdp 1.X verwendet....

Nach kurzer Frage an das allmächtige Google kamm das raus:
[..]"With JAXB 2.0 fewer Java classes are generated from an XML Schema as compared to JAXB 1.0. For each top level complexType, a value class is generated, instead of an interface and an implementation class. For each top-level element, a factory class method is generated, instead of an interface and an implementation class"[..]


war glaube ich auf der ersten oder zweiten Seite:suchen:
 
@Anime-Otaku: Danke!
Gibt es für meine JAXB 2.0 Version (die in Java 6 enthalten ist) auch schon Tutorials?
Da ich nicht nochmal extra das WebPack installieren will...
 
Hallo,

hier mal ein kleines Beispiel zu JaxB:

In meinem Beispiel bilde ich ein Objektmodell zu einem
Kurs-Teilnehmer Szenario ab.

Participant
Java:
package de.tutorials;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "participant", propOrder = { "fieldOfStudy", "firstName",
        "lastName", "matriculationNumber" })
@XmlRootElement(name="participant")
public class Participant {

    protected String fieldOfStudy;
    protected String firstName;
    protected String lastName;
    protected String matriculationNumber;
    
    public Participant(){
        
    }
    
    public Participant(String fieldOfStudy, String firstName, String lastName,
            String matriculationNumber) {
        super();
        this.fieldOfStudy = fieldOfStudy;
        this.firstName = firstName;
        this.lastName = lastName;
        this.matriculationNumber = matriculationNumber;
    }

    public String getFieldOfStudy() {
        return fieldOfStudy;
    }

    public void setFieldOfStudy(String value) {
        this.fieldOfStudy = value;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String value) {
        this.firstName = value;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String value) {
        this.lastName = value;
    }

    public String getMatriculationNumber() {
        return matriculationNumber;
    }

    public void setMatriculationNumber(String value) {
        this.matriculationNumber = value;
    }

    @Override
    public String toString() {
        return this.getMatriculationNumber() + " " + this.getFirstName() + " "
                + this.getLastName() + " " + this.getFieldOfStudy();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((fieldOfStudy == null) ? 0 : fieldOfStudy.hashCode());
        result = prime * result
                + ((firstName == null) ? 0 : firstName.hashCode());
        result = prime * result
                + ((lastName == null) ? 0 : lastName.hashCode());
        result = prime
                * result
                + ((matriculationNumber == null) ? 0 : matriculationNumber
                        .hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final Participant other = (Participant) obj;
        if (fieldOfStudy == null) {
            if (other.fieldOfStudy != null)
                return false;
        } else if (!fieldOfStudy.equals(other.fieldOfStudy))
            return false;
        if (firstName == null) {
            if (other.firstName != null)
                return false;
        } else if (!firstName.equals(other.firstName))
            return false;
        if (lastName == null) {
            if (other.lastName != null)
                return false;
        } else if (!lastName.equals(other.lastName))
            return false;
        if (matriculationNumber == null) {
            if (other.matriculationNumber != null)
                return false;
        } else if (!matriculationNumber.equals(other.matriculationNumber))
            return false;
        return true;
    }
}

Course:
Java:
package de.tutorials;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "course", propOrder = {
    "name",
    "participants"
})
@XmlRootElement(name="course")
public class Course {

    @XmlElementWrapper(name = "participants")
   @XmlElement(name = "participant")
    protected List<Participant> participants;
    protected String name;
    
    public Course(String name) {
        this.name = name;
    }
    
    public Course(){
        
    }

    public List<Participant> getParticipants() {
        if (participants == null) {
            participants = new ArrayList<Participant>();
        }
        return this.participants;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return this.getName() + ": " + this.participants;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final Course other = (Course) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

Wir generieren ein XML Schema via schemagen:
Code:
C:\Dokumente und Einstellungen\Tom\workspace\de.tutorials.training>schemagen -d . -cp .\bin de.tutorials.Course
Note: Writing schema1.xsd

Das vom Generator erzeugte XML Schema schaut dann so aus:
XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:complexType name="course">
    <xs:sequence>
      <xs:element name="name" type="xs:string" minOccurs="0"/>
      <xs:element name="participants" type="participant" nillable="true" maxOccurs="unbounded" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="participant">
    <xs:sequence>
      <xs:element name="fieldOfStudy" type="xs:string" minOccurs="0"/>
      <xs:element name="firstName" type="xs:string" minOccurs="0"/>
      <xs:element name="lastName" type="xs:string" minOccurs="0"/>
      <xs:element name="matriculationNumber" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

Anschliessend lassen wir uns via xml to java compiler xjc eine entsprechende
ObjectFactory generieren:
Code:
C:\Dokumente und Einstellungen\Tom\workspace\de.tutorials.training>xjc -p de.tutorials ..\schema1.xsd
parsing a schema...
compiling a schema...
de\tutorials\Course.java
de\tutorials\ObjectFactory.java
de\tutorials\Participant.java

Da wir ja schon die Klassen Course und Participant mit den korrekten XML Binding annotationen ausgestattet haben
kopieren wir uns nur die generierte ObjectFactory in unser Projekt.

ObjectFactory:
Java:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.0 in JDK 1.6 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2007.01.13 at 07:17:23 PM CET 
//


package de.tutorials;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;


/**
 * This object contains factory methods for each 
 * Java content interface and Java element interface 
 * generated in the de.tutorials package. 
 * <p>An ObjectFactory allows you to programatically 
 * construct new instances of the Java representation 
 * for XML content. The Java representation of XML 
 * content can consist of schema derived interfaces 
 * and classes representing the binding of schema 
 * type definitions, element declarations and model 
 * groups.  Factory methods for each of these are 
 * provided in this class.
 * 
 */
@XmlRegistry
public class ObjectFactory {

    private final static QName _Course_QNAME = new QName("", "Course");

    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: de.tutorials
     * 
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link Participant }
     * 
     */
    public Participant createParticipant() {
        return new Participant();
    }

    /**
     * Create an instance of {@link Course }
     * 
     */
    public Course createCourse() {
        return new Course();
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link Course }{@code >}}
     * 
     */
    @XmlElementDecl(namespace = "", name = "Course")
    public JAXBElement<Course> createCourse(Course value) {
        return new JAXBElement<Course>(_Course_QNAME, Course.class, null, value);
    }

}

Hier nun ein Beispiel wie man dann ein Java Objekt modell nach XML Marshallen kann:
Java:
/**
 * 
 */
package de.tutorials;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

/**
 * @author Tom
 * 
 */
public class JAXBExample {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        
        Course course = new Course("ABC");
        course.getParticipants().add(new Participant("1","A","AA","X"));
        course.getParticipants().add(new Participant("2","B","BB","Y"));
        course.getParticipants().add(new Participant("3","C","CC","X"));
        course.getParticipants().add(new Participant("4","D","DD","Z"));
        
        System.out.println(course);
        
        Marshaller marshaller = JAXBContext.newInstance("de.tutorials")
        .createMarshaller();
        marshaller.marshal(course, System.out);
    }

}

Ausgabe:
Code:
ABC: [X A AA 1, Y B BB 2, X C CC 3, Z D DD 4]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><course><name>ABC</name><participants><fieldOfStudy>1</fieldOfStudy><firstName>A</firstName><lastName>AA</lastName><matriculationNumber>X</matriculationNumber></participants><participants><fieldOfStudy>2</fieldOfStudy><firstName>B</firstName><lastName>BB</lastName><matriculationNumber>Y</matriculationNumber></participants><participants><fieldOfStudy>3</fieldOfStudy><firstName>C</firstName><lastName>CC</lastName><matriculationNumber>X</matriculationNumber></participants><participants><fieldOfStudy>4</fieldOfStudy><firstName>D</firstName><lastName>DD</lastName><matriculationNumber>Z</matriculationNumber></participants></course>

Bzw:
XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<course>
	<name>ABC</name>
	<participants>
		<participant>
			<fieldOfStudy>1</fieldOfStudy>
			<firstName>A</firstName>
			<lastName>AA</lastName>
			<matriculationNumber>X</matriculationNumber>
		</participant>
		<participant>
			<fieldOfStudy>2</fieldOfStudy>
			<firstName>B</firstName>
			<lastName>BB</lastName>
			<matriculationNumber>Y</matriculationNumber>
		</participant>
		<participant>
			<fieldOfStudy>3</fieldOfStudy>
			<firstName>C</firstName>
			<lastName>CC</lastName>
			<matriculationNumber>X</matriculationNumber>
		</participant>
		<participant>
			<fieldOfStudy>4</fieldOfStudy>
			<firstName>D</firstName>
			<lastName>DD</lastName>
			<matriculationNumber>Z</matriculationNumber>
		</participant>
	</participants>
</course>

Hier der umgekehrte Weg (von XML -> Java Objektmodell):
Java:
/**
 * 
 */
package de.tutorials;

import java.io.StringReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

/**
 * @author Tom
 * 
 */
public class JAXBExample {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
    String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><course><name>ABC</name><participants><participant><fieldOfStudy>1</fieldOfStudy><firstName>A</firstName><lastName>AA</lastName><matriculationNumber>X</matriculationNumber></participant><participant><fieldOfStudy>2</fieldOfStudy><firstName>B</firstName><lastName>BB</lastName><matriculationNumber>Y</matriculationNumber></participant><participant><fieldOfStudy>3</fieldOfStudy><firstName>C</firstName><lastName>CC</lastName><matriculationNumber>X</matriculationNumber></participant><participant><fieldOfStudy>4</fieldOfStudy><firstName>D</firstName><lastName>DD</lastName><matriculationNumber>Z</matriculationNumber></participant></participants></course>";
        Unmarshaller unmarshaller = JAXBContext.newInstance("de.tutorials")
                .createUnmarshaller();
        Course course = (Course) unmarshaller.unmarshal(new StringReader(xml));
        System.out.println(course);

    }
}

Ausgabe:
Code:
ABC: [X A AA 1, Y B BB 2, X C CC 3, Z D DD 4]

Gruß Tom
 
Zuletzt bearbeitet von einem Moderator:
Vielen Dank, dass hat mir sehr weitergeholfen !

Ich habe nun mal mit meinem Schema nun die Klassen erstellt.
Nun habe ich aber eine komische Klasse zurück bekommen.
Ich weiß gar nicht wie ich darauf zugreifen soll...

Wie kann ich eine Frage oder Antwort bzw. mehrere Vorschriften eingeben mit getFrageAndVorschriftAndAntwort ?!

EintragTyp.java
Code:
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.0 in JDK 1.6 
// See <a href="<A href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a">http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2007.01.15 at 11:27:33 AM CET 
//
 
package de.beispiel;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlType;
 
/**
 * <p>Java class for EintragTyp complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="EintragTyp">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence maxOccurs="unbounded">
 *         &lt;element name="Frage" type="{http://www.w3.org/2001/XMLSchema}string"/>
 *         &lt;element name="Vorschrift" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded" minOccurs="0"/>
 *         &lt;element name="Antwort" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
 *       &lt;/sequence>
 *       &lt;attribute name="Index" use="required" type="{http://www.w3.org/2001/XMLSchema}positiveInteger" />
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "EintragTyp", propOrder = {
    "frageAndVorschriftAndAntwort"
})
public class EintragTyp {
    @XmlElementRefs({
        @XmlElementRef(name = "Frage", type = JAXBElement.class),
        @XmlElementRef(name = "Vorschrift", type = JAXBElement.class),
        @XmlElementRef(name = "Antwort", type = JAXBElement.class)
    })
    protected List<JAXBElement<String>> frageAndVorschriftAndAntwort;
    @XmlAttribute(name = "Index", required = true)
    protected int index;
    /**
     * Gets the value of the frageAndVorschriftAndAntwort property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the frageAndVorschriftAndAntwort property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getFrageAndVorschriftAndAntwort().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * {@link JAXBElement }{@code <}{@link String }{@code >}
     * 
     * 
     */
    public List<JAXBElement<String>> getFrageAndVorschriftAndAntwort() {
        if (frageAndVorschriftAndAntwort == null) {
            frageAndVorschriftAndAntwort = new ArrayList<JAXBElement<String>>();
        }
        return this.frageAndVorschriftAndAntwort;
    }
    /**
     * Gets the value of the index property.
     * 
     * @return
     *     possible object is
     *     {@link int }
     *     
     */
    public int getIndex() {
        return index;
    }
    /**
     * Sets the value of the index property.
     * 
     * @param value
     *     allowed object is
     *     {@link int }
     *     
     */
    public void setIndex(int value) {
        this.index = value;
    }
}

Hier mein Schema:
Code:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" 
        targetNamespace="http://10.196.150.5/WebSVN/xml/Pruefungskatalog" 
        xmlns:tns="http://10.196.150.5/WebSVN/xml/Pruefungskatalog">        
 <element name="Pruefungskatalog" type="tns:KatalogTyp" />
    <complexType name="KatalogTyp">
        <sequence>
            <element name="Thema" type="tns:ThemaTyp" maxOccurs="unbounded" />
        </sequence>
        <attribute name="Erstellungsdatum" type="date" use="required" />
        <attribute name="Passwort" type="string" use="required" />
    </complexType>
    <complexType name="ThemaTyp">
        <sequence>
            <element name="Kategorie" type="tns:KategorieTyp" maxOccurs="unbounded" />
        </sequence>
        <attribute name="Name" type="string" use="required" />
        <attribute name="Index" type="positiveInteger" use="required" />
    </complexType>
    <complexType name="KategorieTyp">
        <sequence>
            <element name="Unterkategorie" type="tns:UnterkategorieTyp" maxOccurs="unbounded"/>
        </sequence>
        <attribute name="Name" type="string" use="required" />
        <attribute name="Index" type="positiveInteger" use="required" />
    </complexType>
 
    <complexType name="UnterkategorieTyp">
        <sequence>
            <element name="Eintrag" type="tns:EintragTyp" maxOccurs="unbounded"/>
        </sequence>
        <attribute name="Name" type="string" use="required" />
        <attribute name="Index" type="positiveInteger" use="required" />
    </complexType>    
    <complexType name="EintragTyp">
        <sequence maxOccurs="unbounded">
            <element name="Frage" type="string" />
            <element name="Vorschrift" type="string" minOccurs="0" maxOccurs="unbounded" />
            <element name="Antwort" type="string" minOccurs="0" />
        </sequence>
        <attribute name="Index" type="positiveInteger" use="required" />
    </complexType>
</schema>
 
Hab es rausgefunden....
ich muss mit ObjectFactory die Frage, Antwort, Vorschrift ansprechen...

Also Marshallen funktioniert einwandfrei, jedoch beim Unmarshall bekomm ich einnen Fehler:
Code:
Exception in thread "main" java.lang.ClassCastException: javax.xml.bind.JAXBElement cannot be cast to de.beispiel.KatalogTyp
	at de.beispiel.JAXBExample.unmarshall(JAXBExample.java:54)
 
Zuletzt bearbeitet:
Hallo Tom,

ich beschäftige mich mit Jaxb und muss aus einer XML-Datei, die Namensräume beinhaltet, Werte auslesen und anderweitig weiterverarbeiten. Zum Testen habe ich dieses Beispiel verwendet, in dem ich versucht habe aus XSD-Datei (<xs:complexType name="course"> ...) mit XJC Klassen-Packages zu bilden, bis auf die Warnung "Schema contains no global element declaration", wurden die Packete auch erstellt. Nur sobald ich versuche "Course cource = (Course) u.unmarshal(new File("tutorial.xml"));" auszuführen, wird folgende Fehlermeldung geworfen:

DefaultValidationEventHandler: [FATAL_ERROR]: The processing instruction target matching "[xX][mM][lL]" is not allowed.

Was mach ich falsch, kannst du mir auf die Sprünge helfen?

Meine JDK-Version und die includierten JAR-Files aus jwsdp-1.5:
- j2sdk1.4.2_12
- jaxb-api.jar, jaxb-impl.jar, jaxb-libs.jar, jaxb-xjc.jar, jax-qname.jar. namespace.jar, relaxngDatatype.jar

Danke im Voraus!

Gruss, Lena

P.S. muss dazu sagen, dass ich mit Java bis jetzt nicht so viel zu tun hatte.
 
Hallo,

welche JAXB Implementierung ist momentan die ausgereifteste und wo bekomm ich sie her.

Tom hat weiter oben den schemagen verwendet. Wo kann man diesen beziehen? Möchte gerne ein wenig mit JAXB experimentieren und bin daher auf der Suche nach Quellen (wie schon gesagt: Implementationen, Tutorials, Tipps & Tricks (Benchmarking))

Vielen Dank
 
Zurück