XML binding with JAXB 1/3
I’ve been watching for an XML binding tool for one of my projects, which make use of XML to store datas.
I looked at hibernate, which now make XML bindings, but, from what I’ve seen, the binding is managed by the relational mapping. As I do not have a database in my application, I had to search elsewhere.
So I took a look at JAXB. It’s the tool I needed : you specify your xml schema, run xjc and you have your object mapping done. As example, I’ll use a schema I’m writing at the moment (phonebook.xsd). Now, all you have to write, once the classes are generated is 4 lines of code (plus catching the exceptions:
Phonebook phonebook = null; JAXBContext jc; try { // Create the context with package containing mapping classes jc = JAXBContext.newInstance(BINDING_ID); // Load the xml file Unmarshaller u = jc.createUnmarshaller(); u.setSchema(SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema( new File("phonebook.xsd"))); phonebook = (Phonebook)u.unmarshal( new FileInputStream( phonebookFilename ) ); // Do some work ... // Save the modified datas (here writes on stdout) Marshaller m = jc.createMarshaller(); m.marshal( b, System.out); } catch (SAXException e) { logger.log(Level.ERROR, "Altered schema file.", e); throw new Exception("Schema file has been altered.", e); } catch (FileNotFoundException e) { logger.log(Level.ERROR, "Phonebook file not found.", e); throw new Exception("Phonebook file not found."); } catch (JAXBException e) { logger.log(Level.ERROR, "Corrupted phonebook file ", e); throw new Exception("Corrupted phonebook file "); }
Let’s comment the source :
- Create a context : the constant BINDING_ID is the package name of the generated xml binding classes.
- Create the unmarshaller : the object that will read the xml file and bind it to objects
- Set the schema of the xml file read to assume xml validation
- Unmarshal : load the file in the objects
But you have three things to know to better use it : first if you want to directly unmarshal to your root class and to write an object representation to an xml file, the master object class has to be tagged @xmlRootElement, if you want to write simplier code.
Take the following schema, that does not generate the @XmlRootElement annotation :
<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="phonebook" type="Phonebook" />; <xsd:complexType name="Phonebook"> ... </xsd:complexType>
If you use that schema, you’ll have an error (java.lang.ClassCastException: javax.xml.bind.JAXBElement cannot be cast to package.name.Phonebook
) when unmarshalling and an other (unable to marshal type "package.name.Phonebook" as an element because it is missing an @XmlRootElement annotation
) when marshalling. You’ll have to write the following java code to unmarshall and marshall without errors with the schema above :
phonebook = (Phonebook) ((JAXBElement)u.unmarshal( new FileInputStream( phonebookFilename ) )).getValue; m.marshal( new JAXBElement( new QName("", "phonebook"), Phonebook.class, phonebook ), System.out);
Instead, a better way to declare your schema (and have simplier java code) is :
<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="phonebook" >; <xsd:complexType > ... </xsd:complexType> </xsd:element>
The two others tips to knows will be the subjects of the next posts.
About this entry
You’re currently reading “XML binding with JAXB 1/3,” an entry on Java Thoughts
- Published:
- April 25, 2009 / 1:13 pm
- Tags:
- jaxb, xml binding
6 Comments
Jump to comment form | comment rss [?] | trackback uri [?]