Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make JAXB error on non mapped elements

Tags:

java

xml

jaxb

I am trying to do the opposite of: JAXB - Ignore element

That is I'm trying to parse XML with JAXB to a POJO and I want to JAXB to fail if it does NOT find a matching Java property for a given element. I know I could probably do schema validation but I would rather not do that.

Example:

@XmlRootElement(name="Dog")
public class Dog {
    private String name;
    public String getName() {return name;}
    public String setName(String name) {this.name = name};
}

This XML would fail:

<Dog>
<id>blah</id>
<name>Stuff</name>
</Dog>

Because there is no id Java property

like image 596
Adam Gent Avatar asked May 23 '12 13:05

Adam Gent


People also ask

Is JAXB deprecated?

JAXB is one of the APIs in the Jakarta EE platform (formerly Java EE), part of the Java Web Services Development Pack (JWSDP), and one of the foundations for WSIT. It was also part of the Java SE platform (in version Java SE 6-10). As of Java SE 11, JAXB was removed.

Is JAXB Unmarshaller thread safe?

A: The JAXB Specification currently does not address the thread safety of any of the runtime classes. In the case of the Oracle JAXB RI, the JAXBContext class is thread safe, but the Marshaller , Unmarshaller , and Validator classes are not thread safe.


1 Answers

You can leverage a ValidationEventHandler to get the behaviour you are looking for. An unexpected elements is treated as a warning which is ignored by default. To support your use case you can supply a ValdidationEventHandler that fails on warnings (see below).

Demo

package forum10721257;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Dog.class);

        File xml = new File("src/forum10721257/input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.setEventHandler(new ValidationEventHandler () {

            @Override
            public boolean handleEvent(ValidationEvent event) {
                return false;
            }

        });
        Dog dog = (Dog) unmarshaller.unmarshal(xml);
    }

}

JAXB RI Exception

Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"id"). Expected elements are <{}name>
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:647)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:243)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:238)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:105)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.childElement(Loader.java:90)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.StructureLoader.childElement(StructureLoader.java:236)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:483)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:465)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:135)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:506)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:376)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2715)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:488)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:202)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:174)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:189)
    at forum10721257.Demo.main(Demo.java:26)

EclipseLink JAXB (MOXy)

We recently added this behaviour to MOXy. You will need to use EclipseLink 2.4.0 or 2.3.3. A nightly build can be obtained from the following location:

  • http://www.eclipse.org/eclipselink/downloads/nightly.php

UPDATE

I needed to tweak the Dog class from your question. Below is what I used.

Dog

package forum10721257;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="Dog")
public class Dog {
    private String name;
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
}
like image 51
bdoughan Avatar answered Sep 28 '22 15:09

bdoughan