Engineering Full Stack Apps with Java and JavaScript
JAXB 2.x support bidirectional binding between xml schema (XSD) and java classes - binding from XML schema (XSD) to create java classes and binding of Java classes to create XML Schema components.
Here we will see binding from XML schema (XSD) to create JAXB classes and and then do marshalling and unmarshalling.
To bind from XML schema (XSD) to create JAXB classes, first we need to create an XSD and provide this as the input to the JAXB compiler, wihch creates the required JAXB classes.
In this example, we will first create a sample xml and then write (or generate) an xsd for it, then using the xsd, we will create the java stub code corresponding to the xsd and finally do marshaling and unmarshaling using the generated code.
Step 1: Setting-Up the environment
You need to have a java jee eclipse (indigo or above) with Java SE 6 or above. JAXB 2.x is now part of Java SE 6 and above; and hence we won’t need to import any jaxb related jars for this example.
Step 2: Create an XSD
Create or copy paste an xsd in the project folder.
I will use the below xml to create an xsd:
<hello>
<greeting>Hello</greeting>
<name title="Mr">Heartin</name>
</hello>
I have written an xsd as below based on the above xml:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
jxb:version="2.0">
<xsd:element name="hello" type="helloType"/>
<xsd:complexType name="helloType">
<xsd:sequence>
<xsd:element name="greeting" type="xsd:string"/>
<xsd:element name="name" type="nameType"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="nameType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="title" type="titleType">
</xsd:attribute>
</xsd:extension>
</xsd:simpleContent>
</xsd:complexType>
<xsd:simpleType name="titleType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="Mr"/>
<xsd:enumeration value="Mrs"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Save it with .xsd extension.
Step 3: Generate the java stub code corresponding to the xsd
Traditionally we had to use the xjc schema compiler from command prompt or an ant build for generating java code from xsd. However the current Jee eclipse provide inbuilt support for generating the JAXB java classes and interfaces from input xsd. Just right click the xsd and generate jaxb classes.
In the dialog, give a package structure as below and click finish. We will leave other options as is.
JAXB defines a default binding rule, which we can override binding through custom binding declarations. These custom binding rules can be specified inline within the schema or in a separate XML binding declaration document. The external binding file can be included as well in the above dialog, but for this example we won’t specify any custom binding except for the generated package and use the default JAXB binding rules.
The java files will be generated in the specified package.
Now, create a java class JaxbExample.java in the package com.javajee.jaxb2. We will do our marshaling and unmarshaling logic here using the generated classes.
Marshaling an XML document means to create an XML document from Java classes. To marshal an xml document, you need to follow these steps:
1. Create a JAXBContext object with its static method newInstance(String contextPath).
2. Use the JAXBContext object to create a Marshaller object.
3. Create an instance of the generated ObjectFactory object.
4. Using the ObjectFactory object, create an object tree starting with the root object.
5. Populate these tree objects with the relevant data using the appropriate setter methods.
6. Create a JAXBElement<RootType> object of the RootType using the appropriate factory method. JAXBElement<RootType> represents the root element in XML document.
7. Finally, call the marshal method passing the JAXBElement for root and an output stream to print the result.
1. Create a JAXBContext object with its static method newInstance(String contextPath).
JAXBContext jaxbContext = JAXBContext.newInstance("com.javajee.jaxb2.generated");
2. Use the JAXBContext object to create a Marshaller object.
Marshaller marshaller=jaxbContext.createMarshaller();
3. Create an instance of the generated ObjectFactory object.
ObjectFactory factory = new ObjectFactory();
4. Using the ObjectFactory object, create an object tree starting with the root object.
HelloType hello = factory.createHelloType();
NameType name=factory.createNameType();
5. Populate these tree objects with the relevant data using the appropriate setter methods.
hello.setGreeting("Hello");
TitleType title=TitleType.MR;
name.setValue("Heartin");
name.setTitle(title);
hello.setName(name);
6. Create a JAXBElement<RootType> using the factory method.
JAXBElement<HelloType> helloElement = factory.createHello(hello);
JAXBElement represents the root element in XML document.
7. Finally, call the marshal method passing the JAXBElement for root and an output stream to print the result.
marshaller.marshal(helloElement,System.out);
Unmarshaling means creating a Java object tree from an XML document. In case of converting from an xml document to java objects, the xml document is the starting point. So first, we need to create an xml document. We will use the same xml. Save it into a file hello.xml in the eclipse project folder. To unmarshal, we need to follow these steps:
1. Create a JAXBContext object with its static method newInstance(String contextPath)
2. Use the JAXBContext object to create an UnMarshaller object.
3. Create a JAXBElement object of type root using the unmarshal method of Unmarshaller.
4. Create root object type from the JAXBElement object using its getValue() method.
5. Use appropriate getters of root object to get its attributes and children.
1. Create a JAXBContext object with its static method newInstance(String contextPath)
JAXBContext jaxbContext = JAXBContext.newInstance("com.javajee.jaxb2.generated");
2. Use the JAXBContext object to create an UnMarshaller object.
Unmarshaller unMarshaller=jaxbContext.createUnmarshaller();
3. Create a JAXBElement object of type root using the unmarshal method of Unmarshaller.
JAXBElement<HelloType> helloElement = (JAXBElement<HelloType>) unMarshaller.unmarshal(new File("hello.xml"));
4. Create root object type from the JAXBElement object using its getValue() method.
HelloType hello = helloElement.getValue();
5. Use appropriate getters of root object to get its attributes and children.
String greeting=hello.getGreeting();
String name=hello.getName().getValue();
TitleType title=hello.getName().getTitle();
System.out.println(greeting+" "+title.value()+" "+name);
Though we are using the eclipse feature now to generate java classes from xsd, traditionally we had to use the xjc schema compiler from command prompt or from an ant build. The xjc schema compiler tool generates the required interfaces and classes from the schema. The xjc compiler takes as input the xml schema, optionally the external binding declarations file and then generates the required interfaces and classes, including the ObjectFactory class as we have seen. The xjc generated classes do all the low-level work associated with parsing, validating, element accessing, marshaling, and unmarshaling.
Important xjc Command Options are:
To run the JAXB 2.0, you needed JWSDP 2.0. However JAXB 2.x is now part of Java SE 6 and above; and we will use it. JAXB 2.0 requires at least Java 5.0 because JAXB 2.0 uses parameterized types and annotations. While working in eclipse, we need to make sure our Java build path shows all required JARs and if you are using java 6 or above, it is already there. In older or non-Jee versions of Eclipse, we needed to configure xjc as an eclipse external tool as below or use an ant build.
However in latest Jee eclipse, you can simply right click an XSD and generate the java classes specifying package structure and bindings.