ServiceLayer异常未在控制器上捕获

时间:2013-09-05 03:07:47

标签: java spring spring-mvc exception-handling

测试我的应用程序我决定关闭数据库。

public Object getEntityById(Class<?> clazz, Object _id) throws PersistenceServiceException {
    Object o = null;
    try {
        o = entityManager.find(clazz, _id);
    } catch (Exception e) {
        throw new PersistenceServiceException(e);
    }
    return o;
}

所以,应该将任何数据库异常传递给调用者

在控制器中我有

    try {
        template = (Template)persistenceService.getEntityById(Template.class, id);
    } catch (PersistenceServiceException e) {
        response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        response.setStatusMessage("INTERNAL SERVER ERROR");
        response.setData(e);
        return  response;
    }

调试时,我可以看到DatabaseException被抛出。

但在servlet上下文中,一旦我有了这个......

<beans:bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
    <beans:property name="defaultErrorView" value="core/error.uncatched" />
</beans:bean>

它将上述错误视为未处理。

如何在控制器上捕获它?为什么会这样?

例外

ERROR: org.springframework.transaction.interceptor.TransactionInterceptor - **Application exception overridden by commit exception**
com.company.exceptions.PersistenceServiceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.0.v20130619-7d05127): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

3 个答案:

答案 0 :(得分:0)

您应该使用PersistenceException来捕获异常。因为您使用的是JPA。

答案 1 :(得分:0)

事实上,Transactional上下文抛出了一个TransactionSystemException(一个RunTimeException),所以我所做的包装版本是由TransactionSystemException再次包装的。最后一个需要添加到控制器中的catch子句中。

无论如何,我现在没有将其标记为正确。如果有人想要添加一些东西,欢迎。

答案 2 :(得分:0)

stacktrace显示了以下两个例外:

  

内部异常:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:通信链接失败

这意味着无法访问数据库。这是因为您已关闭数据库。 Here是关于此例外的讨论。

  

错误:org.springframework.transaction.interceptor.TransactionInterceptor - 由提交异常覆盖的应用程序异常

Spring框架的事务基础结构的默认配置仅在抛出的Exception是未经检查的异常时标记回滚事务。如果已将PersistenceServiceException定义为已检查的异常,则不会导致Spring事务中的回滚。您正在捕获未经检查的异常(在您的getEntityById方法中),将其转换为已检查的异常,然后您将抛出此已检查的异常。

要解决此问题,您可以将事务基础结构配置为通过

回滚PersistenceServiceException的事务
  

PersistenceServiceException更改为运行时异常(PersistenceServiceException extends RuntimeException)

或通过

注释您的服务
  

@Transactional(rollbackFor = PersistenceServiceException.class)