5
\$\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?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Sep 3, 2013 at 7:20
\$\endgroup\$

3 Answers 3

5
\$\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 an exception then catch it and process it in the catch section. If you do not know what to do at the current level(layer) then throw it. Of course the last line of defence is before the view layer where you should catch the ones that you didn't manage to catch in the other layers and show something meaningful to the user.

Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges201 bronze badges
answered Jan 6, 2014 at 18:32
\$\endgroup\$
2
\$\begingroup\$

My question is, am I doing this correctly?

If you don't know anything about recovering from failure then the implemented solution is usual business, otherwise catching Throwable could be improved by catching exceptions and caching errors to enable recovering solutions (e.g. catching OutOfMemoryError could be recovered from by re-running the statement with result pagination parameters).

The short answer is yes and no, depending on the complexity the application could/should handle.

answered 2 days ago
New contributor
user293258 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$
2
\$\begingroup\$

You can follow MVC and OOP design best practices. Look into your company's framework(many companies either build their own or rely on a popular one). Each layer should take care of its own responsibility:

DAO layer: should only deal with persistence/technical concerns.

Service layer: should apply business rules, interpret persistence failures, and decide what the controller should see.

Controller layer: should focus on UI/response concerns, not Hibernate details.

answered 2 days ago
New contributor
peter8015 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.