SAX: Exception Handling

James Clark jjc at jclark.com
Tue May 5 08:29:49 BST 1998


David Brownell wrote:

> James Clark wrote:
> > Declaring an *interface* as throws
> > java.lang.Exception does not constrain an *implementation* of that
> > interface to be declared as throws java.lang.Exception.  It can be
> > declared to throw the appropriate subclass of java.lang.Exception.
> 
> But then since application programmers write to interfaces, not
> implementations, then application programmers would have all those
> nasty problems with getting handed random exceptions.
>
> A primary intent of exception declarations is to constrain the
> kinds of errors that a substystem (e.g. parser) reports, so that
> its clients have a clean "contract" and know exactly the kinds of
> "expected faults" they have to deal with.

You're not distinguishing two quite different uses of interface:

1. There are interfaces like Parser.  These are interfaces that are
implemented by the SAX implementation and called by clients of the
application.  For interfaces that are used in this way, I completely
agree with the points you make.  I did not suggest that methods on
parser should be declared as throws Exception: they should be declared
as throws SAXException.
 
2. There are interfaces like DocumentHandler.  These are not implemented
by the SAX implementation, nor are they called by the client.  Instead
the reverse is true: these are called by the SAX implementation and
implemented by the client.  Your arguments don't carry through to
interfaces that are used in this way.  Declaring methods in these
interfaces as throws Exception does not cause a client to have to deal
with random errors because they are not called by the client.  Nor does
it require the parser to deal with random errors

> Clauses like "throws Exception" are basically counter to the core
> philosophy of exceptions in Java.

It's not that simple.

The real problem ehere is the lack of parameterized types in Java.  If
Java had a concept of parameterized types, we could get the typing
exactly write, eg (using a C++ like syntax):

template<class ET>
interface DocumentHandler {
  void endElement(String name) throws ET;
}

template<class ET>
interface Parser {
  void setDocumentHandler(DocumentHandler<ET> handler);
  void parser(InputSource in) throws ET;
}

class MyDocumentHandler implements DocumentHandler<IOException> {

  void endElement(String name) throws IOException {
  }
}

class Demo {
  void foo(Parser<IOException> parser) {
    parser.parse(new MyDocumentHandler());
  }
}

The use of Exception that I'm arguing for is analogous to the use of
Object in a class like Vector.  Because Java doesn't have parameterized
types, you can't express the idea that the type you can get out of the
Vector constrains the type you can put in (or vice-versa), so you have
to settle for using Object.  Similarily with SAX you can't express that
the idea that the type of the exception that the Parser can throw
contrains the type of the exception that the handler methods can throw,
so you have to settle for using Exception.

Just as with Vectors, you can easily add a type-safe wrapper:

interface IODocumentHandler extends DocumentHandler {
  void endElement(String name) throws IOException;
}

class IOParser {
  Parser parser;
  public void setDocumentHandler(IODocumentHandler handler) {
    parser.setDocumentHandler(handler);
  }
  public void parser(InputSource in) throws IOException {
    try {
      parser.parse(in);
    }
    catch (SAXException e) {
      // The cast can't fail since the DocumentHandler is an
      // IODocumentHandler that can only throw IOExceptions
      throw (IOException)e.getException();
    }
  }
}

With this wrapper I now get a version of SAX specialized for handlers
that throw IOExceptions.  Using this wrapper I get complete exception
type-safety.  I can similarily do a wrapper for AWTException or
SQLException which will give me exception type-safety for applications
using AWT or SQL.  Note that these wrappers have minimal run-time cost,
because the handler methods are called directly.

The more I think about this the more certain I am that having the
handler methods declared as throws Exception is the right solution.

James


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