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.
Search
Calendar
| M | T | W | T | F | S | S |
|---|---|---|---|---|---|---|
| « May | Jul » | |||||
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 | ||||||
Archives
Categories
- Android (3)
- Apple (26)
- Books (7)
- Eclipse (14)
- Errors (3)
- Firefox (7)
- Git (2)
- Hardware (16)
- Horror Code (8)
- Internet (18)
- Java (98)
- JavaScript (9)
- Life, universe and everything (45)
- Lifehacks (25)
- Linux (50)
- Opinions (25)
- OSX (4)
- Python (1)
- Software (27)
- Speeches and Conferences (8)
- Unix (3)
- Web (21)
- Windows (19)
Tag Cloud
Android apple architecture Bash colors configuration CSS Development Düsseldorf Eclipse germany Git Google Hardware hdr How-To Java JAXB job junit Karmic Linux MacBook music night Open Source Opinion oracle OSX patterns Pitfalls Practices Resume Security Software Suspend TDD Testing tip tonemapped Tricks Ubuntu video Web XML
WP Cumulus Flash tag cloud by Roy Tanck and Luke Morton requires Flash Player 9 or better.
Blog License
Blogs I like
Books on the desk
Friends' Blogs
- Antonio Terreno & Valter Bernardini
- Bruno Bossola
- Daniele Galluccio
- Domenico Ventura
- Ed Schepis
- Fabrizio Gianneschi
- Luca Grulla
- Luigi Zanderighi
- Marcello Teodori
- Mida Boghetich
- Muralidharan Chandrasekaran
- Piero Ricca
- Renzo Borgatti
- Simone Bordet
- Simone Bruno
- Uberto Barbini
- Valvolog
- Webtide blogs (Greg Wilkins & Jan Bartel)
Links




















No Responses to “Bug: SAXException swallows the error cause!”
Please Wait
Leave a Reply