Exceptions

Thomas Feiner

Short recap

Short recap

try / catch / finally


try {
    body
} catch (exception-classname variable-name) {
    handler
} finally {
    finally code
}
                

Short recap

The code inside a finally block will always be executed, even if an exception is thrown within the try or catch block. When the code has a return statement within try or catch block, the code inside the finally block will get executed before returning from the method.

Short recap


public class TestMyTest {

    @Test
    public void finallyTest() {
        int value = finallyMethod();
        assertEquals(??, value);
    }

    private int finallyMethod() {
        try {
           return 0;
        } finally {
           return 1;
        }
    }
}
               

try with resources


InputStream in = getSystemResourceAsStream("test.txt" );
try (Scanner res = new Scanner( in )) {
    System.out.println(res.nextLine());
}
                

instead of


InputStream in = getSystemResourceAsStream("test.txt" );
final Scanner res = new Scanner( file );
try {
    System.out.println(res.nextLine());
} finally {
    res.close();
}
                

If close() throws a checked exception, you have to handle it.

Hierarchy

Checked or Unchecked Exceptions

Checked exceptions

must be caught or declared thrown and extend java.lang.Exception

Unchecked exceptions

do not have to be caught or declared thrown and extend java.lang.RuntimeException

Pro Checked Exceptions

  • it is harder to forget handling exceptions
  • when methods do not declare which unchecked exceptions they may throw it is hard to handle them

Pro Unchecked Exceptions

  • checked exceptions clutter top level methods (violates the open/closed principle)
  • checked exceptions are part of the signature or interface, it is hard to remove them later
  • when programmer KNOWS that all preconditions are met, he is not forced to clutter code with try/catch

Error situations

Client errors

Caused by clients of a system, e.g. web client sends invalid web service request.

Service errors

External or internal service does not work properly, e.g. DB is down.

Internal errors

Malfunction of the system, not detected by tests, dicovered during runtime. The error needs to be investigated and the application fixed and redeployed.

System errors

Serious and unrecoverable problems with the JVM. The application has to shut down immediately.

java.lang.Error, subclass of java.lang.Throwable
NEVER catch Error or Throwable!

Principles

  • Exception handling design according to application design
  • Exception hierarchy should reflect application's component hierarchy
  • Exception handling is more than error handling

Throwing exceptions

  • Assertions and preconditions at the beginning of crucial methods. (should throw IllegalArgumentException)
  • Add context information to Exception if possible
  • Avoid differentiating by error text messages. Use context information or exception subclasses instead

Exception handling antipatterns

Do not use exceptions for flow control!

Logging

  • Logging a stacktrace where it is not needed
  • Mix logging and propagation (log and rethrow)
  • 
    catch (final NoSuchMethodException e) {
        LOG.error("error", e);
        throw e;
    }
    
    catch (final NoSuchMethodException e) {
        LOG.error("error", e);
        throw new MyAwesomeException(e);
    }
                        

Finally

  • Forgot to use finally where it is appropriate
  • Throw within finally, overrides the originally thrown exception without any trace

Swallow exceptions


try {
    foo();
} catch (final Exception e) {
    //something happened
    return null; // I have seen something with "return 0" for DB counts :)
}
               

Throwing Exception


public void foo() throws Exception
               

Catch java.lang.Exception


try {
    foo();
} catch (final Exception e) {  //also catches checked exceptions!
    LOG.error("foo failed", e);
}
               

Catch Throwable


try {
    foo();
} catch (final Throwable t) {  //also catches checked exceptions!
    //wait ... what?
}
               

Throw the kitchen sink


public void foo throws MyException, AnotherException, SomeOtherException, YetAnotherException { ... }
               

Destructive wrapping


catch (NoSuchMethodException e) {
    throw new MyServiceException("something went wrong" + e.getMessage); //stacktrace is lost!
}
               

Log and return null


catch (NoSuchMethodException e) {
    LOG.error("something happened", e);
    return null;
}
               

Relying on getCause()


catch (MyException e) {
    if (e.getCause() instanceof FooException) {
    ...
    }
}
               

Unsupported operation returning null


public String foo() {
   // Not supported in this implementation.
   return null;
}
           

Three rules

  • Be specific
    create exception hierarchy
  • Throw early
    (e.g. prohibit NPE and give context with specific exception)
  • Catch late
    catch exceptions at the proper layer, where your program can either meaningfully recover from the exception and continue without causing further errors, or provide the user with specific information

Debate

http://stackoverflow.com/questions/613954/the-case-against-checked-exceptions

http://mikehadlow.blogspot.co.at/2009/08/first-rule-of-exception-handling-do-not.html

http://blogs.atlassian.com/2011/05/exceptions_are_bad/

http://tapestryjava.blogspot.in/2011/05/tragedy-of-checked-exceptions.html

Thank you for your attention!

Sources:
Presentation by Peter Nagy (https://prezi.com/fmcp-mnimush/exception-handling-in-java-part-1)
Effective Java 2nd Edition, Joshua Bloch
Clean Code, Robert C. Martin
Oracle Community (https://community.oracle.com/docs/DOC-983543#catchingException)
http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html