Error Handling

Both JAXP and the Xerces DOM implementation follow the basic Java architecture for exception handling. Consistent with that architecture, most of the code in the main method lies within a try block that is followed by various catch blocks. JAXP implements an interesting overall parsing architecture in that it allows you to use a different underlying XML parser than the default Xerces implementation. One way JAXP does this is by requiring such pluggable parsers to use the SAX classes related to exception handling. So, whether or not your parser is actually a SAX parser under the hood, you need a SAX exception handler if you want to handle parsing exceptions. The JAXP documentation (in Javadoc format) has this to say about declaring an exception handler for your DocumentBuilder:

If an application does not register an ErrorHandler, XML parsing errors will go unreported and bizarre behavior may result.

Given that, I tend to think it's a good idea to declare an exception handler. However, SAX parsing errors are just one kind of error, even if they tend to be the most involved to handle. Here are some other errors we want to catch:

  • SAX parsing exceptions: warnings, errors, fatal errors

  • DOM exceptions of all types: for example, attempting to reference nonexistent DOM nodes and using an out-of-range index into a NodeList

  • All other Java exceptions: most likely I/O exceptions

To catch SAX parsing exceptions we declare an error handler for our DocumentBuilder as follows:

dbBuilder.setErrorHandler(new SAXErrorHandler());

The SAXErrorHandler class will be reused in all our Java utilities that read XML documents, so it is worth looking at in a bit of detail. It has four methods, the first three of which are required by the SAX ErrorHandler interface it implements.

  • warning: Under normal circumstances this will just print exception information to the standard system error stream and continue. However, it may itself also throw another SAXException if it encounters anything really bizarre.

  • error: This gets SAX-specific exception information and rethrows the exception.

  • fatalError: This is virtually the same as the error method. It gets SAX-specific exception information and rethrows the exception.

  • getSAXExceptionInfo: This utility formats interesting SAX exception information into a string.

Here's the code:

SAXErrorHandler.java
// Standard libraries
import java.io.*;

// JAXP packages
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;

public class SAXErrorHandler implements ErrorHandler
{

  //  The first three methods are required by the SAX
  //  ErrorHandler interface. They deal with warnings, errors,
  //  and fatalErrors, respectively.

  public void warning(SAXParseException spe)
    throws SAXException
  {
    System.err.println("
Warning during parsing " +
      getSAXExceptionInfo(spe));
  }

  public void error(SAXParseException spe)
    throws SAXException
  {
    String sInfo = "
Error during parsing " +
      getSAXExceptionInfo(spe);
    throw new SAXException(sInfo);
  }

  public void fatalError(SAXParseException spe)
    throws SAXException
  {
    String sInfo = "
Fatal error during parsing " +
      getSAXExceptionInfo(spe);
    throw new SAXException(sInfo);
  }

  //  This utility method gets SAX specific information about
  //  the exception
  private String getSAXExceptionInfo(SAXParseException spe)
  {
    String sInfo = "
" +
      "URL    = " + spe.getSystemId() + "
" +
      "Entity = " + spe.getPublicId() + "
" +
      "Line = " + spe.getLineNumber() + "
" +
      "Column = " + spe.getColumnNumber() + "
" +
      "Text = " + spe.getMessage() + "
";
    return sInfo;
  }
}

The use of URL is not as goofy as it looks on first take. We can report not only parsing errors in the instance document we're working with but also errors in parsing any associated schema files. So, the URL may actually give us some useful information.

Our general strategy is to continue if we encounter a warning and bail out if we encounter anything more severe. When we bail out, we exit back all the way out of the try block in the main routine and execute its catch block.

Keeping with the strategy of fairly simple error handling, the catch block for the main routine is pretty simple. We want it to handle DOM exceptions and anything else we might have tripped over such as I/O errors. The DOMException class extends java.lang.RuntimeException and doesn't have any special methods associated with it. So, for DOM exceptions and everything else throwable we just print the message and a stack trace to the standard system error stream, then set an exit status to an error condition.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset