From object to XML

JAXB (Java Architecture for XML Binding) provides an easy way of converting Java objects to XML. In the JAXB jargon, this is know as marshalling, where unmarshalling means the opposite action of extracting a Java object from an XML.

As a first example, let's see how to create an XML fragment like this:
<user id="42" rating="4.2">Bill</user>
from a Java class named User that has the user name, id, and rating as data member.

Even if this looks like a pretty simple job, still there are a couple of points that it could be interesting to pay attention to. Large part of the JAXB job is done by annotations, with the result that the code looks quite simple to understand at first sight, once you know what it is going on.

In this case, I want my class User to have a couple of annotations, one to state that it represents a root XML element, and the second one to let JAXB know that I want to put an annotation to the data fields, and not to their getters, to specify their XML role.

The result is something like this:
@XmlRootElement // 1
@XmlAccessorType(XmlAccessType.FIELD) // 2
public class User {
    @XmlValue
    private String name;
    @XmlAttribute
    private int id;
    @XmlAttribute
    private float rating;

    // getters and setters follow ...
}
1. This class is the root element for my XML
2. If you don't explicitly say that the accessor type should be found in the field definition, JAXB gets confused. If you comment this line out, you get an IllegalAnnotationsException, and a message saying that "Class has two properties of the same name".

Once you have defined your JAXB annotated class, it is just a matter of creating an object, and marshalling:
public String obj2xml(User user) {  
    try {
        JAXBContext ctx = JAXBContext.newInstance(User.class); // 1
        Marshaller marshaller = ctx.createMarshaller(); // 2
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); // 3

        StringWriter sw = new StringWriter();
        marshaller.marshal(user, sw); // 4
        return sw.toString();
    }
    catch (JAXBException e) { // 5
        e.printStackTrace();
        return "<bad />";
    }
}
1. Create a JAXB context that knows about the User class.
2. Then from the context we get a marshaller.
3. Here I want to generate just an XML fragment, if I want to generate a full XML document, I would remove this line, and the generated XML would have this header:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
4. Ask the marshaller to send its output to a StringWriter, from which the resulting XML could be extracted as a String.
5. In case of anything goes wrong, give an alarming feedback to the user (not a very polite thing to do, but here it will suffices) but still return a valid XML.

The full Java source code for the User class and a Main class using it are on github.

No comments:

Post a Comment