簡體   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