1
votes

We have a layered architecture and want to control exception handling at the application service layer. The layers below it will throw the necessary exceptions, but the service layer will provide the wrapper to the facade layer so the facade layer can expect a consistent exception class.

However, The service layer is using autowired components and basically all the errors are wrapped in spring exception (and hibernate) classes. Since this is not at the method level, how do I wrap them into a consistent service level exception class? Any ideas on how the service layer can take control over the exceptions wrapped in spring exception classes. I apologize if this question sounds too vague, but I can provide more details if needed. We are not using spring MVC.

Example below:

@Service("RuleService")
@Transactional
public class RuleService implements IRuleService  {

    @Autowired
    IPersistenceManager<IRuleBO, Long> pMgrRule;

    public AppServiceResponse createRule(RuleDTO ruleDTO) throws ApplicationException, ServerException {
    try {
        //do something
    }
    catch (PersistenceException pe) {
        throw new ApplicationException (pe);
    }
    catch (ServerException se) {
        throw se;
    }
    catch (Exception e) {
        throw new ApplicationException (e);
    }

At the persistence layer, it is something like..

@Transactional
public T save(T entity) throws ServerException, PersistenceException {
    try {
        getSession().saveOrUpdate(entity);
        return entity;
    }
    catch (JDBCException je) {
        throw new PersistenceException(je);
    }
    catch (QueryException qe) {
        throw new PersistenceException(qe);
    }
    catch (NonUniqueResultException nre) {
        throw new PersistenceException(nre);
    }
    catch (HibernateException he) {
        throw new ServerException(he);
    }
}

As you can see we want to return the ApplicationException from the service layer. But since the components are autowired, any database connection error, for example, would result in a HibernateException wrapped in a SpringException. Is there a way to take control of the exception from Spring?

1
some code examples will be useful :) - Marek Raki

1 Answers

3
votes

I would not declare any extra exceptions as long as you do not want to handle them later so..

@Service("RuleService")
@Transactional
public class RuleService implements IRuleService  {

    @Autowired
    IPersistenceManager<IRuleBO, Long> pMgrRule;

    public AppServiceResponse createRule(RuleDTO ruleDTO) throws ApplicationException {
        //
        persistenceService.save(myEntity);
    }

and persistence like

@Transactional
public T save(T entity){
   getSession().saveOrUpdate(entity);
}

then you can create an ExceptionHandler aspect to handle all of exceptions from service layer and wrap them to ApplicationException

@Aspect
public class ExceptionHandler {

@Around("execution(public * xxx.xxx.services.*.*(..))")
public Object handleException(ProceedingJoinPoint joinPoint) throws Throwable {

Object retVal = null;

try {
  retVal = joinPoint.proceed();
}
catch (JDBCException jDBCException ) {
  throw new ApplicationException(jDBCException);
}
catch (JpaSystemException jpaSystemException) {
  throw new ApplicationException(jDBCException);
}
// and others

return retVal;

}

This kind of design can reduce your code complexity. You may appreciate this especially during the testing phase of you project. You have also here a clear design and one special component ONLY for handling exceptions.