Spring 4.1.0和aspectj:无法捕获异常

时间:2016-06-06 15:49:53

标签: java eclipse maven spring-mvc aspectj

我有一个使用Spring 4.1.0的Spring MVC应用程序。我的部分代码是由MyEclipse生成的,因为由于数据库更改,我经常不得不重新生成它,所以我选择使用方面向生成的类添加方法和属性,而不会在每次重新生成时丢失自定义。

最近我决定摆脱Eclipse构建,并希望改用Maven。我得到了一个Bamboo服务器,找到了我需要的所有依赖项,并且构建似乎完成得很好。但是,当我使用maven部署到tomcat的WAR时,我遇到了一个问题:我添加方面的方法无法捕获自己引发的异常。例如,这是我用来向生成的类添加方法的一个方面:

public Elementvalue ElementvalueDAOOligoExtension.getDrawdownRecoveryPeriod(Integer elementid, java.util.Calendar date, Double value, Integer elementvalueid, int startResult, int maxRows) throws DataAccessException {
    try {
        Query query = createNamedQuery("getDrawdownRecoveryPeriod", startResult, maxRows, elementid, date, value, elementvalueid);
        return (ch.oligofunds.oligoworld.domain.Elementvalue) query.getSingleResult();
    } catch (NoResultException nre) {
        return null;
    }
}

如您所见,我的想法是,如果我没有得到查询的结果,我返回null(然后由调用者正确处理)。但是,当调用此方法时,NoResultException实际上会向调用者冒泡,我可以在日志中找到它:

    org.springframework.dao.EmptyResultDataAccessException: No entity found for query; nested exception is javax.persistence.NoResultException: No entity found for query
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:392)
    at org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect.ajc$afterThrowing$org_springframework_orm_jpa_aspectj_JpaExceptionTranslatorAspect$1$18a1ac9(JpaExceptionTranslatorAspect.aj:33)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.getDrawdownRecoveryPeriod_aroundBody20(ElementvalueDAOImplAspect.aj:145)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect$AjcClosure21.run(ElementvalueDAOImplAspect.aj:1)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:59)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:65)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:63)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.ajc$interMethod$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ElementvalueDAOOligoExtension$getDrawdownRecoveryPeriod(ElementvalueDAOImplAspect.aj:141)
    at ch.oligofunds.oligoworld.dao.ElementvalueDAOImpl.getDrawdownRecoveryPeriod(ElementvalueDAOImpl.java:1)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.ajc$interMethodDispatch1$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ElementvalueDAOOligoExtension$getDrawdownRecoveryPeriod(ElementvalueDAOImplAspect.aj)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.getDrawdownRecoveryPeriod_aroundBody18(ElementvalueDAOImplAspect.aj:137)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect$AjcClosure19.run(ElementvalueDAOImplAspect.aj:1)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96cproceed(AbstractTransactionAspect.aj:59)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect$AbstractTransactionAspect$1.proceedWithInvocation(AbstractTransactionAspect.aj:65)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)
    at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$around$org_springframework_transaction_aspectj_AbstractTransactionAspect$1$2a73e96c(AbstractTransactionAspect.aj:63)
    at ch.oligofunds.oligoworld.aspects.dao.ElementvalueDAOImplAspect.ajc$interMethod$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ch_oligofunds_oligoworld_aspects_dao_ElementvalueDAOImplAspect$ElementvalueDAOOligoExtension$getDrawdownRecoveryPeriod(ElementvalueDAOImplAspect.aj:136)
    at ch.oligofunds.oligoworld.dao.ElementvalueDAOImpl.getDrawdownRecoveryPeriod(ElementvalueDAOImpl.java:1)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    ...

第四行到最后一行指向上面的代码行,我返回查询的单个结果。所以,我希望catch部分会捕获NoResultException,这显然不会发生。

我应该指出,当我在Eclipse中构建时,一切正常。因此,我认为eclipse如何构建这一点以及独立maven与aspectj-maven-plugin如何管理事物有一些根本的区别(这也是由于独立maven创建了一堆$ AjcClosureXXX.class文件这一事实暗示,如果我用Eclipse构建。

任何人都可以向正确的方向提供指针吗?我是否从根本上误解了maven构建此代码的方式与Eclipse的工作方式有关?

1 个答案:

答案 0 :(得分:0)

你所看到的是Spring JpaExceptionTranslatorAspect来自spring-aspects的行动。它将调用网站包含在EntityManagerEntityManagerFactoryEntityTransactionQuery的方法中,并转换这些方法调用中引发的异常并使用特定于Spring的{{1}包装它们} subtype如果可能的话。

基于Eclipse的构建与Maven构建之间的差异很可能是您的Eclipse构建使用Java编译器,而Maven构建使用的是AspectJ编译器或Java编译器 AspectJ编织器。所以Spring DataAccessException确实在基于Maven的构建中生效,但在基于Eclipse的构建中不生效。

尝试捕获特定于Spring的包装器JpaExceptionTranslatorAspect而不是EmptyResultDataAccessException或禁用NoResultException,以便不转换JPA异常。

此外,您应该将AJDT(AspectJ开发工具)插件安装到Eclipse中,并将项目配置为使用AspectJ编译器而不是Java编译器,以便您的Eclipse和Maven构建相同。