package io.dropwizard.hibernate; import org.glassfish.jersey.spi.ExtendedExceptionMapper; import org.hibernate.exception.DataException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.persistence.PersistenceException; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.ext.ExceptionMapper; import javax.ws.rs.ext.Provider; import javax.ws.rs.ext.Providers; @Provider public class PersistenceExceptionMapper implements ExtendedExceptionMapper<PersistenceException> { private static final Logger LOGGER = LoggerFactory.getLogger(DataException.class); @Context private Providers providers; @Override public Response toResponse(PersistenceException e) { LOGGER.error("Hibernate error", e); Throwable t = e.getCause(); // PersistenceException wraps the real exception, so we look for the real exception mapper for it // Cast is necessary since the return type is ExceptionMapper<? extends Throwable> and Java // does not allow calling toResponse on the method with a Throwable @SuppressWarnings("unchecked") final ExceptionMapper<Throwable> exceptionMapper = (ExceptionMapper<Throwable>) providers.getExceptionMapper(t.getClass()); return exceptionMapper.toResponse(t); } @Override public boolean isMappable(PersistenceException e) { return providers.getExceptionMapper(e.getCause().getClass()) != null; } }