mscharhag, Programming and Stuff;

A blog about programming and software development topics, mostly focused on Java technologies including Java EE, Spring and Grails.

Thursday, 4 June, 2015

Exception Translation with ET

Some time ago I wrote a small blog post about exception translation with AspectJ. In this blog post we will see how to accomplish the same using ET and its lighter Java 8 approach.

Motivation

Exception translation (or exception conversion) is the process of converting one type of exception into another. The Java code to translate an exception is quite simple and I think every Java developer writes something like this from time to time:

try {
  // code that can throw FooException
} catch(FooException e) {
  // convert FooException to BarException
  throw new BarException(e);
}

Exception translation is typically applied if exceptions from third party libraries do not fit into your application. Reasons for this might be:

  • Exceptions thrown by a library are too low level and/or you do not want to leak implementation details into other parts of your application. For example, you want to use a more generic DataAccessException instead of a lower level SQLException.
  • A library is using checked exception while you prefer using only runtime exception in your application.

Exception Translation with ET

ET is a small and simple library for exception translation. To get started with ET, you just need to add the following dependency to your code:

<dependency>
  <groupId>com.mscharhag</groupId>
  <artifactId>et</artifactId>
  <version>0.2.0</version>
</dependency>

ET makes use of Java 8 features, so do not forget to set your compiler Level to Java 8.

We start with configuring an ExceptionTranslator instance:

ExceptionTranslator et = ET.newConfiguration()
    .translate(IOException.class).to(MyRuntimeException.class)        
    .translate(FooException.class, BarException.class).to(BazException.class)
    .done()

Here we create an ExceptionTranslator that converts IOException, FooException and BarException. IOException will be translated to MyRuntimeException while FooException and BarException are translated to BazException.

Please note that ET requires the translation target exceptions (here MyRuntimeException and BazException) to be RuntimeExceptions.
ExceptionTranslator instances are thread safe and immutable. It is safe to configure an ExceptionTranslator once and then make it globally available.

Now we can use our new ExceptionTranslator to wrap the code that can throw exceptions we want to convert.

et.withTranslation(() -> {
  // can throw IOException, FooException and/or BarException
  myObject.dangerOperation(); 
});

If now an IOException is thrown by dangerOperation() et will catch it. et then throws a new MyRuntimeException from the caught IOException. The original IOException is stored in the cause field of MyRuntimeException.

To return a value from a translation block withReturningTranslation() can be used:

MyResultClass data = et.withReturningTranslation(() -> {
  ...
  return myObject.dangerOperation(); 
});

Summary

ET is a small library that might be useful to you, if you have to do a lot of exception conversion in your code. After configuring your conversion rules once, exceptions can be converted by simply wrapping the code in a lambda expression.

Have a look at the full ET documentation on GitHub.

Leave a reply