Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java JaxB - Object to XML String to Object

Tags:

xml

jaxb

I have an issue using JaxB in Netbeans 7.1.2.

I have auto-generated my classes from a schema using JaxB (New JaxB Binding). I am creating the object that will be serialized to an XML string using the Marshaller and then back to a new object instance from the XML String. However, I get the following exception:

javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.somewhere.com/some/path", local:"MyQueryComplexTypeQuery"). Expected elements are (none)

The marshalling/serializing to XML string works fine. It's when it is unmarshalled/deserialized that is causing the issue.

I am using the following code to build the object and marshal it to an XML string:

// build the object
ObjectFactory of = new ObjectFactory();

MyQueryComplexType oaaqc = of.createMyQueryComplexType();
oaaqc.setField1("edit");
oaaqc.setField2("net");
oaaqc.setField3("24");

JAXBElement<MyQueryComplexType> createMyQueryComplexType = of.createMyQueryComplexTypeQuery(oaaqc);

// serialise to xml
StringWriter writer = new StringWriter();
JAXBContext context = JAXBContext.newInstance(MyQueryComplexType.class);            
Marshaller m = context.createMarshaller();
m.marshal(createMyQueryComplexType, writer);

// output string to console
String theXML = writer.toString();
System.out.println(theXML);

This produces the following XML (formatted) in the console:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MyQueryComplexTypeQuery xmlns="http://www.somewhere.com/some/path">
    <Field1>edit</Field1>
    <Field2>net</Field2>
    <Field3>24</Field3>
</MyQueryComplexTypeQuery>

Now I come to deserialize/unmarshal the string to a new instance MyQueryComplexType with the following code:

Unmarshaller u = context.createUnmarshaller();
MyQueryComplexTypeQuery o = (MyQueryComplexType) u.unmarshal(new StringReader(theXML));

In the auto generated package-info.java it has the following contents:

@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.somewhere.com/some/path", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package MyProject.SomeNamespace.MyQuery;

I thought the simple process of object -> string -> object would work. This is the first time I've used JaxB (so be gentle). I have seen other posts mentioning the namespaces, and everything looks ok to me. I've auto generated the classes from the schema, constructed the object, marshalled to xml string. I thought simply reversing the process for unmarshal would be similar.

The actual exception is thrown on line:

MyQueryComplexTypeQuery o = (MyQueryComplexType) u.unmarshal(new StringReader(theXML));

I thought I was doing the unmarshalling from string to object would be simple. I don't know if I am doing something wrong or missing something. I hope you guys can shed some light or open my eyes.

I have cut down the code to simplify what is in my app that causes the error. Namespaces have been changed to protect the identity of things on the web.

Any thoughts?

Thanks

Andez

like image 373
Andez Avatar asked Nov 08 '12 12:11

Andez


People also ask

How do you Unmarshal a string?

To unmarshal an xml string into a JAXB object, you will need to create an Unmarshaller from the JAXBContext, then call the unmarshal() method with a source/reader and the expected root object.

How do you cast an Object to a string in Java?

We can convert Object to String in java using toString() method of Object class or String. valueOf(object) method. You can convert any object to String in java whether it is user-defined class, StringBuilder, StringBuffer or anything else.

How does JAXB read XML?

To read XML, first get the JAXBContext . It is entry point to the JAXB API and provides methods to unmarshal, marshal and validate operations. Now get the Unmarshaller instance from JAXBContext . It's unmarshal() method unmarshal XML data from the specified XML and return the resulting content tree.


1 Answers

Creating the JAXBContext

For JAXB models that are generated from an XML schema you could create the JAXBContext on the package name rather than on a particular class:

JAXBContext context = JAXBContext.newInstance("your.package.name");

Not:

JAXBContext context = JAXBContext.newInstance(MyQueryComplexType.class);  

This will ensure that the ObjectFactory class that contains the @XmlElementDecl annotations is processed correctly which is what is missing from your use case.

Unmarshal Operation

Note that during your marshal operation you needed to wrap your instance of MyQueryComplexType in a JAXBElement? This is because MyQueryComplexType was not annotated with @XmlRootElement and the root element information needed to come from the JAXBElement. This means that when you do the unmarshal operation you will get a JAXBElement back as well.

JAXBElement<MyQueryComplexTypeQuery> o = (JAXBElement<MyQueryComplexType>) u.unmarshal(new StringReader(theXML));

Not:

MyQueryComplexTypeQuery o = (MyQueryComplexType) u.unmarshal(new StringReader(theXML));

For More Information

  • http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.html
like image 115
bdoughan Avatar answered Sep 17 '22 15:09

bdoughan