Differences between revisions 3 and 4
Revision 3 as of 2010-03-05 09:15:05
Size: 4695
Editor: kfc
Comment:
Revision 4 as of 2010-03-17 13:13:02
Size: 4699
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 5: Line 5:
The following concepts of contingency and fault is derived from [http://www.oracle.com/technology/pub/articles/dev2arch/2006/11/effective-exceptions.html Barry Ruzek's Article ''Effective Java Exceptions''] and it is advised that developers atleast skim it. The following concepts of contingency and fault is derived from [[http://www.oracle.com/technology/pub/articles/dev2arch/2006/11/effective-exceptions.html|Barry Ruzek's Article ''Effective Java Exceptions'']] and it is advised that developers atleast skim it.
Line 34: Line 34:
'''NOTE:''' To enforce that we minimally log exceptions at the root of a thread we could use [http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) Thread.setDefaultUncaughtExceptionHandler]. '''NOTE:''' To enforce that we minimally log exceptions at the root of a thread we could use [[http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html#setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)|Thread.setDefaultUncaughtExceptionHandler]].

Exception Guidelines

Contingencies and Faults

The following concepts of contingency and fault is derived from Barry Ruzek's Article ''Effective Java Exceptions'' and it is advised that developers atleast skim it.

Grossly oversimplified picture in a nutshell: A contingency is a control-flow related checked exception. A fault is an unexpected RuntimeException or Error that does not relate to the workflow of the class/method/application. Faults subclassing Error are generally signs that the entire JVM might be compromised (see also javadoc for the Error class) and should as a rule of thumb not be caught (except possibly by the outermost fault barrier).

The following table is copied from Ruzek's article:

Condition

Contingency

Fault

Is considered to be

A part of the design

A nasty surprise

Is expected to happen

Regularly but rarely

Never

Who cares about it

The upstream code that invokes the method

The people who need to fix the problem

Examples

Alternative return modes

Programming bugs, hardware malfunctions, configuration mistakes, missing files, unavailable servers

Best Mapping

A checked exception

An unchecked exception

A fault barrier is a conceptual layer in the control flow where certain kinds of faults are caught. It is a perfectly acceptable fault barrier to catch general Exceptions, used for example to encapsulate unreliable subsystems. It must be specified in the javadoc of a method that it acts as a fault barrier and what the intended purpose of the fault handling is (including the types of faults it handles).

Best Practices

  • A fault is a RuntimeException or in rare cases an Error

  • It is allowed to wrap a contingency in a fault and send it up stream
  • A contingency cannot pass a fault barrier although a fault barrier can have contingencies it self.
  • A fault barrier cannot let a fault pass that is one of the fault types that it is itself designated to handle.
  • A contingency is specific to one problem or event in the control flow.
  • Avoid that the same contingency can be thrown by two or more different causes in the same method. If this is the case you should either refactor your method or create different types of exceptions for the other contingencies.
  • Never have a finally block in a fault barrier - it may throw exceptions that escape the fault barrier

Threads

  • Every thread should have a fault barrier at the top. In practice this means that we put try/catch as the outermost statement in each run method
  • Gotcha: Beware of implicitly started threads: Webservice-initiated methods, threads started by events like JMS messages or Timer events.

  • Gotcha: Beware that throwing a nasty fault might only stop the running thread and not the application as a whole

NOTE: To enforce that we minimally log exceptions at the root of a thread we could use Thread.setDefaultUncaughtExceptionHandler.

Finally

  • Close your resources and files in a finally clause

  • Never ever do return statements in a finally clause

System.Exit

  • Only in the main method. Use faults instead, for really nasty faults use Error subclasses

  • Gotcha: Beware that throwing a nasty fault might only stop the running thread and not the application as a whole

Throwing Exceptions

Generally don't log when throwing exceptions. Instead make sure to put a good error message in the exception. Good error messages include as much context as reasonable. For example

        for (Record rec : database) {
                if (rec.length == 0) {
                        throw new EmptyRecordException ("Record " + rec.getId() + " was empty");
                }
                ...
        }

Rethrowing Exceptions

Rethrowing exceptions is fine, as long as the old Exception is wrapped in a new Exception as this preserves the stack trace. Follow the guidelines from the throwing exceptions chapter above.

        try {
                myStream.write(rec.toBytes());
        catch (IOException e) {
                throw new RecordWriterException("Could not store the record '" + rec.getId() + "' to file '" + filename + "'", e);
        }

ExceptionGuidelines (last edited 2010-03-17 13:13:02 by localhost)