JAXB is a Java Api for for Marshalling and UnMarshalling XML Data. The idea is that you bind an XML Schema to an object and then use this schema-bound object to marshall or unmarshall XML Data. Using this API you can transform any XML document into a java object and any java object into an XML document.
So how is it done. Here is a summery of the steps:
- Create an XSD file that describes structure of your XML document
- Execute xjc command from command prompt and pass package and .xsd file as parameters
Well that's it really, this will generate the java files in the given package. It will generate the complete package/directory structure according to the given parameter.
Let's try that using an example XSD file.
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> <xs:element name="Contacts"> <xs:complexType> <xs:sequence> <xs:element maxOccurs="unbounded" ref="Contact"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Contact"> <xs:complexType> <xs:sequence> <xs:element ref="FirstName"/> <xs:element ref="LastName"/> <xs:element ref="PhoneNumber"/> </xs:sequence> <xs:attribute name="id" use="required" type="xs:integer"/> </xs:complexType> </xs:element> <xs:element name="FirstName" type="xs:string"/> <xs:element name="LastName" type="xs:string"/> <xs:element name="PhoneNumber" type="xs:integer"/> </xs:schema>
Save the above as contacts.xsd and then generate Java files using JAXB compiler. * xjc [file.xsd] -p [package]
> xjc contacts.xsd -p test.jaxb.contact parsing a schema... compiling a schema... test\jaxb\contact\Contact.java test\jaxb\contact\Contacts.java test\jaxb\contact\ObjectFactory.java
This will create all the required classes for you in the given package. In our case you can see the package name is test.jaxb.contact so the classes are generated in this package. The compiler will also create necessory folders for you to place java fiels, i.e. all you need to do is to provide a package name and the rest is automatically handled.
Now let's do the Marshalling and UnMarshalling of some XML data using these generated java files. Marshalling means writing XML data and UnMarshalling means reading XML data. We will do the UnMarshalling first and the we will see how to do the Marshalling.
Un-Marshalling:
Now lets create a sample XML file and load the data in the XML file to our java objects. I am creating a sample file with some famous hollywood names.
<?xml version="1.0" encoding="UTF-8"?> <Contacts> <Contact id="2002"> <FirstName>Will</FirstName> <LastName>Smith</LastName> <PhoneNumber>0192824546</PhoneNumber> </Contact> <Contact id="2008"> <FirstName>Bruce</FirstName> <LastName>Willis</LastName> <PhoneNumber>0138542756</PhoneNumber> </Contact> <Contact id="2029"> <FirstName>Julia</FirstName> <LastName>Roberts</LastName> <PhoneNumber>0138452168</PhoneNumber> </Contact> <Contact id="2086"> <FirstName>Kate</FirstName> <LastName>Hudson</LastName> <PhoneNumber>0169485324</PhoneNumber> </Contact> </Contacts>
Now create a simple java file to Unmarshal this XML data. I am not going into the details of File Handlilng, here is a method that will take the InputStream that you can create for the file and then using that InputStream it will Unmarshal the XML data.
// Create an Input Stream for the XML file // and pass the Stream as a method parameter private static void unmarshalXMLData(InputStream is) throws Exception{ // Context is the name of package String context = "test.jaxb.contact"; // Create an instance of JAXB Context JAXBContext jContext = JAXBContext.newInstance(context); // Unmarshal the data from InputStream Contacts contacts = (Contacts) jContext.createUnmarshaller().unmarshal(is); Listcontact = contacts.getContact(); // Lets see the results. for (Contact c : contact) { System.out.println(c.id+""+c.firstName+""+c.lastName+""+c.phoneNumber); } }
And when this method is executed, it produced the following results for the given XML file.
2002 Will Smith 192824546 2008 Bruce Willis 138542756 2029 Julia Roberts 138452168 2086 Kate Hudson 169485324
OK, so the Unmarshalling was easy, we successfully created some java objects and loaded data into these java objects using JAXB. Now let's see how to pulish the XML data from your java objects.
Marshalling:
Let's stick to the same conventions, just for the ease of use. To generate the XML data from our java classes, all we need to do is to tell the Marshaller what it needs to write and where.
Again I am not going into the details of File Handling, here is a method that takes the PrintWriter object as a parameter and writes the XML data to that writer.
private static void marshalXML(PrintWriter out) throws Exception{ // Context is the name of package String context = "test.jaxb.contact"; // Initialise JAXB Context JAXBContext jc = JAXBContext.newInstance(context); // Always use factory methods to initialise XML classes ObjectFactory factory = new ObjectFactory(); Contacts contacts = factory.createContacts(); // Now create some sample contacts Contact c = new Contact(); c.setId(new BigInteger("2098")); c.setFirstName("Jonny"); c.setLastName("Depp"); c.setPhoneNumber(new BigInteger("2646215098")); // Always use the get methods for adding more objects to a collection contacts.getContact().add(c); c = new Contact(); c.setId(new BigInteger("2168")); c.setFirstName("Anthony"); c.setLastName("Hopkins"); c.setPhoneNumber(new BigInteger("2646546879")); // Add the new Object to collection contacts.getContact().add(c); // Now Create JAXB XML Marshallar Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE ); // Write the XML File m.marshal(contacts, out); }
This method will initialize the Marshaller and will marshal the data to the PrintWriter. Fortunately PrintWriter is not the only option for you. You can also send data to any OutputStream or even to a ResultSet. Executing this piece of code will generate an XML file that will look something like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <Contacts> <Contact id="2098"> <FirstName>Jonny</FirstName> <LastName>Depp</LastName> <PhoneNumber>2646215098</PhoneNumber> </Contact> <Contact id="2168"> <FirstName>Anthony</FirstName> <LastName>Hopkins</LastName> <PhoneNumber>2646546879</PhoneNumber> </Contact> </Contacts>
That's it really. From here on you can now create your own XSD documents to take advantage of JAXB. What I really like about that is that I dont have to worry about the XML formatting of my data when I am reading or writing XML data to an external resource. The JAXB API takes care of almost all of the possible scenarios where you have to manually handle the text in an XML document.
As far as XML is concirned, almost everyone now a days os familiear with it, however, not everyone feels comfortable with the XML Schema fiels (XSD). For those of you who are not comfortable with creating the XSD files, I would suggest using the XML to XSD converters. There are loads of converters available there on the internet if you search for the term XML to XSD.
My favourite is the trang-xml XML to XSD converter. This is a very simple jar file that you can use to generate an XSD document from any XML. Using Trang is very simple, all you need to do is to execute the following command from the command prompt and it will generate an XSD file for you from the given XML file.
java -jar trang.jar contacts.xml contacts.xsd
This sounds excellent, however, whenever you are using any XML to XSD generator, always use it with caution. The automated process that will identify the data types from your XML document to generate an XSD, is never going to be absolutely correct. There are always areas where you have to make neccessory changes to the XSD file after generating it using any convertor.
No comments:
Post a Comment