Thursday, July 25, 2013

How to convert XML to Java object and vice versa in runtime?

Well the obvious choice would be to use JaxB, due to its familiarity. Let us see it with a simple example. JAXB is governed by the same team as Glassfish. JAXB comes by default with JDK1.6+. JAXB stands for Java Architecture for XML Binding.

XML has become a common form of data storage in many applications and for webservices. There are two common operations that are required while dealing with XML from Java. Read an xml file and convert it to a Java object, and write a Java object to an xml file.

JAXB does both the above said operations and those operations are called as
  1. Marshalling – Convert a Java object into a XML.
  2. Unmarshalling – Convert a XML into a Java Object.
Let us see this with an example,
Marshalling: Converting Java object to XML
Its a simple process, lets see this with a sample program
Output
While running the above example you will run into the following exception,

Exception in thread "main" javax.xml.bind.MarshalException
 - with linked exception:
[com.sun.istack.internal.SAXException2: unable to marshal type "com.ananth.samples.Employee" as an element because it is missing an @XmlRootElement annotation]
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:317)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:243)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:75)
at com.ananth.samples.Java2XMLExample.main(Java2XMLExample.java:20)
Caused by: com.sun.istack.internal.SAXException2: unable to marshal type "com.ananth.samples.Employee" as an element because it is missing an @XmlRootElement annotation
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:216)
at com.sun.xml.internal.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:286)
at com.sun.xml.internal.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:462)
at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:314)
... 3 more

To fix the above exception you have to add an @XmlRootElement annotation to your Employee Pojo.
Instead of System.out you can point to the File to which you want to write the output during jaxbMarshaller.marshal(employee, file);. Once make the change while rerunning the sample will give your the following output.
UnMarshalling: Converting XML to Java object
Its a simple process, lets see this with a sample program
Now, I had a question why do I should I have a @XmlRootElement annotation in my pojo.  Cant I do I deal with my existing POJOs of my application?
The answer is you cant do it with JAXB but there are other options like XStream. I have referred their two minutes tutorial and it really look me only 2 minutes to try it out.
Add the XStream maven dependency and after that it is as easy as calling toXML and fromXML methods of XStream object.


6 comments:

  1. This is really a good tutorial. It shows how easy it is to make use of JaxB for marshalling and Unmarshalling. I know the pain of making use of other binding frameworks like JibX where you need to modify so many lines of code in mapping xml (though mapping files are created automatically by JibX) files which should be included pom.xml to make the information available for marshalling/unmarshalling during runtime.

    It would be more interesting if you could also say how to create java objects from XSD automatically using any utility available for JaxB.

    ReplyDelete
    Replies
    1. Thanks for those encouraging comments. XSDs can be used to define how your objects are going to be, and not the actual content. If you are talking about how to generate the class files based on the XSD definition, sure I will write up something on it soon.

      Delete
  2. This is such a great tutorial for jaxb, easy to understand the conversion process and all. thanks a lot

    ReplyDelete
  3. Actually i don't have idea about JAXB , i planed to know what is JAXB for that just i searched in google i found your link. the way you explained it's very neat and clean i had some idea about JAXB. Thanks for helping others

    ReplyDelete
  4. In situations where a schema is used to validate the given XML document, what do we do? If the schema is mentioned in the XML document, will JAXB automatically validate the XML against the specified Schema?
    Thanks..!

    ReplyDelete
    Replies
    1. Yes it does if you set the schema to the marshaller, for ex:

      SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
      Schema schema = schemaFactory.newSchema(locationOfMySchema);

      Marshaller marshaller = jaxbContext.createMarshaller();
      marshaller.setSchema(schema);

      marshal() operation will throw a JAXBException if validation against the schema fails.

      Delete