[
Lists Home |
Date Index |
Thread Index
]
* Alan Gutierrez <alan-xml-dev@engrm.com> [2005-01-02 09:08]:
> * David Megginson <david.megginson@gmail.com> [2005-01-01 22:03]:
> > On Sat, 1 Jan 2005 19:42:20 -0500, Alan Gutierrez
> > <alan-xml-dev@engrm.com> wrote:
> >
> > > What was the thinking behind making SAXException a checked
> > > exception?
> > We talked about a few different strategies -- having all of the
> > callbacks throw Exception, having SAXException extend
> > RuntimeException, and having SAXException as a distinct base type.
> > No one less than James Gosling got in touch with me through an
> > intermediary to argue against throwing Exception. RuntimeException
> > was generally felt not to be the Java way (after all, IOException is
> > checked, and XML parsing is a kind of IO).
> > My single greatest regret about SAX, and one that I can never fix
> > without breaking backwards compatibility, is not having SAXException
> > extend IOException. I originally wanted to, but was too easily talked
> > out of it.
> SAX is a observer pattern. The logic is defined as a bunch of
> callbacks. The contents of the callbacks are specific to the
> application implementing the call backs. The exception thrown is
> unlikely to be a SAXException, since SAX is so simple. It is
> either a parse exception or an application exception.
> In STAX, an iterator pattern, a checked STAXException, makes
> a lot more sense.
Let me see if I can's solicit some feedback this way...
!? What is an exception handling strategy for an event API?
SAX chose to have a single checked exception type that was
propigated through the callback interface.
When I look at ActionListener in Swing however, I don't see a
checked ActionException thrown.
SAX is not really generating the exception, the callback is, and
the call back is application logic, not necessarily SAX logic.
public void startElement(String ns, String ln, String qn, Attributes a)
throws SAXException {
if (ln.equals("foo")) {
try {
Foo foo = FooFactory.newFoo();
} catch (FooException e) {
throw new SAXExcpetion("Cannot create Foo.", e);
}
}
}
Checked exceptions are a good way to give feedback, not a good
way to route (tunnnel, channel?) errors in an observer pattern.
Part of the problem lies in the fact that once an exception is
thrown, it is too late.
public void processBar () {
try {
parseFooXML();
} catch (SAXException e) {
if (e.getException() instanceof FooResourceException) {
if (FooFactory.freeUpSomeFoos()) {
// Too late. Oh, well!
throw e.getException();
}
}
throw e.getException();
}
}
Part of the problem is that programmers will keep wrapping and
throwing, not sure what to do.
public void processBar () throws BarException {
try {
parseFooXML();
} catch (SAXException e) {
throw new BarException("Can't run SAX.", e);
}
}
Exception handling is sorta ugly even if they try to do the
right thing.
public void processBar () {
try {
parseFooXML();
} catch (SAXException e) {
if (e.getException() instanceof FooResourceException) {
if (FooFactory.freeUpSomeFoos()) {
// Start all over again.
processBar();
} else {
throw e.getException();
}
} else if (e.getException() instanceof FooSecurityException){
if (FooSecurityManager.queryCredentials()) {
// Start all over again.
processBar();
} else {
throw e.getException();
}
} else if (e.getException() instanceof FooConfigurationException){
throw e.getException();
}
}
}
Not that catch blocks are much prettier.
public void processBar () {
try {
parseFooXML();
} catch (SAXException e) {
try {
throw e.getException();
} catch (FooResourceException e) {
if (FooFactory.freeUpSomeFoos()) {
// Start all over again.
processBar();
} else {
throw e;
}
} catch (FooSecurityException e) {
if (FooSecurityManager.queryCredentials()) {
// Start all over again.
processBar();
} else {
throw e;
}
}
}
}
This must be why David provided ErrorHandler, so that people
could intercept Exceptions before they are thrown. Er, no, I see
that ErrorHandler is only to report parse exceptions.
This is, in fact, a common tactic.
public void processBar () {
try {
parseFooXML();
} catch (SAXException e) {
// e.printStackTrace();
}
}
I'd like to design an error handler for event processing that
allows interception of errors at the source, and allows the
callback to throw an exception that is designed for the catch
block of the method invoking the parse.
public class FooBarStategyCassandra
implements StrategyCassandra {
public boolean error(StrategyError strategyError) {
try {
throw strategyError.getCause();
} catch (FooResourceException e) (
if (FooFactory.freeUpSomeFoos()) {
// Lovely! Try again without restarting parse.
return false;
}
// Throw past Bar.
throw strategyError;
} catch (FooSecurityException e) {
// Throw something that Bar will expect.
throw new BarFooSecurityError(e);
} catch (Throwable e) {
// Throw past Bar.
throw strategyError;
}
}
}
The above handles resources errors during processing, it also,
throws an exception that is expected by the caller. Looking at
the above, once could compose an error handler from other error
handlers by using the delegate or decororator design patterns.
Here's a stream processing invocation to match the cassandra.
public void processBar () {
try {
parseFooXML();
} catch (BarFooSecurityError e) {
if (FooSecurityManager.queryCredentials()) {
// Start all over again.
processBar();
} else {
scoldUser();
}
}
}
I'm hoping that I'm not talking to myself on this one. If this
is too Java oriented, tell me, but I'd like to sort this out so
that maybe I can create something worth sharing.
Kind regards.
--
Alan Gutierrez - alan@engrm.com
|