JAXB Context expects empty namespace no matter what

JAXB Context expects empty namespace no matter what
java
Ethan Jackson

I am facing an issue when unmarshalling an XML to my XJC Schema based generated classes using JAXB. I have read every post I've found so far, trying already who knows how many things, without success.

I have generated my Java classes using xjc -d "/myDir/src" -p nodeset.generated ./UANodeSet.xsd, where UANodeSet.xsd is this.

In my Java code, I call unmarshall the NodeSet2.xml file to the generated class UANodeSet (Root element) like:

String packageName = UANodeSet.class.getPackage().getName(); JAXBContext context = JAXBContext.newInstance(packageName); Unmarshaller unmarshaller = context.createUnmarshaller(); unmarshaller.setEventHandler(event -> { System.err.println("JAXB EVENT: " + event.getMessage()); return true; // continue after error }); String filePath = "C:/Users/mr/Downloads/Opc.Ua.NodeSet2.xml"; File file = new File(filePath); JAXBElement<UANodeSet> nodeSet = (JAXBElement<UANodeSet>)unmarshaller.unmarshal(new StreamSource(file), UANodeSet.class); UANodeSet nd = nodeSet.getValue();

This outputs the following:

JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"Models"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified> JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"Aliases"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified> JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"UAObject"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified> JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"UAObject"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified> JAXB EVENT: unexpected element (uri:"http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", local:"UADataType"). Expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified>

...

and nd is populated with a UANodeSet object with null values.

I confirm I have a file named package-info.java within the same package (nodeset.generated) with the following content:

@XmlSchema( namespace = "http://opcfoundation.org/UA/2011/03/UANodeSet.xsd", elementFormDefault = XmlNsForm.QUALIFIED) package nodeset.generated; import jakarta.xml.bind.annotation.XmlNsForm; import jakarta.xml.bind.annotation.XmlSchema;

To have as reference, here is what UANodeSet looks like:

package nodeset.generated; import java.util.ArrayList; import java.util.List; import javax.xml.datatype.XMLGregorianCalendar; import jakarta.xml.bind.annotation.XmlAccessType; import jakarta.xml.bind.annotation.XmlAccessorType; import jakarta.xml.bind.annotation.XmlAttribute; import jakarta.xml.bind.annotation.XmlElement; import jakarta.xml.bind.annotation.XmlElements; import jakarta.xml.bind.annotation.XmlRootElement; import jakarta.xml.bind.annotation.XmlSchemaType; import jakarta.xml.bind.annotation.XmlType; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "namespaceUris", "serverUris", "models", "aliases", "extensions", "uaObjectOrUAVariableOrUAMethod" }) @XmlRootElement(name = "UANodeSet") public class UANodeSet { @XmlElement(name="NamespaceUris") protected UriTable namespaceUris; @XmlElement(name="ServerUris") protected UriTable serverUris; @XmlElement(name="Models") protected ModelTable models; @XmlElement(name="Aliases") protected AliasTable aliases; @XmlElement(name="Extensions") protected ListOfExtensions extensions; @XmlElements({ @XmlElement(name="UAObject", type = UAObject.class), @XmlElement(name="UAVariable", type = UAVariable.class), @XmlElement(name="UAMethod", type = UAMethod.class), @XmlElement(name="UAView", type = UAView.class), @XmlElement(name="UAObjectType", type = UAObjectType.class), @XmlElement(name="UAVariableType", type = UAVariableType.class), @XmlElement(name="UADataType", type = UADataType.class), @XmlElement(name="UAReferenceType", type = UAReferenceType.class) }) protected List<UANode> uaObjectOrUAVariableOrUAMethod; @XmlAttribute(name = "LastModified") @XmlSchemaType(name = "dateTime") protected XMLGregorianCalendar lastModified; ...

Things I've tried

  1. Instantiate the JAXBContext from UANodeSet.class (JAXBContext context = JAXBContext.newInstance(UANodeSet.class);) => nothing has changed
  2. Add manually namespace = "http://opcfoundation.org/UA/2011/03/UANodeSet.xsd" to @XmlTypes and/or @XmlElements @XmlRootElement => JAXBContext continues to say the expected elements are <{}models>,<{}serverUris>,<{}extensions>,<{}aliases>,<{}namespaceUris>,<{}lastModified>
  3. Removing package-info.java file completely, and add the namespace="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd" attribute everywhere (@XmlTypes, @XmlElements, @XmlRootElement) => no changes.

Basically, I cannot make my JAXBContext expect the proper namespace for the UANodeSet elements.

Any help is appreciated, I have been fighting with this since too long already.

Answer

While not a direct answer to your question, I am currently using XJC and JAXB on the exact same schema in this project: https://github.com/digitalpetri/uanodeset

I use jaxb2-maven-plugin as configured here: https://github.com/digitalpetri/uanodeset/blob/ec3c182f0c808667994951c19f1c7d2b42c46c92/uanodeset-core/pom.xml#L55-L91

Parsing the UANodeSet XML file is simply:

/** * Read and parse an XML document conforming to the <a * href="http://opcfoundation.org/UA/2011/03/UANodeSet.xsd">UANodeSet</a> schema from an {@link * InputStream}. * * @param inputStream the {@link InputStream} to read from. * @return a {@link UANodeSet}. * @throws JAXBException if an error occurs while unmarshalling. */ public static UANodeSet parse(InputStream inputStream) throws JAXBException { JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class); return (UANodeSet) jaxbContext.createUnmarshaller().unmarshal(inputStream); } }

If you can't use my project, maybe you can at least re-use some of the code.

Related Articles