mbmast
mbmast

Reputation: 1100

JAXB Unmarshall Error: UnmarshalException- Unexpected Element - Expected elements are (none) - @XmlRootElement NOT missing

I am having problems unmarshalling some XML. The partial stack dump looks like:

javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"properties"). Expected elements are (none)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)

Below is the XML I am trying to unmarshal, the XJC generated root element Java class, the XSD fed into XJC and finally the XJC generated ObjectFactory.

The XML I am unmarshaling:

<?xml version="1.0" encoding="UTF-8"?>
<properties program-name="EstateAccounting"
                        properties-file="EstateAccounting.properties">
                        
    <keyword-properties>
        <keyword-property type="string" name="reportDirectory" alias="rd">
            <description>
                <![CDATA[Specifies the optional report directory.  Double quotes are required if the report directory
                contains spaces.  The report directory specifies where the intermediate XML used to produce the PDF report
                and where the PDF report should be produced.]]>
            </description>
        </keyword-property>
        
        <keyword-property type="string" name="beneficiary" alias="b">
            <description>
                <![CDATA[Specifies the optional beneficary name.  Double quotes are required if the beneficiary name
                contains spaces.  When omitted, all beneficiaries are included.]]>
            </description>
        </keyword-property>
        
        <keyword-property type="string" name="date" alias="d">
            <description>
                <![CDATA[Specifies the optional date(s).  The format is mm/yyyy.  Double quotes are required 
                when specifying a date range as "start-date - end-date" (spaces optional).  When omitted,
                all dates are included.]]>
            </description>
        </keyword-property>
        
        <keyword-property type="boolean" name="isGenerateReport" alias="r">
            <description>
                <![CDATA[Indicates that a PDF report should be produced.  One report for each generated XML file will be produced.]]>
            </description>
        </keyword-property>
        
        <keyword-property type="boolean" name="isKeepIntermediateXML" alias="xml">
            <description>
                <![CDATA[Indicates that the XML file used to produce the PDF report should be retained.  Normally, when the -r option
                indicates that a PDF report should be produced, the generated intermediate XML file is deleted.]]>
            </description>
        </keyword-property>
    </keyword-properties>
    
    <positional-properties>
        <positional-property type="string" name="spreadsheet" required="false">
            <description>
                <![CDATA[The location of the input spreadsheet.]]>
            </description>
        </positional-property>
        
        <positional-property type="string" name="intermediateXML" required="false">
            <description>
                <![CDATA[The location of a previously generated EstateAccounting intermediate XML file.  This is specified when 
                 a report based on previously generated intermediate XML is required.]]>
            </description>
        </positional-property>
    </positional-properties>
    
    <mutual-properties>
        <mutual-property-set type="exclusive">
            <mutual-property name="spreadsheet"/>
            <mutual-property name="intermediateXML"/>
        </mutual-property-set>
    </mutual-properties>
</properties>

The partial XJC generated root element Java class. Note the inclusion of @XmlRootElement(name = "properties") on the Properties class:

//
// This file was generated by the Eclipse Implementation of JAXB, v3.0.2 
// See https://eclipse-ee4j.github.io/jaxb-ri 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2022.01.26 at 10:38:30 AM PST 
//

package com.mbm.properties.jaxb;

import java.util.ArrayList;
import java.util.List;
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.XmlRootElement;
import jakarta.xml.bind.annotation.XmlTransient;
import jakarta.xml.bind.annotation.XmlType;
import org.glassfish.jaxb.core.Locatable;
import org.glassfish.jaxb.core.annotation.XmlLocation;
import org.xml.sax.Locator;


/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType&gt;
 *   &lt;complexContent&gt;
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
 *       &lt;sequence&gt;
 *         &lt;element name="description" type="{urn:com-mbm-properties-jaxb}descriptionType" maxOccurs="unbounded" minOccurs="0"/&gt;
 *         &lt;element name="keyword-properties" type="{urn:com-mbm-properties-jaxb}keywordPropertiesType" minOccurs="0"/&gt;
 *         &lt;element name="positional-properties" type="{urn:com-mbm-properties-jaxb}positionalPropertiesType" minOccurs="0"/&gt;
 *         &lt;element name="mutual-properties" type="{urn:com-mbm-properties-jaxb}MutualPropertiesType" minOccurs="0"/&gt;
 *       &lt;/sequence&gt;
 *       &lt;attribute name="program-name" type="{http://www.w3.org/2001/XMLSchema}string" /&gt;
 *       &lt;attribute name="properties-file" type="{http://www.w3.org/2001/XMLSchema}string" /&gt;
 *       &lt;attribute name="debug" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" /&gt;
 *       &lt;attribute name="strict-property-retrieval" type="{http://www.w3.org/2001/XMLSchema}boolean" default="true" /&gt;
 *       &lt;attribute name="strict-command-line" type="{http://www.w3.org/2001/XMLSchema}boolean" default="true" /&gt;
 *       &lt;attribute name="usage" type="{http://www.w3.org/2001/XMLSchema}boolean" default="false" /&gt;
 *     &lt;/restriction&gt;
 *   &lt;/complexContent&gt;
 * &lt;/complexType&gt;
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "descriptions",
    "containerOfListOfKeywordProperties",
    "containerOfListOfPositionalProperties",
    "mutualProperties"
})
@XmlRootElement(name = "properties")
public class Properties
    implements Locatable
{

    @XmlElement(name = "description")
    protected List<DescriptionType> descriptions;
    @XmlElement(name = "keyword-properties")
    protected KeywordPropertiesType containerOfListOfKeywordProperties;
    @XmlElement(name = "positional-properties")
    protected PositionalPropertiesType containerOfListOfPositionalProperties;
    @XmlElement(name = "mutual-properties")
    protected MutualPropertiesType mutualProperties;
    @XmlAttribute(name = "program-name")
    protected String programName;
    @XmlAttribute(name = "properties-file")
    protected String propertiesFile;
    @XmlAttribute(name = "debug")
    protected Boolean debug;
    @XmlAttribute(name = "strict-property-retrieval")
    protected Boolean strictPropertyRetrieval;
    @XmlAttribute(name = "strict-command-line")
    protected Boolean strictCommandLine;
    @XmlAttribute(name = "usage")
    protected Boolean usage;
    @XmlLocation
    @XmlTransient
    protected Locator locator;

    .
    .
    .

    public Locator sourceLocation() {
        return locator;
    }

    public void setSourceLocation(Locator newLocator) {
        locator = newLocator;
    }
}

The XSD fed into XJC that generated the Java classes:

<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
            xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
            xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="urn:com-mbm-properties-jaxb"
            targetNamespace="urn:com-mbm-properties-jaxb"
            elementFormDefault="qualified"
            jaxb:extensionBindingPrefixes="xjc"
            jaxb:version="3.0">

    <xsd:annotation>
        <xsd:appinfo>
            <jaxb:globalBindings>
                <xjc:simple/>
            </jaxb:globalBindings>
        </xsd:appinfo>
    </xsd:annotation>
    
    <xsd:element name="properties">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="description" type="descriptionType" minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="keyword-properties" type="keywordPropertiesType" minOccurs="0" maxOccurs="1">
                    <xsd:annotation>
                        <xsd:appinfo>
                            <jaxb:property name="containerOfListOfKeywordProperties"/>
                        </xsd:appinfo>
                    </xsd:annotation>
                </xsd:element>
                <xsd:element name="positional-properties" type="positionalPropertiesType" minOccurs="0" maxOccurs="1">
                    <xsd:annotation>
                        <xsd:appinfo>
                            <jaxb:property name="containerOfListOfPositionalProperties"/>
                        </xsd:appinfo>
                    </xsd:annotation>
                </xsd:element>
                <xsd:element name="mutual-properties" type="MutualPropertiesType" minOccurs="0" maxOccurs="1"/>
            </xsd:sequence>
            <xsd:attribute name="program-name" type="xsd:string" use="optional"/>
            <xsd:attribute name="properties-file" type="xsd:string" use="optional"/>
            <xsd:attribute name="debug" type="xsd:boolean" use="optional" default="false"/>
            <xsd:attribute name="strict-property-retrieval" type="xsd:boolean" use="optional" default="true"/>
            <xsd:attribute name="strict-command-line" type="xsd:boolean" use="optional" default="true"/>
            <xsd:attribute name="usage" type="xsd:boolean" use="optional" default="false"/>
        </xsd:complexType>
    </xsd:element>

    <xsd:complexType name="PropertyBase" abstract="true">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class name="DummyPropertyBase" implClass="com.mbm.properties.baseclasses.PropertyBase"/>
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:complexType>
    
    <xsd:complexType name="PropertyType" abstract="true">
        <xsd:complexContent>
            <xsd:extension base="PropertyBase">
                <xsd:sequence>
                    <xsd:element name="description" type="descriptionType" minOccurs="0" maxOccurs="unbounded"/>
                    <xsd:element name="forValues" type="forValueType" minOccurs="0" maxOccurs="unbounded"/>
                </xsd:sequence>
                <xsd:attribute name="type" use="required">
                    <xsd:simpleType>
                        <xsd:restriction base="xsd:token">
                            <xsd:enumeration value="integer"/>
                            <xsd:enumeration value="float"/>
                            <xsd:enumeration value="boolean"/>
                            <xsd:enumeration value="string"/>
                        </xsd:restriction>
                    </xsd:simpleType>
                </xsd:attribute>
                <xsd:attribute name="name" type="xsd:string" use="required"/>
                <xsd:attribute name="required" type="xsd:boolean" use="optional" default="false"/>
                <xsd:attribute name="alias" type="xsd:string" use="optional"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    
    <xsd:complexType name="keywordPropertiesType">
        <xsd:sequence>
            <xsd:element name="keyword-property" type="keywordPropertyType" minOccurs="1" maxOccurs="unbounded">
                <xsd:annotation>
                    <xsd:appinfo>
                        <jaxb:property name="listOfKeywordProperties"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>
    
    <xsd:complexType name="keywordPropertyType">
        <xsd:complexContent>
            <xsd:extension base="PropertyType">
                <xsd:sequence>
                    <xsd:element name="challenges" type="ChallengeType" minOccurs="0" maxOccurs="unbounded"/>
                </xsd:sequence>
                <xsd:attribute name="default-value" type="xsd:string" use="optional"/>
                <xsd:attribute name="valid-values" type="xsd:string" use="optional"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="positionalPropertiesType">
        <xsd:sequence>
            <xsd:element name="positional-property" type="positionalPropertyType" minOccurs="1" maxOccurs="unbounded">
                <xsd:annotation>
                    <xsd:appinfo>
                        <jaxb:property name="listOfPositionalProperties"/>
                    </xsd:appinfo>
                </xsd:annotation>
            </xsd:element>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="positionalPropertyType">
        <xsd:complexContent>
            <xsd:extension base="PropertyType"/>
        </xsd:complexContent>
    </xsd:complexType>
    
    <xsd:complexType name="ForValueBase" abstract="true">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class name="DummyForValueBase" implClass="com.mbm.properties.baseclasses.ForValueBase"/>
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:complexType>
    
    <xsd:complexType name="forValueType">
        <xsd:complexContent>
            <xsd:extension base="ForValueBase">
                <xsd:sequence>
                    <xsd:element name="description" type="descriptionType" minOccurs="0" maxOccurs="unbounded"/>
                </xsd:sequence>
                <xsd:attribute name="value" type="xsd:string" use="required"/>
                <xsd:attribute name="implies" type="xsd:string" use="optional"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>
    
    <xsd:complexType name="descriptionType">
        <xsd:simpleContent>
            <xsd:extension base="xsd:string">
                <xsd:attribute name="reformat" type="xsd:boolean" use="optional" default="true"/>
                <xsd:attribute name="includeImplies" type="xsd:boolean" use="optional" default="true"/>
            </xsd:extension>
        </xsd:simpleContent>
    </xsd:complexType>

    <xsd:complexType name="ChallengeBase" abstract="true">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class name="DummyChallengeBase" implClass="com.mbm.properties.baseclasses.ChallengeBase"/>
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:complexType>
    
    <xsd:complexType name="ChallengeType" abstract="true">
        <xsd:complexContent>
            <xsd:extension base="ChallengeBase">
                <xsd:attribute name="forValue" type="xsd:string"/>
                <xsd:attribute name="instruction" type="xsd:string"/>
                <xsd:attribute name="passChallengeValue" type="xsd:string"/>
                <xsd:attribute name="failChallengeValue" type="xsd:string" use="optional"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="MutualPropertiesType">
        <xsd:sequence>
            <xsd:element name="mutual-property-set" type="MutualPropertySetType" minOccurs="1" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <xsd:complexType name="MutualPropertySetBase" abstract="true">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class name="DummyMutualPropertySetBase" implClass="com.mbm.properties.baseclasses.MutualPropertySetBase"/>
            </xsd:appinfo>
        </xsd:annotation>
    </xsd:complexType>

    <xsd:complexType name="MutualPropertySetType">
        <xsd:complexContent>
            <xsd:extension base="MutualPropertySetBase">
                <xsd:sequence>
                    <xsd:element name="mutual-property" type="mutualPropertyType" minOccurs="1" maxOccurs="unbounded"/>
                </xsd:sequence>
                <xsd:attribute name="type" use="required">
                    <xsd:simpleType>
                        <xsd:restriction base="xsd:token">
                            <xsd:enumeration value="inclusive"/>
                            <xsd:enumeration value="exclusive"/>
                        </xsd:restriction>
                    </xsd:simpleType>
                </xsd:attribute>
                <xsd:attribute name="name" type="xsd:string" use="optional"/>
            </xsd:extension>
        </xsd:complexContent>
    </xsd:complexType>

    <xsd:complexType name="mutualPropertyType">
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="value" type="xsd:string" use="optional"/>
    </xsd:complexType>
</xsd:schema>

The XJC generated ObjectClass. Note this is lacking any @XmlElementDecl attributes.

// This file was generated by the Eclipse Implementation of JAXB, v3.0.2 
// See https://eclipse-ee4j.github.io/jaxb-ri 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2022.01.26 at 10:38:30 AM PST 
//


package com.mbm.properties.jaxb;

import jakarta.xml.bind.annotation.XmlRegistry;


/**
 * This object contains factory methods for each 
 * Java content interface and Java element interface 
 * generated in the com.mbm.properties.jaxb package. 
 * <p>An ObjectFactory allows you to programatically 
 * construct new instances of the Java representation 
 * for XML content. The Java representation of XML 
 * content can consist of schema derived interfaces 
 * and classes representing the binding of schema 
 * type definitions, element declarations and model 
 * groups.  Factory methods for each of these are 
 * provided in this class.
 * 
 */
@XmlRegistry
public class ObjectFactory {


    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.mbm.properties.jaxb
     * 
     */
    public ObjectFactory() {
    }

    /**
     * Create an instance of {@link Properties }
     * 
     */
    public Properties createProperties() {
        return new Properties();
    }

    /**
     * Create an instance of {@link DescriptionType }
     * 
     */
    public DescriptionType createDescriptionType() {
        return new DescriptionType();
    }

    /**
     * Create an instance of {@link KeywordPropertiesType }
     * 
     */
    public KeywordPropertiesType createKeywordPropertiesType() {
        return new KeywordPropertiesType();
    }

    /**
     * Create an instance of {@link PositionalPropertiesType }
     * 
     */
    public PositionalPropertiesType createPositionalPropertiesType() {
        return new PositionalPropertiesType();
    }

    /**
     * Create an instance of {@link MutualPropertiesType }
     * 
     */
    public MutualPropertiesType createMutualPropertiesType() {
        return new MutualPropertiesType();
    }

    /**
     * Create an instance of {@link KeywordPropertyType }
     * 
     */
    public KeywordPropertyType createKeywordPropertyType() {
        return new KeywordPropertyType();
    }

    /**
     * Create an instance of {@link PositionalPropertyType }
     * 
     */
    public PositionalPropertyType createPositionalPropertyType() {
        return new PositionalPropertyType();
    }

    /**
     * Create an instance of {@link ForValueType }
     * 
     */
    public ForValueType createForValueType() {
        return new ForValueType();
    }

    /**
     * Create an instance of {@link MutualPropertySetType }
     * 
     */
    public MutualPropertySetType createMutualPropertySetType() {
        return new MutualPropertySetType();
    }

    /**
     * Create an instance of {@link MutualPropertyType }
     * 
     */
    public MutualPropertyType createMutualPropertyType() {
        return new MutualPropertyType();
    }

}

Here is the code that attempts to unmarshal the XML. Note this code contains this statement System.out.println(jc.toString());:

package com.mbm.properties;

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import com.mbm.properties.jaxb.Properties;

public class Main {
    public static void main(String[] args) {
        try {
            File xmlFile = new File("PropertiesDefinitions.xml");
            JAXBContext jc = JAXBContext.newInstance(Properties.class);
            System.out.println(jc.toString());
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            Properties propertiesDefinitions = (Properties) unmarshaller.unmarshal(xmlFile);
        } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
        }
    }
}

When this code runs, the statement System.out.println(jc.toString()); produces this:

jar:file:/C:/Program%20Files/Java/jdk1.8.0_221/jre/lib/rt.jar!/com/sun/xml/internal/bind/v2/runtime/JAXBContextImpl.class Build-Id: 1.8.0_221
Classes known to this context:
  [B
  boolean
  byte
  char
  com.mbm.properties.jaxb.KeywordPropertiesType
  com.mbm.properties.jaxb.MutualPropertiesType
  com.mbm.properties.jaxb.PositionalPropertiesType
  com.mbm.properties.jaxb.Properties
  com.sun.xml.internal.bind.api.CompositeStructure
  double
  float
  int
  java.awt.Image
  java.io.File
  java.lang.Boolean
  java.lang.Byte
  java.lang.Character
  java.lang.Class
  java.lang.Double
  java.lang.Float
  java.lang.Integer
  java.lang.Long
  java.lang.Object
  java.lang.Short
  java.lang.String
  java.lang.Void
  java.math.BigDecimal
  java.math.BigInteger
  java.net.URI
  java.net.URL
  java.util.Calendar
  java.util.Date
  java.util.GregorianCalendar
  java.util.UUID
  javax.activation.DataHandler
  javax.xml.bind.JAXBElement
  javax.xml.datatype.Duration
  javax.xml.datatype.XMLGregorianCalendar
  javax.xml.namespace.QName
  javax.xml.transform.Source
  long
  short
  void

I am confused that the error states unexpected element (uri:"", local:"properties"). Expected elements are (none). I believe I am createating the JAXB Context correctly:

JAXBContext jc = JAXBContext.newInstance(Properties.class);

I am referencing the Properties class. Properties.java contains an @XmlRootElement(name = "properties") element. The XSD identifies properties as an element. The only thing I am aware of that looks strange is that the generated ObjectFactory class lacks any @XmlElementDecl attributes.

If I manually modify the XJC generated ObjectFactory to include the @XmlElementDecl attribute:

@XmlRegistry
public class ObjectFactory {
    
    // Begin manually added code
    private final static QName _Properties_QNAME = new QName("", "properties");
    
    @XmlElementDecl(namespace = "", name = "properties")
    public JAXBElement<Properties> createProperties(Properties value) {
        return new JAXBElement<Properties>(_Properties_QNAME, Properties.class, null, value);
    }
    
    // End manually added code

The above modification made no difference. I get the identical exception.

What am I doing wrong?

Upvotes: 5

Views: 4928

Answers (1)

S. Kom
S. Kom

Reputation: 183

You are using the unmarshaller from javax.xml.bind.Unmarshaller in your Main class but your generated class uses annotations from package jakarta.xml.bind.*. This mismatch led in my case to a quite similar error.

Try recompiling after changing

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

to

import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.Unmarshaller;

in your main class.

Upvotes: 6

Related Questions