2014-10-02 2 views
4

Приложение моей весны (4.1.1) развертывается на экземпляре JBoss-6.10-final, поэтому он использует диспетчер транзакций на основе контейнеров и источники данных. Для обмена сообщениями я использую TIBCO EMS 8.1 с установленной фабрикой соединений XA. Версия Java - 1.8.0_20. Все это работает на моем ноутбуке Ubuntu 14.04.Действительно ли Spring запускает новую транзакцию с помощью REQUIRES_NEW?

Мне нужно отправить запрос через JMS, а затем дождаться ответа. Боб, из которого я звоню, имеет распространение транзакций, установленное в Propagation.REQUIRED, поэтому мне нужно отправить запрос в новую транзакцию, а затем дождаться ответа. Это означает, что запрос отправляется в отдельном компоненте с распространением транзакции, установленным в Propagation.REQUIRES_NEW. Это работает, но я получаю тревожное предупреждение от JBoss:

14-10-02 12:06:12,902 WARN [org.jboss.tm.usertx.UserTransactionRegistry] (http-0.0.0.0-8080-1) Error notifying listener [email protected]7b4de of userTransactionStarted: java.lang.IllegalStateException: Trying to change transaction TransactionImple < ac, BasicAction: 0:ffff7f000101:126a:542d2010:d8 status: ActionStatus.RUNNING > in enlist! at org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener.enlist(TxConnectionManager.java:690) at org.jboss.resource.connectionmanager.TxConnectionManager.transactionStarted(TxConnectionManager.java:427) at org.jboss.resource.connectionmanager.CachedConnectionManager.userTransactionStarted(CachedConnectionManager.java:350) at org.jboss.tm.usertx.UserTransactionRegistry.userTransactionStarted(UserTransactionRegistry.java:119) at org.jboss.tm.usertx.client.ServerVMClientUserTransaction.begin(ServerVMClientUserTransaction.java:141) at org.springframework.transaction.jta.JtaTransactionManager.doJtaBegin(JtaTransactionManager.java:875) at org.springframework.transaction.jta.JtaTransactionManager.doBegin(JtaTransactionManager.java:832) at org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction(AbstractPlatformTransactionManager.java:425) at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:349) at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:438) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:261) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy234.request(Unknown Source) at com.izazi.ioriginate.framework.spring.jms.AbstractRequestReply.request(AbstractRequestReply.java:58) at 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) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.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) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:266) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy235.validate(Unknown Source) 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) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at org.directwebremoting.impl.ExecuteAjaxFilter.doFilter(ExecuteAjaxFilter.java:34) at org.directwebremoting.impl.DefaultRemoter$1.doFilter(DefaultRemoter.java:428) at org.directwebremoting.impl.DefaultRemoter.execute(DefaultRemoter.java:431) at org.directwebremoting.impl.DefaultRemoter.execute(DefaultRemoter.java:283) at org.directwebremoting.servlet.PlainCallHandler.handle(PlainCallHandler.java:52) at org.directwebremoting.servlet.UrlProcessor.handle(UrlProcessor.java:101) at org.directwebremoting.servlet.DwrServlet.doPost(DwrServlet.java:146) at javax.servlet.http.HttpServlet.service(HttpServlet.java:754) at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:324) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:201) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:155) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:274) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:242) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:181) at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.event(CatalinaContext.java:285) at org.jboss.modcluster.catalina.CatalinaContext$RequestListenerValve.invoke(CatalinaContext.java:261) at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:88) at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:100) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:159) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158) at org.apache.catalina.valves.RequestDumperValve.invoke(RequestDumperValve.java:151) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.jboss.web.tomcat.service.request.ActiveRequestResponseCacheValve.invoke(ActiveRequestResponseCacheValve.java:53) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:362) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:654) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:951) at java.lang.Thread.run(Thread.java:745)

... и на стороне EMS, я вижу некоторые ошибки XA:

[email protected]_machine:~/opt/jboss-6.1.0.Final/bin$ 2014-10-02 10:43:15.801 ERROR: Transaction for non-existent consumer: 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 ERROR: Error processing xa end - transaction marked 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}

После просмотра трассировки стека Я открыл источник Спринга 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 ...

+0

Я не уверен, что поиск поможет вам каким-либо образом. Я видел это исключение несколько раз с JBoss, и это было либо ошибкой в ​​самом JBoss, либо неправильным использованием семантики транзакций. Если вы используете 4.1.x, как насчет использования нового 'sendAndReceive' на' JmsTemplate'? Going требует новых для немедленного отправки сообщения (если я понимаю ваш случай использования) - плохая идея. –

+0

1. Как я уже сказал: я использую JBoss 6.1.0-Final 2. sendAndReceive не работает в этом контексте. Последовательность событий следующая, когда вы попробуете: a. Начало транзакции b. Вы отправляете сообщение c. Вы ждете ответа (который никогда не приходит, потому что ...) d. время транзакции – Johan

+0

Сообщение отправляется только после совершения транзакции, поэтому, если вы хотите выполнить запрос-ответ, вам нужно отправить запрос в отдельной транзакции, прежде чем ждать ответа ... – Johan

ответ

3

Рад видеть, что i'am в одиночку не застрял в этом ligthless отверстие ...

Насколько я понял , глубокая причина этого предупреждения описывается here (конец нити)

when the outer transaction is suspended and the new inner transaction started, the managed connection that Jboss connection pool retrieves for the inner transaction is the same as that of the outer transaction, which is causing the IllegalStateException to get thrown!

и связано с особенностями поведения реализации контракта JBoss JCA (Lazy JCA enlistment).

A defect has been opened on spring side, помечены как "не исправит", но они обеспечивают конфигурацию обходной путь:

The typical solution is to use Spring's TransactionAwareDataSourceProxy and switch the "reobtainTransactionalConnections" flag to "true" there

получайте удовольствие!

+0

Спасибо! Это имеет большой смысл – Johan