Spring AOP,@JaversAuditable 在抛出异常时仍在尝试提交更改
Spring AOP, @JaversAuditable still trying to commit a change when exception has been thrown
这是 Spring 4.1.9.RELEASE,Spring-Data 1.11.4.RELEASE,Javers 1.6.0 spring 集成
因此,将 Spring 与 @JaversAuditable
一起使用,我发现如果在我尝试插入时出现异常处理(例如重复键异常),JaversTransactionalDecorator
仍然会继续并且尝试生成提交。
但是,由于插入失败导致我的实体没有 ID,因此 Javers 最终抛出异常(见下文)。通过调试,我发现我最终进入了 finally 块中的 org.springframework.aop.aspectjAspectJAfterAdvice.invoke()
。然后调用 invokeAdviceMethod(JoinPointMatch,null,null)
,第 3 个 null
是 Throwable
.
的位置
根据http://docs.spring.io/spring/docs/4.1.9.RELEASE/spring-framework-reference/html/aop.html,@After
通知将运行作为finally,无论该方法是否正常存在或异常。因此,听起来 Javers 需要能够检测是否已抛出异常,或者使用不同的 Advice,如 @AfterReturning
,可能带有单独的 @AfterThrowing
。我试图在当前的 @After
中找出 Javers 具有( org.javers.spring.auditable.aspect.JaversAuditableRepositoryAspect.commitAdvice(JoinPoint pjp)
)它如何能够检测是否 exception/throwable 已被抛出,但我似乎无法在文档中找到任何相关内容。
那么,这是 Javers 已经拥有的东西,但由于某种原因,它没有正确地接收到抛出的 SQL 异常,或者 @After
中的一些检测信息建议抛出的 exception/throwable 这样我就可以参与并为此做出修复?
很抱歉可能不太有条理,我在这里比正常时间晚了几个小时。
Caused by: org.javers.common.exception.JaversException: ENTITY_INSTANCE_WITH_NULL_ID Found Entity instance of class 'com.findology.api.model.publisher.Publisher' with null id
at org.javers.core.metamodel.type.EntityType.getIdOf(EntityType.java:96)
at org.javers.core.metamodel.object.InstanceId.createFromInstance(InstanceId.java:28)
at org.javers.core.metamodel.object.GlobalIdFactory.createId(GlobalIdFactory.java:47)
at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:24)
at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:9)
at org.javers.core.graph.EdgeBuilder.asCdo(EdgeBuilder.java:39)
at org.javers.core.graph.ObjectGraphBuilder.buildGraph(ObjectGraphBuilder.java:45)
at org.javers.core.graph.LiveGraphFactory.createLiveGraph(LiveGraphFactory.java:39)
at org.javers.core.commit.CommitFactory.create(CommitFactory.java:76)
at org.javers.core.JaversCore.commit(JaversCore.java:70)
at org.javers.spring.jpa.JaversTransactionalDecorator.commit(JaversTransactionalDecorator.java:52)
at org.javers.spring.jpa.JaversTransactionalDecorator$$FastClassBySpringCGLIB$$acb40bd0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:718)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at org.javers.spring.jpa.JaversTransactionalDecorator$$EnhancerBySpringCGLIB$$c6591394.commit(<generated>)
at org.javers.spring.auditable.aspect.JaversCommitAdvice.commitMethodArguments(JaversCommitAdvice.java:24)
at org.javers.spring.auditable.aspect.JaversAuditableRepositoryAspect.commitAdvice(JaversAuditableRepositoryAspect.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:603)
at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:46)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at com.findology.api.dao.PublisherDao$$EnhancerBySpringCGLIB$ba00510.insert(<generated>)
at com.findology.api.controller.SimpleController.createPublisher(SimpleController.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:775)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:965)
... 74 common frames omitted
你是对的,@JaversAuditable 不应该在建议的存储库方法抛出异常时调用 javers.commit()。你能想出一个 PR 来在 JaVers 中解决这个问题吗(使用 'on success' 切入点,也许像你提到的那样 @AfterReturning)?
因此,根据 Spring 文档,最终解决方案正在更改为使用 @AfterReturning,根据 https://github.com/javers/javers/pull/356,它正在被接受,因此未来的版本将包含此修复程序。
这是 Spring 4.1.9.RELEASE,Spring-Data 1.11.4.RELEASE,Javers 1.6.0 spring 集成
因此,将 Spring 与 @JaversAuditable
一起使用,我发现如果在我尝试插入时出现异常处理(例如重复键异常),JaversTransactionalDecorator
仍然会继续并且尝试生成提交。
但是,由于插入失败导致我的实体没有 ID,因此 Javers 最终抛出异常(见下文)。通过调试,我发现我最终进入了 finally 块中的 org.springframework.aop.aspectjAspectJAfterAdvice.invoke()
。然后调用 invokeAdviceMethod(JoinPointMatch,null,null)
,第 3 个 null
是 Throwable
.
根据http://docs.spring.io/spring/docs/4.1.9.RELEASE/spring-framework-reference/html/aop.html,@After
通知将运行作为finally,无论该方法是否正常存在或异常。因此,听起来 Javers 需要能够检测是否已抛出异常,或者使用不同的 Advice,如 @AfterReturning
,可能带有单独的 @AfterThrowing
。我试图在当前的 @After
中找出 Javers 具有( org.javers.spring.auditable.aspect.JaversAuditableRepositoryAspect.commitAdvice(JoinPoint pjp)
)它如何能够检测是否 exception/throwable 已被抛出,但我似乎无法在文档中找到任何相关内容。
那么,这是 Javers 已经拥有的东西,但由于某种原因,它没有正确地接收到抛出的 SQL 异常,或者 @After
中的一些检测信息建议抛出的 exception/throwable 这样我就可以参与并为此做出修复?
很抱歉可能不太有条理,我在这里比正常时间晚了几个小时。
Caused by: org.javers.common.exception.JaversException: ENTITY_INSTANCE_WITH_NULL_ID Found Entity instance of class 'com.findology.api.model.publisher.Publisher' with null id
at org.javers.core.metamodel.type.EntityType.getIdOf(EntityType.java:96)
at org.javers.core.metamodel.object.InstanceId.createFromInstance(InstanceId.java:28)
at org.javers.core.metamodel.object.GlobalIdFactory.createId(GlobalIdFactory.java:47)
at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:24)
at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:9)
at org.javers.core.graph.EdgeBuilder.asCdo(EdgeBuilder.java:39)
at org.javers.core.graph.ObjectGraphBuilder.buildGraph(ObjectGraphBuilder.java:45)
at org.javers.core.graph.LiveGraphFactory.createLiveGraph(LiveGraphFactory.java:39)
at org.javers.core.commit.CommitFactory.create(CommitFactory.java:76)
at org.javers.core.JaversCore.commit(JaversCore.java:70)
at org.javers.spring.jpa.JaversTransactionalDecorator.commit(JaversTransactionalDecorator.java:52)
at org.javers.spring.jpa.JaversTransactionalDecorator$$FastClassBySpringCGLIB$$acb40bd0.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:718)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at org.javers.spring.jpa.JaversTransactionalDecorator$$EnhancerBySpringCGLIB$$c6591394.commit(<generated>)
at org.javers.spring.auditable.aspect.JaversCommitAdvice.commitMethodArguments(JaversCommitAdvice.java:24)
at org.javers.spring.auditable.aspect.JaversAuditableRepositoryAspect.commitAdvice(JaversAuditableRepositoryAspect.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:603)
at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:46)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168)
at org.springframework.transaction.interceptor.TransactionInterceptor.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
at com.findology.api.dao.PublisherDao$$EnhancerBySpringCGLIB$ba00510.insert(<generated>)
at com.findology.api.controller.SimpleController.createPublisher(SimpleController.java:82)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:775)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:965)
... 74 common frames omitted
你是对的,@JaversAuditable 不应该在建议的存储库方法抛出异常时调用 javers.commit()。你能想出一个 PR 来在 JaVers 中解决这个问题吗(使用 'on success' 切入点,也许像你提到的那样 @AfterReturning)?
因此,根据 Spring 文档,最终解决方案正在更改为使用 @AfterReturning,根据 https://github.com/javers/javers/pull/356,它正在被接受,因此未来的版本将包含此修复程序。