JAXB Java API for XML Binding The Objective JAXB is concerned with the translation process between Java objects and XML documents • You have a Java object and want to write it to XML • You have an XML document and want to turn it into Java object(s) Demo code at https://www.movesinstitute.org/~mcgredo/D emos Tasks There are several possible starting points for working with Java and XML: • Write a Java class that can be marshaled to XML • Given a Java class in “java bean” format, generate an XML schema • Given an XML schema, generate Java classes that can read and write XML This intro assumes JDK 1.6 (which incorporates Jaxb 2.x) Annotations Annotations are a new feature of JDK 1.5 and later. Essentially they are markers in the Java source code that can be used by external tools to generate code Format looks like @ThisIsAnAnnotation(foo=“bar”) Annotations can occur only in specific places in the code, including before a class definition, before a method declaration, before an ivar, etc. /** annotations can appear before a method */ @XmlElement Public float getX() { return x;} Java to XML POJO (Plain Old Java Object) to XML. Assume that you want to make a Java class writeable to XML. Suppose you have this: public class Point { float x; float y; } With a getter and setter for each in javabeans format, eg public void setX(float x) public float getX() Annotations Markup See source code. Things to note: • @XmlAttribute to designate a field as an attribute rather than an element. The field must be a primitive schema type (float, int, etc) • @XmlRootElement to designate the document root element. You can also specify a namespace • @XmlElementWrapper to specify the element that encloses a repeating series of elements • Note that you should specify only the getter method as @XmlAttribute. Jaxb oddly treats both the field and the getter method as independent entities • Use @XmlTransient to annotate things that should not be marshalled to XML. Generate an XML Schema from Java Code Suppose you already have Java code (annotated or not) and want to generate an XML schema. How do you do this? JDK 1.6 includes schemagen in the jdk/bin directory, which can accomplish this. Typically you do this with an Ant task, but it’s simpler to show this from the command line Schemagen Note that schemagen can operate on any javabeans compliant class, not just annotated ones. • if it has in ivar called “foo”, it must have getFoo() and setFoo() • No-args constructor Generate XML Schema from Java C:\Program Files\java\jdk1.6.0_03\bin\schemagen -cp src\edu\nps\moves\demo src\edu\nps\moves\demo*.java Places the schema into schema1.xsd Fragment from Schema <xs:complexType name="point"> <xs:sequence/> <xs:attribute name="x" type="xs:float" use="required"/> <xs:attribute name="y" type="xs:float" use="required"/> <xs:attribute name="z" type="xs:float" use="required"/> </xs:complexType> What Happened? This illustrates one of the possible starting points: you have Java classes, and want a corresponding XML schema. We just generated that schema Generate Java from Schema This is another possible starting point: you have an XML schema, and want to create Java classes that correspond to that JAXB can generate simple java beans classes with getters and setters that know how to unmarshall themselves from XML This simplifies the parsing process for small-tomedium XML documents: use JAXB to read it into Java classes xjc The program that does this is xjc, also included in the bin director of the JDK The command: "c:\Program Files\Java\jdk1.6.0_03\bin\xjc" -d src\jaxb -p edu.nps.moves.jaxb schema1.xsd -p specifies the package the generated java will use, -d the directory to which the classes should be written, schema1.xsd the schema to use when creating the Fragment of generated code public class Point { @XmlAttribute(required = true) protected float x; @XmlAttribute(required = true) protected float y; ObjectFactory You generally create new instances of the generated classes via ObjectFactory See Usage.java class for examples NOTE: for obscure reasons, JAXB does not insert the @XmlRootElement annotation where it “should”. The easiest way to handle this is to just add the annotation manually to the Points class, the root element of the document. There are other workarounds, but they appear to be experimental right now Marshalling See Usage.java for full examples of marshalling and unmarshalling to XML JAXBContext context = JAXBContext.newInstance(Points.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(pointContainer, new FileOutputStream("example.xml")); Unmarshalling Unmarshaller unmarshaller = context.createUnmarshaller(); Points unmarshalledObject = (Points)unmarshaller.unmarshal(new FileInputStream("example.xml")); What Happened? • Annotate a POJO Java class so we can marshal & unmarshall it to XML • Given a Java class, generate an XML schema • Given an XML schema, generate Java classes