JAXB unmarshal validation throws cvc-elt.1: Cannot find the declaration of element error

14,580

This is the fourth hour that I'm trying to find the source of the problem. After much struggle, now, I'm confident that you're missing a single line of code to be able to rise to glorious heights!

The problem is that DocumentBuilderFactory created via DocumentBuilderFactory.newInstance() by default isn't namespace aware—yeah.

You can overcome this in two ways:

  1. make your DocumentBuilderFactory namespace aware:

    DocumentBuilderFactory.setNamespaceAware(true);

  2. or use a StreamSource while unmarshalling and drop the DocumentBuilder and his little friends altogether:

    Unmarshaller.unmarshal(StreamSource, Class<T>);

In case of the second choice you're to do it like this.

InputStream xsdStream = ...
InputStream xmlStream = ...

SchemaFactory f = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema s = schemaFactory.newSchema(xsdStream);

JAXBContext c = JAXBContext.newInstance(CalculateBorrowingDataResponseType.class);
Unmarshaller u = c.createUnmarshaller();
u.setSchema(schema);
CalculateBorrowingDataResponseType b = 
  u.unmarshal(new StreamSource(xmlStream), CalculateBorrowingDataResponseType.class);

By the way, on this schema-awareness-ness-document-builderness-awesomeness there is a lot info in the top section of the Unmarshaller class' documentation, you should definitely check that out!

Share:
14,580

Related videos on Youtube

Eric B.
Author by

Eric B.

Updated on June 04, 2022

Comments

  • Eric B.
    Eric B. almost 2 years

    I'm kind of new to JAXB and validation, and have spent several hours trying to figure out this problem to no avail. I've created a simple JAXB unmarshaller sample to parse an XML file. I have created an appropriate XSD file as well, but the validator keeps complaining that it is unable to find the declaration of an element.

    I think it may be related to namespace issues, but I've tried everything I can think of and still can't seem to resolve the error. As far as I can tell, my XSD and XML are proper, so it may have to do with the way I am instantiating the unmarshaller, but I can't seem to find the problem anywhere.

    The error/exception I keep getting is:

    Caused by: org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'calculateBorrowingDataResponse'.
        at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
        at org.apache.xerces.util.ErrorHandlerWrapper.error(Unknown Source)
        at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
        at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
        at org.apache.xerces.impl.xs.XMLSchemaValidator.handleStartElement(Unknown Source)
        at org.apache.xerces.impl.xs.XMLSchemaValidator.startElement(Unknown Source)
        at org.apache.xerces.jaxp.validation.ValidatorHandlerImpl.startElement(Unknown Source)
        at com.sun.xml.internal.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.java:85)
        at com.sun.xml.internal.bind.v2.runtime.unmarshaller.InterningXmlVisitor.startElement(InterningXmlVisitor.java:47)
        at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:113)
        at com.sun.xml.internal.bind.unmarshaller.DOMScanner.visit(DOMScanner.java:236)
        at com.sun.xml.internal.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:119)
        at com.sun.xml.internal.bind.unmarshaller.DOMScanner.scan(DOMScanner.java:102)
        at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:299)
        ... 2 more
    

    Here are the source files that are causing the error.

    Java Code:

    // We need a Document
    InputStream is = UnmarshalTest.class.getClassLoader().getResourceAsStream("calculateBorrowingDataResponse.xml");
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    DocumentBuilder db = dbf.newDocumentBuilder();
    Node node = db.parse(is);
    
    // Creating an unmarshaller
    Unmarshaller u = JAXBContext.newInstance(CalculateBorrowingDataResponseType.class).createUnmarshaller();
    
    // Setting the Validation
    Schema schema;
    SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
    schema = schemaFactory.newSchema(new File("src/main/webapp/WEB-INF/wsdl/CalculateBorrowingDataResponse.xsd"));
    u.setSchema(schema);
    u.unmarshal(node, CalculateBorrowingDataResponseType.class);
    

    CalculateBorrowingDataResponse.xsd:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsd:schema 
        version="1.1"
        attributeFormDefault="unqualified" 
        elementFormDefault="qualified"
        targetNamespace="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
        xmlns:lssSt="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse"
        xmlns:cbdRes="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    
    
        <!-- CalculateBorrowingData -->
        <xsd:complexType name="CalculateBorrowingDataResponseType">
            <xsd:sequence>
                <xsd:element name="loanAgmt" type="cbdRes:LoanAgreementType" minOccurs="1" maxOccurs="1" />
            </xsd:sequence>
        </xsd:complexType>
    
    
        <xsd:complexType name="LoanAgreementType">
            <xsd:sequence>
                <xsd:element name="borrowingBasedPmtAmt" type="lssSt:borrowingBasedPmtAmt" minOccurs="0" maxOccurs="1" />
                <xsd:element name="maxPmtAmt" type="lssSt:maxPmtAmt" minOccurs="0" maxOccurs="1" />
                <xsd:element name="borrowingCapacityMin" type="lssSt:borrowingCapacityMin" minOccurs="0" maxOccurs="1" />
                <xsd:element name="borrowingCapacityMax" type="lssSt:borrowingCapacityMax" minOccurs="0" maxOccurs="1" />
                <xsd:element name="propertyValueMinAmt" type="lssSt:propertyValueMinAmt" minOccurs="0" maxOccurs="1" />
                <xsd:element name="propertyValueMaxAmt" type="lssSt:propertyValueMaxAmt" minOccurs="0" maxOccurs="1" />
            </xsd:sequence>
        </xsd:complexType>
    
        <xsd:element name="calculateBorrowingDataResponse" type="cbdRes:CalculateBorrowingDataResponseType"/>
    
    
        <xsd:simpleType name="borrowingBasedPmtAmt">
            <xsd:restriction base="xsd:decimal" >
            <xsd:totalDigits value="19" />
            <xsd:fractionDigits value="4" />
            </xsd:restriction>
        </xsd:simpleType>
        <xsd:simpleType name="maxPmtAmt">
            <xsd:restriction base="xsd:decimal" >
            <xsd:totalDigits value="19" />
            <xsd:fractionDigits value="4" />
            </xsd:restriction>
        </xsd:simpleType>
        <xsd:simpleType name="borrowingCapacityMin">
            <xsd:restriction base="xsd:decimal" >
            <xsd:totalDigits value="19" />
            <xsd:fractionDigits value="4" />
            </xsd:restriction>
        </xsd:simpleType>
        <xsd:simpleType name="borrowingCapacityMax">
            <xsd:restriction base="xsd:decimal" >
            <xsd:totalDigits value="19" />
            <xsd:fractionDigits value="4" />
            </xsd:restriction>
        </xsd:simpleType>
        <xsd:simpleType name="propertyValueMinAmt">
            <xsd:restriction base="xsd:decimal" >
            <xsd:totalDigits value="19" />
            <xsd:fractionDigits value="4" />
            </xsd:restriction>
        </xsd:simpleType>
        <xsd:simpleType name="propertyValueMaxAmt">
            <xsd:restriction base="xsd:decimal" >
            <xsd:totalDigits value="19" />
            <xsd:fractionDigits value="4" />
            </xsd:restriction>
        </xsd:simpleType>
    </xsd:schema>
    

    calculateBorrowingDataResponse.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <calculateBorrowingDataResponse
        xmlns="http://www.domain.com/ClientServices/LendingSimulation/CalculateBorrowingDataResponse"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ns2="http://www.domain.com/ClientServices/LendingSimulation/V1.1">
        <loanAgmt>
            <borrowingBasedPmtAmt>1231231</borrowingBasedPmtAmt>
            <maxPmtAmt>987654321</maxPmtAmt>
            <borrowingCapacityMax>99999</borrowingCapacityMax>
        </loanAgmt>
    </calculateBorrowingDataResponse>
    

    I tried both with and without the last element definition in the XSD (ie: xsd:element name="calculateBorrowingDataResponse" ... ) but neither work.

    I'm running out of ideas of different things to try. Any suggestions or recommendations would be greatly appreciated!