SAX in Java: Exceptions, again (please respond)

David Megginson ak117 at freenet.carleton.ca
Fri Jan 9 01:45:51 GMT 1998


I'm still working to resolve the issue of exceptions in the Java
implementation of SAX, before I put out a full draft implementation
for discussion (the draft may be delayed a bit by the ice storms and
power outages here in Ottawa).  This is an important, but also an
extremely technical issue, so perhaps a simpler explanation of the
problem will help bring more people into the discussion (thanks to
those who have responded already).

A SAX application will a structure like this:

  User code (top-level) <==> SAX layer <==> User code (callbacks)

In other words, the top-level user code invokes the SAX-conformant
parser, which in turn invokes more user code through the callback
interface.  The user code in the callbacks cannot throw general
exceptions to the user code at the top-level unless explicitly allowed
by the SAX layer.

There are three possible solutions:

1) Allow all callbacks to throw java.lang.Exception (i.e. any
   exception), and require SAX-conformant Java XML parsers to pass
   through any exceptions that are not specific to them.

2a) Allow all callbacks to throw only a special SAX exception, which can
   act as a container to carry other exceptions through to the top
   level.

2b) Don't explicitly allow any callbacks to throw exceptions; callbacks
   can get exceptions to the top level only by creating their own
   container based on the java.lang.RunTime exception, and hiding
   other exceptions in it.


FIRST SOLUTION
--------------

The first solution is the most transparent, because the callbacks can
simply throw exceptions as usual, and the top-level code can catch
it.  To throw an instance of MyException, for example, the
startDocument callback could simply use

  public void startDocument () throws MyException
  {
    if (/* problem */) {
      throw new MyException("oh damn!");
    }
  }

At the top level, you could catch the exception simply, like this:

  try {
    parser.parse(null, "file://localhost/tmp/mydoc.xml");
  } catch (MyException e) {
    /* do something */
  } catch (Exception e) {
    /* any other exception */
  }

Note that even though the interface has

  public void startDocument () throws java.lang.Exception;

the implementation can be more specific, and limit the actual
exceptions thrown (or throw none at all, if desired).

This will cause no problems for application writers (since they can be
specific), but it will make life harder for parser writers, because
nearly every method in the parser will end up throwing
java.lang.Exception, and compile-time error checking will be much
weaker.


SECOND SOLUTIONS (A and B)
--------------------------

The other two solutions both require embedding, using either a regular
exception or a runtime exception.  First, we need a special exception:

  public class SAXException extends java.lang.Exception {
    private java.lang.Exception realException;

    public SAXException (java.lang.Exception e) {
      realException = e;
    }

    public java.lang.Exception getException ()
    {
      return realException;
    }
  }

Now, throwing an exception is a little more indirect:

  public void startDocument () throws SAXException
  {
    if (/* problem */) {
      throw new SAXException(new MyException("oh damn!"));
    }
  }

Catching it is also a little trickier:

  try {
    parser.parse(null, "file://localhost/tmp/mydoc.xml");
  } catch (SAXException e) {
    java.lang.Exception realException = e.getException();
    if (realException instanceof MyException) {
      /* do something */
    } else {
      /* do something else */
    }
  }

You can also rethrow it at this point:

  try {
    parser.parse(null, "file://localhost/tmp/mydoc.xml");
  } catch (SAXException e) {
    throw e.getException();
  }

This is going to make life harder for application writers, but parser
writers will be able to rely on stronger compile-time error checking,
since their internal methods will have to throw only
org.sax.SAXException (or whatever) instead of java.lang.Exception.


Which do we choose?  Someone's going to have a harder time, and we
have to choose between the parser writers and the application writers.
I have already written Ælfred so that all callbacks can throw
java.lang.Exception and have it passed transparently through to the
top-level code, but Ælfred will also allow the more specific solution
if we choose it.


All the best,


David

-- 
David Megginson                 ak117 at freenet.carleton.ca
Microstar Software Ltd.         dmeggins at microstar.com
      http://home.sprynet.com/sprynet/dmeggins/

xml-dev: A list for W3C XML Developers. To post, mailto:xml-dev at ic.ac.uk
Archived as: http://www.lists.ic.ac.uk/hypermail/xml-dev/
To (un)subscribe, mailto:majordomo at ic.ac.uk the following message;
(un)subscribe xml-dev
To subscribe to the digests, mailto:majordomo at ic.ac.uk the following message;
subscribe xml-dev-digest
List coordinator, Henry Rzepa (mailto:rzepa at ic.ac.uk)




More information about the Xml-dev mailing list