Friday 1 June 2012

The problem of checked exceptions in java


One thing that I really don't like about java is the use and abuse of checked exceptions.  They:

1) Pollute the code.  

With checked exceptions you either need to have try catch blocks all over the place or you need declare that the method throws a checked exception ie.

public void myMethod() {
  try {
     FileInputStream fis = new FileInputStream( "c:/file" );
  }

  catch( IOException e ) {
    //do something
  }
}

or

public void myMethod() throws IOException {
    FileInputStream fis = new FileInputStream( "c:/file" );

}

The problem with the second example is that in the calling class you then need to deal with the exception.

2) Lead to naive developers thinking they know best 


public void myMethod() throws CorporateException {
  try {
     FileInputStream fis = new FileInputStream( "c:/file" );

  }
  catch( IOException e ) {
    throw new CorporateException( "An error has occured: " + e.getMessage() );
  }
}



This is not particularly helpfull as the actual real reason of the failure (ie. the IOException) has been swallowed.

The number of times I've seen this, with the only thing to go on a message saying "CorporateException : message: java.lang.NullPointeException".  It's useless to me as I've got no line number to go on as the original NullPointerException has been swallowed.

3) Nested stack traces

public void myTopLevelMethod() throws CorporateException {
  try {
     myMethod1();
  myMethod2();
      FileInputStream fis = new FileInputStream( "c:/file" );
  }
  catch(  Exception  e ) {
     throw new CorporateException( "An error orccured in the top level method", e );
  }
}



This could result in a very long stack trace full of repeated exceptions!  The number of times I've seen this.

4) Transactions not rolling back

When using EJB's or Spring to manage transactions, the key is to ensure that a RuntimeException crosses the transaction boundary if the rollback is to be triggered.  If the naive developer declares that his methods throws a checked exception, then the transaction management will not work as expected.

------------------


What can we do?


  1. Do not use checked exceptions.
  2. Do not create a CorporateException class
  3. When a method does trigger a checked exception convert it immediately into a RuntimeException
  4. Policy that no methods are allowed to throw checked exceptions.
  5. If you do need to add context do this in a dedicated single layer which all code will fall through ie. a Servlet in a web app. or via a hook in whatever framework you are using eg. spring batch @OnWriteError. This should worked out as part of the software architecture and not left to each and every developer.



No comments:

Post a Comment