JAXB - Unmarshalling and avoiding the DOM

JAXB is a great tool for working with XML and Java, but it can be very confusing. We encountered a situation where JAXB generated DOM objects (elementNsImpl), instead of JAXB objects, when unmarshalling. This occurred when working with the CIM (Common Information Model) standard, CIM_INUP message. The INUP message has a HeaderType with an any element with lax set to true as shown in the code below.

CIM_INUP HeaderType

@XmlAccessorType(XmlAccessType.FIELD)
 
@XmlType(name = "HeaderType", propOrder = {
 
…
 
public class HeaderType {
 
…
 
@XmlAnyElement(lax = true)
 
protected List<Object> any;
 
…
 
}

This can give you both JaxbElement Objects and Dom objects. It all depends on how you handle the element. According to Blaise Doughan such for such elements this depends on:

if an element is associated with a class via @XmlRootElement or @XmlElementDecl then an instance of the corresponding class will be used to populate the field if not the element will be set as an instance of org.w3c.dom.Element.

As shown in the figure below, if the element is associated XmlRootElement or XmlElementDecl it will generate JAXB element Objects. On the other hand if it not associated it will generate DOM objects.

JAXBDomOrObject

In our case we had no XmlElementDecl association in our ObjectFactory to the relevant element, nor did we have XmlRootElement. To solve this problem we used an additional objectFactory called cim_namm. It had an ElementDecl for the element (SupplierTaskID) and XmlRootElements for one other element (STATUS). The additional objectFactory had to be set in the JAXBContext as shown below. This solution gave us JAXB elements for SupplierTaskID when unmarshalling.

Setting the objectFactory:

cimDataFormat = new JaxbDataFormat(JAXBContext.newInstance(TIFINUPTYPE.class, ObjectFactory.class));

ElementDecl for SupplierTaskID in the CIM_NAMM objectFactory:

@XmlElementDecl(namespace = "CIM_NAMM", name = "ElWinTaskID")
public JAXBElement<String> createElWinTaskID(String value) {
return new JAXBElement<String>(_ElWinTaskID_QNAME, String.class, null, value);
}

XmlRoot for Status:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(
...)
@XmlRootElement(
name = "status"
)
public class Status {
...

Related stories