Exception Translation in Java vs. Scala

Exception Translation is a very important pattern to prevent your code from being cluttered by framework specific exception types. For example, you don’t want to deal with JDBC exceptions in your business code, especially because you might want to switch to JPA or a NoSQL database some day.
The idea is to translate all vendor specific exceptions to an internal exception hierarchy before they cross layer or module boundaries. So, a developer of an higher level module has only to deal with a known set of possible exceptions and will not get headaches because of cryptic database exceptions.
Since Exception Translation is a cross cutting concern it should not be done in the production code. Lower level modules should not even know about the exception hierarchy used up the call stack by higher level modules.

Let’s say we have an persistence layer with repositories that throw all kinds of javax.persistence Exceptions and a service layer that only want to deal with internal exceptions:

@Repository
public class CustomerRepositoryImpl implements CustomerRepository {
  @PersistenceContext
  private EntityManager entityManager;

  public Customer persist(Customer customer) {
     //Could throw an javax.persistence.OptimisticLockException
     return this.entityManager.merge(partner);
  }  
}
   //In the service code
   try {
      this.customerRepository.persist(customer);
   } catch (my.ConcurrentUpdateException e) {
     //Deal with it
   }

In Java the only way to do such a translation is AOP. In Spring you could do something like this:

public class ExceptionTranslator {

  public void handleException(Throwable ex) {
    if (ex instanceof javax.persistence.OptimisticLockException) {
      return new my.ConcurrentUpdateException(
        "Concurrent update", ex);
    }
    //more
  }
}
<bean id="exceptionTranslator" class="my.ExceptionTranslator"/>

<aop:config>
  <aop:aspect ref="exceptionTranslator">
    <aop:pointcut id="repositoryMethod" 
       expression="within( @org.springframework.stereotype.Repository *)" />
    <aop:after-throwing pointcut-ref="repositoryMethod" 
       method="handleException" throwing="ex"/>
  </aop:aspect>
</aop:config>

This approach is of course quite magic (as AOP always is) and might be confusing to developers. Because they throw an exception on one end and have to catch another one at the other.

In Scala is is possible to integrate the exception translation directly in the code, but do the actual translation at one place at the same time. Due to the magic of closures and lazy evaluation. Remember, in Scala you can defer the evaluation of an method argument with the “=>” operator.

So, we could do this:

def persist(customer: Customer): Customer = {
  translateExceptions {
    this.customerRepository.persist(customer)
  }
}

If the translateExceptions Method looks like this:

def translateExceptions[T <: Any](body: => T): T = {
  try {
    body //Evaluate the given method body
  } catch {
    case e: javax.persistence.OptimisticLockException 
      => throw new my.ConcurrentUpdateException("Concurrent udpate", e)
  }
}

You could put the translation method into a Scala object and use it from everywhere:


object ExceptionTranslator {
  def apply[T <: Any](body: => T): T = {
  try {
    body
  } catch {
    case e: javax.persistence.OptimisticLockException 
      => throw new my.ConcurrentUpdateException("Concurrent udpate", e)
  }
}

//And use it like this:
def persist(customer: Customer): Customer = {
  ExceptionTranslator {
    this.customerRepository.persist(customer)
  }
}

Much smarter, much more understandable as in Java.