WARNING: Problem creating Marshaller
javax.xml.bind.JAXBException: "com.overstock" doesnt contain ObjectFactory.class or jaxb.index
It took me a while to figure out what went wrong. So now that I've got things working correctly, I thought I'd post this example and solution to hopefully save you some time.
Given this class:1 package com.overstock; 2 3 import javax.xml.bind.annotation.XmlAccessType; 4 import javax.xml.bind.annotation.XmlAccessorType; 5 import javax.xml.bind.annotation.XmlElement; 6 import javax.xml.bind.annotation.XmlRootElement; 7 8 @XmlRootElement(name="example", namespace="http://overstock.com/example") 9 @XmlAccessorType(XmlAccessType.FIELD) 10 public class ExampleJaxbClass { 11 12 @XmlElement(required=true) 13 private String elementOne; 14 private String elementTwo; 15 16 protected ExampleJaxbClass() { 17 super(); 18 } 19 20 public String getElementOne() { 21 return elementOne; 22 } 23 public void setElementOne(String elementOne) { 24 this.elementOne = elementOne; 25 } 26 public String getElementTwo() { 27 return elementTwo; 28 } 29 public void setElementTwo(String elementTwo) { 30 this.elementTwo = elementTwo; 31 } 32 }You can easily convert it to XML via the
javax.xml.bind.Marshaller
class, like this:1 public class ExampleTest { 2 3 @Test 4 public void generateXml() throws JAXBException { 5 ExampleJaxbClass ex = new ExampleJaxbClass(); 6 ex.setElementOne("first Element Value"); 7 ex.setElementTwo("second Element Value"); 8 9 // Get a JAXB Context for the object we created above 10 JAXBContext context = JAXBContext.newInstance(ex.getClass()); 11 12 // To convert ex to XML, I need a JAXB Marshaller 13 Marshaller marshaller = context.createMarshaller(); 14 15 // Make the output pretty 16 marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 17 StringWriter sw = new StringWriter(); 18 19 // marshall the object to XML 20 marshaller.marshal(ex, sw); 21 22 // print it out for this example 23 System.out.println(sw.toString()); 24 } 25 }
Here is the XML generated by the annotations above:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:example xmlns:ns2="http://overstock.com/example">
<elementOne>first Element Value</elementOne>
<elementTwo>second Element Value</elementTwo>
</ns2:example>
Now for the problem. To create a marshaller, you first need to create a
JAXBContext
via its newInstance()
factory method. You can create a context for a specific JAXB class, as in the example above, or you can create a context for a list of packages (check out the javadoc page for more). When using the Restlet class JaxbRepresentation
(only available in Restlet 1.1m1), it uses the package version of newInstance()
, that's when I got my error above. I didn't want to create an ObjectFactory
(apparently this is another way to get around the above error), at least not yet if I could help it, so I wanted to get some more info on the jaxb.index
file. I couldn't find out much, I even looked at the JSR-222 spec. Well, it turns out that all you need to do is add class names to the file and place the file in the package (directory) where your JAXB annotated classes reside (it's similar in one way to a jpa persistence.xml file but without the xml). Here is the content of my jaxb.index
file for the example class above:ExampleJaxbClass
As you can see, its just the class name, not the fully qualified name (the package name is determined by the directory you placed the file in) or the .class
name.
If you want to test this out, we need to slightly change the test above. Modify line 10 in the unit test above to look like this:
JAXBContext context = JAXBContext.newInstance(ex.getClass().getPackage().getName());If the package
com.overstock
does not have jaxb.index
file, this change will cause the test to throw the JAXBException
. Add the file and everything works great.
If you know where there is good documentation on this let me know I couldn't find any :-)
Code formatting courtesy of Code2HTML.