users@jaxb.java.net

Possible bug in unmarshal() after SAXParseException thrown twice

From: Mikyla DeWitt <mdewitt_at_mncsoftware.com>
Date: Thu, 22 May 2014 16:47:33 -0700

Hello,

I've encountered an issue with the JAXB unmarshaller that I think may be a potential bug. I am seeing the following behavior: After two calls to unmarshal() fail due to an (expected) parsing exception, calling unmarhsal() on any object that does not have an XMLRootElement tag will return the expected object wrapped in the JAXBElement that was created for the failed unmarshal() call. Once a call to unmarshal() is made for an object that doesn't have an XMLRootElement tag, this error seems to be "reset" and all calls to unmarshal() work as expected again.

The jaxb version specified in my pox.xml is:

    <jaxb2-basics.version>0.6.4</jaxb2-basics.version>

I've included a code sample and the parsing exception that I receive, though again, I do expect this exception to be thrown.
Is this a known bug? Is there a workaround for this issue?

Please let me know if you need any more information from me.
Thank you very much for all your help!

Mikyla

Parsing exception:

Caused by: javax.xml.bind.UnmarshalException
- with linked exception:
[org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 7; The element type "severity" must be terminated by the matching end-tag "</severity>".]
                at javax.xml.bind.helpers.AbstractUnmarshallerImpl.createUnmarshalException(AbstractUnmarshallerImpl.java:335)
                at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.createUnmarshalException(UnmarshallerImpl.java:512)
                at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:209)
                at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
                at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
                at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:204)
                at com.mncsoftware.mosaic.persistence.simplefile.XmlFileAccessor.xmlUnmarshall(XmlFileAccessor.java:267)
                ... 39 more
Caused by: org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 7; The element type "severity" must be terminated by the matching end-tag "</severity>".
                at org.apache.xerces.util.ErrorHandlerWrapper.createSAXParseException(Unknown Source)
                at org.apache.xerces.util.ErrorHandlerWrapper.fatalError(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.XMLErrorReporter.reportError(Unknown Source)
                at org.apache.xerces.impl.XMLScanner.reportFatalError(Unknown Source)
                at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
                at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
                at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
                at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
                at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
                at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
                at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
                at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
                at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
                ... 43 more

Below is an example with code that demonstrates the problem:

I have the following auto generated schemas :
public class NonRootObjectWithBadXMLFile { ... }

public class NonRootObjectWithGoodXMLFile { ... }

@XMLRootElement (name = "XMLObject1)
public class XMLObject1 { ... }


I have the following xml files:

/NonRootObjectBadElement.xml

/NonRootObjectGoodElement.xml

/RootObject.xml

The following code was taken from a junit test used to test this bug. I've attached the junit test to this email, though with the fake namespace added it will not run without some slight modification:

        JAXBContext jc = JAXBContext.newInstance("com.acme.foo");
        Unmarshaller xmlUnmarshaller = jc.createUnmarshaller();

        Path nonRootFileWithError = Paths.get("/", "NonRootObjectBadElement.xml");
        Path nonRootFileWithoutError = Paths.get("/", "NonRootObjectGoodElement.xml");
        Path eventDisplay = Paths.get("/", "RootObject.xml");

        // When this succeeds, it should return a JAXBElement.
        // This situation will fail due to a bad xml element.
        try (InputStream str = Files.newInputStream(nonRootFileWithError))
        {
            try
            {
                Object obj = xmlUnmarshaller.unmarshal(str);
                System.out.println("alarm " + obj);
                assertTrue(obj instanceof JAXBElement);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }

        // When this succeeds, it should return a JAXBElement.
        // This situation will fail due to a bad xml element. (This is the same call as above)
        try (InputStream str = Files.newInputStream(nonRootFileWithError))
        {
            try
            {
                Object obj = xmlUnmarshaller.unmarshal(str);
                System.out.println("alarm " + obj);
                assertTrue(obj instanceof JAXBElement);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }

        // When this succeeds, it should return a JAXBElement.
        // When this is commented out: the call below to unmarshal() will return
        // a JAXBElement with the XMLObject1 object in the value field.
        // This should not happen.
        //
        // When this is not commented out: the call below to unmarshall() will
        // correctly return an XMLObject1
        try (InputStream str = Files.newInputStream(nonRootFileWithoutError))
        {
            try
            {
                Object obj = xmlUnmarshaller.unmarshal(str);
                System.out.println("sec " + obj);
                assertTrue(obj instanceof JAXBElement);
            }
            catch (Exception ex)
            {
                assertTrue(false);
                ex.printStackTrace();
            }
        }

        // When this succeeds, it should return a XMLObject1 object.
        // It should NOT return a JAXBElement.
        // This will fail unless the block of code above is not commented out.
        try (InputStream str = Files.newInputStream(eventDisplay))
        {
            try
            {
                Object obj = xmlUnmarshaller.unmarshal(str);
                System.out.println("event " + obj);
                assertTrue(obj instanceof XMLObject1);
            }
            catch (Exception ex)
            {
                ex.printStackTrace();
            }
        }