繁体   English   中英

Spring真的用REQUIRES_NEW开始新的交易吗?

[英]Does Spring actually start a new transaction with REQUIRES_NEW?

我的spring(4.1.1)应用程序部署在JBoss-6.10-final实例上,因此它使用基于容器的事务管理器和数据源。 对于消息传递,我使用TIBCO EMS 8.1和XA队列连接工厂设置。 Java版本是1.8.0_20。 所有这些都在我的Ubuntu 14.04笔记本电脑上运行。

我需要通过JMS发送请求,然后等待回复。 我正在调用的bean将事务传播设置为Propagation.REQUIRED,因此我需要在新事务中发送请求,然后等待回复。 这意味着请求在一个单独的bean中发送,事务传播设置为Propagation.REQUIRES_NEW。 它有效,但我收到了JBoss的一个令人担忧的警告:

14-10-02 12:06:12,902 WARN [org.jboss.tm.usertx.UserTransactionRegistry](http-0.0.0.0-8080-1)错误通知监听器userRnsactionStarted的org.jboss.resource.connectionmanager.CachedConnectionManager@1917b4de: java.lang.IllegalStateException: 尝试在enlist中更改事务TransactionImple <ac,BasicAction:0:ffff7f000101:126a:542d2010:d8 status:ActionStatus.RUNNING> 在org.jboss.resource.connectionmanager.TxConnectionManager $ TxConnectionEventListener.enlist(TxConnectionManager.java:690)在org.jboss.resource.connectionmanager.TxConnectionManager.transactionStarted(TxConnectionManager.java:427)在org.jboss.resource.connectionmanager.CachedConnectionManager在org.jboss.tm.usertx.UserTransactionRegistry.userTransactionStarted(UserTransactionRegistry.java:119)在org.jboss.tm.usertx.client.ServerVMClientUserTransaction.begin(ServerVMClientUserTransaction.java:141).userTransactionStarted(CachedConnectionManager.java:350)在org.springframework.transaction.jta.JtaTransactionManager.doJtaBegin(JtaTransactionManager.java:875)atg.springframework.transaction.jta.JtaTransactionManager.doBegin(JtaTransactionManager.java:832)org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction( AbstractPlatformTransactionManager.java:425)org.springframework.transaction.support.AbstractPlatformTransactionManager.getTr 位于org.springframework的org.springframework.transaction.transaction.transaction.transaction.Traringaction(TransactionAspectSupport.java:261)的org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:438)的ansaction(AbstractPlatformTransactionManager.java:349)位于org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)的.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java) :207)at com.siz.proxy。$ Proxy234.request(Unknown Source)at com.izazi.ioriginate.framework.spring.jms.AbstractRequestReply.request(AbstractRequestReply.java:58)at com.izazi.ioriginate.service。 sunvalid.ationValidationServiceImpl.validate(AddressValidationServiceImpl.java:34)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMet hodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在java.lang.reflect.Method.invoke(Method.java:483)在org.springframework.aop.support .AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)atg.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)at org.springframework.transaction.interceptor.TransactionInterceptor $ 1.proceedWithInvocation(TransactionInterceptor.java:98)在org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266)在org.springframework.transaction.interceptor.TransactionInterceptor.invoke (TransactionInterceptor.java:95)org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)at org。 springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)在com.sun.proxy $ Proxy235.validate(来源不明)在com.izazi.ioriginate.services.dwr.AddressValidation.validate(AddressValidation.java: 40)在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在java.lang.reflect中.Method.invoke(Method.java:483)在org.directwebremoting.impl.ExecuteAjaxFilter.doFilter(ExecuteAjaxFilter.java:34)在org.directwebremoting.impl.DefaultRemoter $ 1.doFilter(DefaultRemoter.java:428)在org.directwebremoting .impl.DefaultRemoter.execute(DefaultRemoter.java:431)在org.directwebremoting.impl.DefaultRemoter.execute(DefaultRemoter.java:283)在org.directwebremoting.servlet.PlainCallHandler.handle(PlainCallHandler.java:52)在有机org中的directwebremoting.servlet.UrlProcessor.handle(UrlProcessor.java:101)。 directwebremoting.servlet.DwrServlet.doPost(DwrServlet.java:146)在javax.servlet.http.HttpServlet.service(HttpServlet.java:754)在javax.servlet.http.HttpServlet.service(HttpServlet.java:847)在组织位于org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter的org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)上的.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324) (FilterChainProxy.java:330)在org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)在org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java :84)在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)在org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)在org.springframework。 security.web。 的FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)在org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(的FilterChainProxy。 Java的:342)在org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)在org.springframework org.springframework.security.web.savedrequest.RequestCacheAwareFilter上的.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342) .doFilter(RequestCacheAwareFilter.java:45)at org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java) :342)在org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:201)在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)的组织。 springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:155)位于org.springframework.security.web的org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)。在org.springframework.security.web.authentication.logout.LogoutFilter.doFilter的org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)中的authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) LogoutFilter.java:110)org.springframework.security.web.context.re上的org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342) 在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy。)的org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)中的quest.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)。 Java的:342)在org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)在org.springframework org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)中的.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java) :344)atg.apringframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(App) licationFilterChain.java:274)在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)在org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)在org.apache.catalina .core.StandardContextValve.invoke(StandardContextValve.java:161)在org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:181)在org.jboss.modcluster.catalina.CatalinaContext $ RequestListenerValve.event(CatalinaContext的.java:285)在org.jboss.modcluster.catalina.CatalinaContext $ RequestListenerValve.invoke(CatalinaContext.java:261)在org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:88)的组织。 jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:100)在org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:159)在org.apache.catalina.valves.ErrorReportValve.invoke( ErrorReportValve.java:102)org.jboss.web.tomcat.service.jca .CachedConnectionValve.invoke(CachedConnectionValve.java:158)在org.apache.catalina.valves.RequestDumperValve.invoke(RequestDumperValve.java:151)在org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)在org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke在org.apache.coyote.http11(ActiveRequestResponseCacheValve.java:53)在org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362)。 Http11Processor.process(Http11Processor.java:877)在org.apache.coyote.http11.Http11Protocol $在org.apache.tomcat.util.net.JIoEndpoint $ Worker.run(JIoEndpoint Http11ConnectionHandler.process(Http11Protocol.java:654)。 java:951)at java.lang.Thread.run(Thread.java:745)

......在EMS方面,我看到了一些XA错误:

johan @ my_machine:〜/ opt / jboss-6.1.0.Final / bin $ 2014-10-02 10:43:15.801错误:不存在的消费者的交易:15 connID = 16 sessID = 20 {formatID = 131076 gtrid_length = 29 bqual_length = 28 data =%00%00%00%00%00%00%00%00%00%00%FF%FF%7F%00%01%01%00%00%12jT-%0D *%00 %00%00%AF1%00%00%00%00%00%00%00%00%00%00%FF FF%7F%00%01%01%00%00%%12jT-%0D * 00% %00%00%B1} 2014-10-02 10:43:15.832错误:处理xa end时出错 - 事务标记为ROLLBACKONLY,Exception。 connID = 16 sessID = 20 {formatID = 131076 gtrid_length = 29 bqual_length = 28 data =%00%00%00%00%00%00%00%00%00%00%FF%FF%7F%00%01%01 %00%00%12jT-%0D *%00%00%00%AF1%00%00%00%00%00%00%00%00%00%00%FF FF%7F%00%01%01% %00%00%12jT-%0D *%00%00%00%B1}

在查看堆栈跟踪之后,我打开了Spring的AbstractPlatformTransactionManager的源代码,并遇到了以下代码,用于处理REQUIRES_NEW(从第415行开始):

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
    if (debugEnabled) {
        logger.debug("Suspending current transaction, creating new transaction with name [" +
                definition.getName() + "]");
    }
    SuspendedResourcesHolder suspendedResources = suspend(transaction);
    try {
        boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        DefaultTransactionStatus status = newTransactionStatus(
                definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
        doBegin(transaction, definition);
        prepareSynchronization(status, definition);
        return status;
    }
    catch (RuntimeException beginEx) {
        resumeAfterBeginException(transaction, suspendedResources, beginEx);
        throw beginEx;
    }
    catch (Error beginErr) {
        resumeAfterBeginException(transaction, suspendedResources, beginErr);
        throw beginErr;
    }
}

我的问题是:新的交易在哪里开始?

从表面上看,它似乎正在使用现有的事务而不是正在启动的新事务 - 请参阅如何将'事务'传递给doBegin(...)。 我也查看了doBegin,并且没有指示要求或创建新事务。 这个视图似乎得到了我从JBoss获得的堆栈跟踪和警告的支持......

很高兴看到我并非孤身一人被困在这个无洞的洞里......

据我所知,此警告的深层原因在这里描述(线程结束)

当外部事务被挂起并且新的内部事务开始时,Jboss连接池为内部事务检索的托管连接与外部事务的托管连接相同,这导致抛出IllegalStateException!

并且是由于jboss JCA合同实施的特定行为( Lazy JCA enlistment )。

在弹簧方面打开了一个缺陷 ,标记为“将无法修复”,但它们提供了一种解决方法配置:

典型的解决方案是使用Spring的TransactionAwareDataSourceProxy并将“reobtainTransactionalConnections”标志切换为“true”

玩得开心 !

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM