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

时间:2014-10-02 10:59:55

标签: java jboss spring-transactions spring-jms

我的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警告   [org.jboss.tm.usertx.UserTransactionRegistry](http-0.0.0.0-8080-1)   通知监听器时出错   org.jboss.resource.connectionmanager.CachedConnectionManager@1917b4de   userTransactionStarted:java.lang.IllegalStateException:尝试   更改交易TransactionImple< ac,BasicAction:   0:ffff7f000101:126a:542d2010:d8状态:ActionStatus.RUNNING>在   入伍! at   org.jboss.resource.connectionmanager.TxConnectionManager $ TxConnectionEventListener.enlist(TxConnectionManager.java:690)   在   org.jboss.resource.connectionmanager.TxConnectionManager.transactionStarted(TxConnectionManager.java:427)   在   org.jboss.resource.connectionmanager.CachedConnectionManager.userTransactionStarted(CachedConnectionManager.java:350)   在   org.jboss.tm.usertx.UserTransactionRegistry.userTransactionStarted(UserTransactionRegistry.java:119)   在   org.jboss.tm.usertx.client.ServerVMClientUserTransaction.begin(ServerVMClientUserTransaction.java:141)   在   org.springframework.transaction.jta.JtaTransactionManager.doJtaBegin(JtaTransactionManager.java:875)   在   org.springframework.transaction.jta.JtaTransactionManager.doBegin(JtaTransactionManager.java:832)   在   org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction(AbstractPlatformTransactionManager.java:425)   在   org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:349)   在   org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:438)   在   org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:261)   在   org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)   在   org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)   在   org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)   在com.sun.proxy。$ Proxy234.request(未知来源)at   com.izazi.ioriginate.framework.spring.jms.AbstractRequestReply.request(AbstractRequestReply.java:58)   在   com.izazi.ioriginate.service.addressvalidation.AddressValidationServiceImpl.validate(AddressValidationServiceImpl.java:34)   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)   在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)   在java.lang.reflect.Method.invoke(Method.java:483)at   org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)   在   org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)   在   org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)   在   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)   在   org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)   在com.sun.proxy。$ Proxy235.validate(未知来源)at   com.izazi.ioriginate.services.dwr.AddressValidation.validate(AddressValidation.java:40)   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)   在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)   在java.lang.reflect.Method.invoke(Method.java:483)at   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)   在   org.directwebremoting.servlet.DwrServlet.doPost(DwrServlet.java:146)   在javax.servlet.http.HttpServlet.service(HttpServlet.java:754)at   javax.servlet.http.HttpServlet.service(HttpServlet.java:847)at at   org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324)   在   org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242)   在   org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(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.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)   在   org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)   在   org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)   在   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)   在   org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:155)   在   org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)   在   org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)   在   org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)   在   org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)   在   org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)   在   org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)   在   org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)   在   org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)   在   org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)   在   org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:342)   在   org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)   在   org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)   在   org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)   在   org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)   在   org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.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)   在   org.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(ActiveRequestResponseCacheValve.java:53)   在   org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362)   在   org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)   在   org.apache.coyote.http11.Http11Protocol $ Http11ConnectionHandler.process(Http11Protocol.java:654)   在   org.apache.tomcat.util.net.JIoEndpoint $ Worker.run(JIoEndpoint.java:951)   在java.lang.Thread.run(Thread.java:745)

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

   @ 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   数据=%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-transaction时出错   标记为ROLLBACKONLY,例外。 connID = 16 sessID = 20 {formatID = 131076   gtrid_length = 29 bqual_length = 28   数据=%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获得的堆栈跟踪和警告......

1 个答案:

答案 0 :(得分:3)

很高兴看到我并不孤单被困在这个无洞的洞里......

据我所知,这个警告的深层原因被描述为here(线程结束)

  

当外部交易被暂停时和新的内部交易   启动,Jboss连接池检索的托管连接   内部交易与外部交易相同   事务,导致抛出IllegalStateException!

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

A defect has been opened on spring side,标记为"无法修复"但它们提供了一种解决方法配置:

  

典型的解决方案是使用Spring   TransactionAwareDataSourceProxy并切换   " reobtainTransactionalConnections"标记为" true"有

玩得开心!