Bug: SAXException swallows the error cause!

I recently discovered a behavior of SAXParser provided in JDK 6 that I think it’s a BUG.

Here is the source:

 1import java.io.StringReader;
 2
 3import javax.xml.parsers.SAXParser;
 4import javax.xml.parsers.SAXParserFactory;
 5
 6import org.xml.sax.Attributes;
 7import org.xml.sax.InputSource;
 8import org.xml.sax.SAXException;
 9import org.xml.sax.helpers.DefaultHandler;
10
11
12public class SAXExceptionTest {
13
14    private static class SampleHandler extends DefaultHandler {
15        @Override
16        public void startElement(String uri, String localName, String name,
17                Attributes attributes) throws SAXException {
18            try {
19                Object o = null;
20                o.hashCode();
21            } catch (Exception ex) {
22                throw new SAXException("Exception during startElement", ex);
23            }
24        }
25    }
26
27    public static void main(String[] args) throws Exception {
28        SAXParserFactory factory = SAXParserFactory.newInstance();
29        SAXParser parser = factory.newSAXParser();
30        String xmlToParse = "<sample-xml>Hello wold!</sample-xml>";
31        InputSource source = new InputSource(new StringReader(xmlToParse));
32        parser.parse(source, new SampleHandler());
33    }
34}
35

The exception you get from this source is:

Exception in thread "main" java.lang.NullPointerException
	at SAXExceptionTest$SampleHandler.startElement(SAXExceptionTest.java:22)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
	at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.startElement(XMLDTDValidator.java:767)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1357)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$ContentDriver.scanRootElementHook(XMLDocumentScannerImpl.java:1297)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3088)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:914)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:508)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
	at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
	at SAXExceptionTest.main(SAXExceptionTest.java:32)

So, you see a NullPointerException (that in reality is a SAXException, so this information is wrong!) thrown at line 22, but nothing about the root cause (the real NullPointerException, that in reality is thrown at line 20!).
Also notice that the message “Exception during startElement” is lost, as well as the message contained in the NullPointerException (that usually just contains the String “null”).
I think all this is misleading.

Here is a fixed version of the same example (I subclasses SAXParseException into FixedSAXParseException):

 1import java.io.StringReader;
 2
 3import javax.xml.parsers.SAXParser;
 4import javax.xml.parsers.SAXParserFactory;
 5
 6import org.xml.sax.Attributes;
 7import org.xml.sax.InputSource;
 8import org.xml.sax.SAXException;
 9import org.xml.sax.helpers.DefaultHandler;
10
11public class FixedSAXExceptionTest {
12    
13    public static class FixedSAXException extends SAXException {
14        private static final long serialVersionUID = 649860250063124096L;
15        private Throwable cause;
16        private String message;
17
18        public FixedSAXException(String message, Exception cause) {        
19            this.message = message;
20            this.cause = cause;
21        }
22
23        @Override
24        public Throwable getCause() {
25            return cause;
26        }
27
28        @Override
29        public String getMessage() {
30            return message + ": " + cause.getMessage();
31        }
32    }    
33
34    private static class SampleHandler extends DefaultHandler {
35        @Override
36        public void startElement(String uri, String localName, String name,
37                Attributes attributes) throws SAXException {
38            try {
39                Object o = null;
40                o.hashCode();
41            } catch (Exception ex) {
42                throw new FixedSAXException("Exception during startElement", ex);
43            }
44        }
45    }
46
47    public static void main(String[] args) throws Exception {
48        SAXParserFactory factory = SAXParserFactory.newInstance();
49        SAXParser parser = factory.newSAXParser();
50        String xmlToParse = "<sample-xml>Hello wold!</sample-xml>";
51        InputSource source = new InputSource(new StringReader(xmlToParse));
52        parser.parse(source, new SampleHandler());
53    }
54}

So you see the stacktrace I get this time:

Exception in thread "main" FixedSAXExceptionTest$FixedSAXException: Exception during startElement: null
	at FixedSAXExceptionTest$SampleHandler.startElement(FixedSAXExceptionTest.java:42)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
	at com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator.startElement(XMLDTDValidator.java:767)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1357)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$ContentDriver.scanRootElementHook(XMLDocumentScannerImpl.java:1297)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3088)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:914)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:647)
	at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:508)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:807)
	at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
	at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:107)
	at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
	at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
	at javax.xml.parsers.SAXParser.parse(SAXParser.java:395)
	at FixedSAXExceptionTest.main(FixedSAXExceptionTest.java:52)
Caused by: java.lang.NullPointerException
	at FixedSAXExceptionTest$SampleHandler.startElement(FixedSAXExceptionTest.java:40)
	... 15 more

This time you get a FixedSAXException with message “Exception during startElement: null” at line 42 (where “null” is the message returned by the original exception) and as cause you get the NullPointerException at line 40. As it should be.

Loosing that information could be painful debugging an application.

My suggestion is to subclass the SAXParseException with a fixed behavior, like I did in this example.


One Response to “Bug: SAXException swallows the error cause!”  

  1. 1 Thierz

    Thanks dude, I ran into the very same problem 7 years after you, it seems SAXExceptions have not been fixed since a long time.

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>



Calendar

June 2008
M T W T F S S
« May   Jul »
 1
2345678
9101112131415
16171819202122
23242526272829
30  

Follow me

twitter flickr LinkedIn feed

Subscribe by email

Enter your email address:

Archives


Categories

Tag Cloud


Listening