OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.

 


Help: OASIS Mailing Lists Help | MarkMail Help

 


 

   Re: [xml-dev] SAXException, checked, buy why?

[ 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




 

News | XML in Industry | Calendar | XML Registry
Marketplace | Resources | MyXML.org | Sponsors | Privacy Statement

Copyright 2001 XML.org. This site is hosted by OASIS