Engineering Full Stack Apps with Java and JavaScript
JAXB 2.x support bidirectional binding between xml schema and java objects - binding from XML schema to java classes and binding of Java classes to XML Schema components.
Here we will do java to xsd binding and then do marshaling and unmarshaling.
To generate XML Schema content from a Java class using the JAXB 2.0, we need to first define a class using binding annotations. We can create a JAXBContext from this class and do marshaling and unmarshaling. We can also apply the schemagen tool to generate a schema definition from this class.
In JAXB2, annotations are used both in generated Java content classes and in Java classes as input to generate schema definitions. Some of the more commonly used annotations defined in the javax.xml.bind.annotation package can be found @ http://javajee.com/introduction-to-jaxb-2.
We will first create the annotated Java class required to generate the xml and schema. We will try creating the annotated class to generate a simple xml as below:
<hello>
<greeting>Hello</greeting>
<name>Heartin</name>
</hello>
First, create a java project in eclipse with java version 6 or above. Create a simple class as below:
package com.javaee.jaxb2;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class HelloBinding {
private String greeting;
private String name;
public String getGreeting() {
return greeting;
}
@XmlElement
public void setGreeting(String greeting) {
this.greeting = greeting;
}
public String getName() {
return name;
}
@XmlElement
public void setName(String name) {
this.name = name;
}
}
Note that we have used @XmlElement over the setters rather than on fields; and that is a good practice. In this example we can’t use this annotation over the fields as we have getters which will also resolve to the same name. Check it out if you want.
Now, create a java class JaxbExample2.java in the package com.javajee.jaxb2. We will do our marshaling and unmarshaling logic here using the annotated class.
Marshaling an XML document means to create an XML document from Java classes.
To marshal an xml document with java to xml binding, you need to follow these steps:
1. Create an object of the annotated class and populate data.
2. Create a JAXBContext object with JAXBContext’s static method newInstance(Class... classesToBeBound).
3. Use the JAXBContext object to create a Marshaller object.
4. Finally, call the marshal method passing the object of the annotated class representing root and an output stream to print the result.
Steps in detail:
1. Create an object of the annotated class and populate data.
HelloBinding hbinding = new HelloBinding();
hbinding.setGreeting("Hello");
hbinding.setName("Heartin");
2. Create a JAXBContext object with JAXBContext’s static method newInstance(Class... classesToBeBound).
JAXBContext jaxbContext = JAXBContext.newInstance(HelloBinding.class);
3. Use the JAXBContext object to create a Marshaller object.
Marshaller marshaller=jaxbContext.createMarshaller();
You can optionally format the displayed output as below:
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
4. Finally, call the marshal method passing the object of the annotated class representing root and an output stream to print the result.
marshaller.marshal(hbinding, 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 input. So first, we need to create an xml document like:
<hello>
<greeting>Hello</greeting>
<name>Heartin</name>
</hello>
Note: Use the same xml we generated before.
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 JAXBContext’s static method newInstance(Class... classesToBeBound).
2. Use the JAXBContext object to create an UnMarshaller object.
3. Create an object of the annotated type representing root using the unmarshal method of Unmarshaller.
4. Use appropriate getters of root object to get its attributes and children.
Steps in detail:
1. Create a JAXBContext object with JAXBContext’s static method newInstance(Class... classesToBeBound).
JAXBContext jaxbContext = JAXBContext.newInstance(HelloBinding.class);
2. Use the JAXBContext object to create an UnMarshaller object.
Unmarshaller unMarshaller=jaxbContext.createUnmarshaller();
3. Create an object of the annotated type representing root using the unmarshal method of Unmarshaller.
HelloBinding hBinding = (HelloBinding) unMarshaller.unmarshal(new File("hello.xml"));
4. Use appropriate getters of root object to get its attributes and children.
String greeting = hBinding.getGreeting();
String name = hBinding.getName();
System.out.println(greeting+" "+name);
So far we have seen marshaling and unmarshaling during java to xsd binding, but did not generate a schema. We will see generating an xsd as well. JAXB provides the schemagen tool similar to xjc to generate a schema definition from a jaxb annotated class. However, eclipse also currently provides that feature inbuilt and we will see how to do it using eclipse.
From the Navigator or Project Explorer, select File > New > Other. Then select ‘Schema from JAXB classes’ under JAXB heading.
You have to click next, select the jaxb class’s parent folder in the next screen and click next; and again in the next screen select the classes or folder and click exit.
I found that in my indigo eclipse, only from a project created as jaxb project, you can do this. However once you start from a jaxb project and click next from the above screen, you can select any project and any folder within your workspace and it will generate the xsd in the respective folder. Looks like an eclipse bug which they might fix in future.