jaxb unmarshal Expected elements are (none)

Classes with XmlRootElement can be unmarshalled from XML elements simply by invoking the unmarshal method that takes one parameter. This is the simplest mode of unmarshalling.

Unmarshalling with @XmlRootElement
@XmlRootElement
class Foo {
  @XmlAttribute
  String name;
  @XmlElement
  String content;
}

Unmarshaller u = ...;
Foo foo = (Foo)u.unmarshal(new File("foo.xml"));
foo.xml
<foo name="something">
  <content>abc</content>
</foo>

However, sometimes you may need to unmarshal an instance of a type that does not have an XmlRootElement . For example, you might dynamically find out at the runtime that a certain element has a certain type. For example, the following document illustrates an XML instance where the content of <someOtherTagName> element is represented by the Foo class. If we use the above code, it would probably throw: “Expected elements are (none)” Exception. So we need to:

foo2.xml
<someOtherTagName name="something">
  <content>abc</content>
</someOtherTagName>

To unmarshal this into a Foo class, use the version of the unmarshal method that takes the ‘expectedType’ argument, as follows:

Unmarshalling into a known type

Unmarshaller u = ...;
JAXBElement<Foo> root = u.unmarshal(new StreamSource(new File("foo.xml")),Foo.class);
Foo foo = root.getValue();

next

I. Marshal when @XMLRootElement is missing

Marshalling is the process of transforming the memory representation of an object to a data format suitable for storage or transmission. In the case of JAXB it means converting a Java object into XML. The below code snippet shows the creation of a new Car instance.

1
2
3
4
car = new Car();
car.setMake("Passat");
car.setManufacturer("Volkswagen");
car.setId("ABC-123");

The method below takes as input the above car object and tries to marshal it using JAXB.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static String marshalError(Car car) throws JAXBException {
    StringWriter stringWriter = new StringWriter();
    JAXBContext jaxbContext = JAXBContext.newInstance(Car.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    // format the XML output
    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    jaxbMarshaller.marshal(car, stringWriter);
    String result = stringWriter.toString();
    LOGGER.info(result);
    return result;
}

When running the above method, the runtime returns an error as the Car class is missing the required @XMLRootElement annotation.

1
2
unable to marshal type "info.source4code.jaxb.model.Car" as an
element because it is missing an @XmlRootElement annotation

In order to be able to marshal the car object we need to provide a root XML element. This is done as shown below by first creating a qualified name which contains the name and namespace of the root XML element. In a next step we create a new JAXBElement and pass the qualified name, class and object. Using the created JAXBElement we call themarshal() method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static String marshal(Car car) throws JAXBException {
    StringWriter stringWriter = new StringWriter();
    JAXBContext jaxbContext = JAXBContext.newInstance(Car.class);
    Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
    // format the XML output
    jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    QName qName = new QName("info.source4code.jaxb.model", "car");
    JAXBElement<Car> root = new JAXBElement<Car>(qName, Car.class, car);
    jaxbMarshaller.marshal(root, stringWriter);
    String result = stringWriter.toString();
    LOGGER.info(result);
    return result;
}

This time JAXB is able to successfully marshal the object and the result is the following:

1
2
3
4
5
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:car id="ABC-123" xmlns:ns2="info.source4code.jaxb.model">
    <make>Passat</make>
    <manufacturer>Volkswagen</manufacturer>
</ns2:car>

 

More detail HERE

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s