Sunday, 5 June 2016

Java 8 Lambda Error Handling

In Java 8 streams and checked exceptions don't play too well. Having to catch the exception within lambda functions can, lead to some ugly code due to try catch clause. For example:
List<String> myList = Arrays.asList("1","2","3");
myList.stream().forEach( fileNumber -> {
  try {
    FileInputStream is = new FileInputStream("myFile" + fileNumber);
  }
  catch (Exception ex){
    throw new RuntimeException(ex);
  }
});
There have been many cases where converting a checked exception to an unchecked runtime exception is preferable so it can bubble out of the lambda function. However doing it manually everytime is a pain. So I have written a class to make this a little easier.

Usage Examples

Now this class can be used to uncheck the checked exceptions. For example: 
List<String> myList = Arrays.asList("1","2","3");
myList.stream().forEach( fileNumber -> {
  Err.uncheck0(() -> {
    FileInputStream is = new FileInputStream("myFile" + fileNumber);
  });
For when you have functions that return a value you can use uncheck1. For example
myList.stream().map( fileNumber -> {
  return Err.uncheck1(() -> {
    return Integer.parseInt(fileNumber);
  }
});
The code for the Err.java is below:

public class Err {

  /**
   * Interface where no return value is required
   */
  @FunctionalInterface
  interface Uncheck0 { public void run() throws Exception; }

  /**
   * Interface where a return value is required
   * @param <T>
   */
  @FunctionalInterface
  interface Uncheck1<T>{ public T run() throws Exception; }

  /**
   * Closure to convert checked exceptions into runtime ErrException,
   * use when a return value is not required
   * @param aUncheck0
   * @example Err.uncheck0(() ->{ ... })
   */
  public static void uncheck0(Uncheck0 aUncheck0) {
    try {
      aUncheck0.run();
    }
    catch (RuntimeException ex){
      throw ex;
    }
    catch (Exception ex){
      throw new ErrException(ex);
    }

  }

  /**
   * Closure to convert checked exceptions into runtime ErrException
   * use when a return value is requied
   * @param aUncheck1 code to run
   * @param <T> Return value type (inferred)
   * @return result of executing closure
   *
   * @example Integer result = Err.uncheck1(() ->{ ..; return 1});
   */
  public static <T> T uncheck1(Uncheck1<T> aUncheck1) {
    try {
      return aUncheck1.run();
    }
    catch (RuntimeException ex){
      throw ex;
    }
    catch (Exception ex){
      throw new ErrException(ex);
    }
  }

  public static class ErrException extends RuntimeException{
    public ErrException(Exception ex) {
      super(ex);
    }
  }
}

No comments:

Post a Comment