3
\$\begingroup\$

I am developing a webapp using Spring MVC + Hibernate. I created a GenericDao class that implements basic data access methods, to be extended by all my concrete daos in the app. What I want advice or review about is the exception handling of the data access layer exceptions. Let me post a shortened version of my generic Dao class:

public class GenericDaoHibernateImpl<E, PK extends Serializable> extends AbstractDaoHibernateImpl implements
        GenericDao<E, PK> {


    private Class<E> entityClass;


    @SuppressWarnings("unchecked")
    public GenericDaoHibernateImpl() {
        this.entityClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public Class<E> getEntityClass() {
        return entityClass;
    }


    public void saveOrUpdate(E entity) throws GenericDataBaseException {
        try {
            getSession().saveOrUpdate(entity);
        } catch (Throwable t) {
            Collection<Object> args = new ArrayList<Object>();
            args.add(entity);
            throw exceptionHandler.handle(this, t, "saveOrUpdate", args);
        }
    }



    public void delete(PK id) throws GenericDataBaseException, InstanceNotFoundException {
        try {
            getSession().delete(findById(id));
        } catch (InstanceNotFoundException t) {
            throw t;
        } catch (Throwable t) {
            Collection<Object> args = new ArrayList<Object>();
            args.add(id);
            throw exceptionHandler.handle(this, t, "delete", args);
        }
    }

    @SuppressWarnings("unchecked")
    public E findById(PK id) throws GenericDataBaseException, InstanceNotFoundException {
        try {
            E entity = (E) getSession().get(entityClass, id);

            if (entity == null)
                throw new InstanceNotFoundException(id, entityClass.getName());

            return entity;
        } catch (InstanceNotFoundException t) {
            throw t;
        } catch (Throwable t) {
            Collection<Object> args = new ArrayList<Object>();
            args.add(id);
            throw exceptionHandler.handle(this, t, "findById", args);
        }
    }

    @SuppressWarnings("unchecked")
    public List<E> findByProperty(String propertyName, Object propertyValue, String orderBy, boolean isOrderAsc,
            int firstResult, int maxResults) throws GenericDataBaseException, NoSearchResultException {
        try {
            Criteria criteria = getSession().createCriteria(getEntityClass());
            criteria.add(Expression.eq(propertyName, propertyValue));
            criteria.addOrder(getOrder(orderBy, isOrderAsc));
            criteria.setFirstResult(firstResult);
            criteria.setMaxResults(maxResults);

            List<E> result = criteria.list();

            if (result == null || result.size() == 0)
                throw new NoSearchResultException("", getEntityClass());

            return result;
        } catch(NoSearchResultException t)
        {
            throw t;
        }
        catch (Throwable t) {
            Collection<Object> args = new ArrayList<Object>();
            args.add(propertyName);
            args.add(propertyValue);
            args.add(orderBy);
            args.add(isOrderAsc);
            args.add(firstResult);
            args.add(maxResults);
            throw exceptionHandler.handle(this, t, "findByProperty", args);
        }
    }

}

What I do is throw my own created exceptions (InstanceNotFound, NoSearchResults, GenericDatabaseException) and propagate them to the controller, where I catch them using @ExceptionHandler annotation:

@Controller
public class MyControllerextends BaseController {



 public String myMethod(Model model) throws NoSearchResultException {
       (...)
    }

      @ExceptionHandler(InstanceNotFoundException.class)
        public ModelAndView  instanceNotFoundException(InstanceNotFoundException e) {
            String message ="Error inesperado";
            message = "Element with provided ID was not found"; 
            return devuelvePaginaError(message);
        }

        @ExceptionHandler(NoSearchResultException.class)
        public ModelAndView  handleNoSearchResultException(NoSearchResultException e) {
            String message ="Error inesperado";
            message = "Search of " + e.getObjectClass().getSimpleName() + " with no results";
            return devuelvePaginaError(message);
        }
}

My question is, am I doing this correctly? Should I catch my exceptions earlier, in another layer? Should I even model events like "instance not found" or "No search results" as Exceptions?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

I would say don't set rules like "I will catch exceptions in this layer." With exceptions you have two options catch them or throw them. If you know what to do with exception then catch it and proccess it in the catch section. If you dont know what to do at the current level(layer) throw it. Of course the last line of defence is before the view layer where you should catch the ones that you didn't managed to catch in the other layers and show somethin meaningful to the user.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.