Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IllegalStateException thrown by JBoss 4.0.3 when PROPAGATION_REQUIRES_NEW used during active transaction in MessageBean with BMT [SPR-1384] #6084

Closed
spring-issuemaster opened this Issue Oct 15, 2005 · 7 comments

Comments

Projects
None yet
2 participants
@spring-issuemaster
Copy link
Collaborator

spring-issuemaster commented Oct 15, 2005

Thomas Risberg opened SPR-1384 and commented

Deploy a MessageBean that is using BMT. The following sequence of events in the onMessage() method will cause the IllegalStateException:

  1. create TransactionTemplate with PROPAGATION_REQUIRED
  2. in the execute do this:
    2a. Connection conn = DataSourceUtils.getConnection(ds);
    2b. DataSourceUtils.releaseConnection(conn, ds);
    2c. call method that does the following:
    I. create TransactionTemplate with PROPAGATION_REQUIRES_NEW
    II. call execute and the exception is thrown.

Here is the debug and stacktrace:

12:03:50,703 INFO [STDOUT] MyMessageBean got message!
12:03:50,705 INFO [STDOUT] // obtain DataSource
12:03:50,707 INFO [STDOUT] *** Create TransactionManager
12:03:50,900 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Retrieving JTA UserTransaction from JNDI location [java:comp/UserTransaction]
12:03:50,901 DEBUG [org.springframework.jndi.JndiTemplate] Looking up JNDI object with name [java:comp/UserTransaction]
12:03:50,981 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Retrieving JTA TransactionManager from JNDI location [java:/TransactionManager]
12:03:50,983 DEBUG [org.springframework.jndi.JndiTemplate] Looking up JNDI object with name [java:/TransactionManager]
12:03:50,985 INFO [org.springframework.transaction.jta.JtaTransactionManager] Using JTA UserTransaction: org.jboss.ejb.EnterpriseContext$UserTransactionImpl@66d882
12:03:50,987 INFO [org.springframework.transaction.jta.JtaTransactionManager] Using JTA TransactionManager: org.jboss.tm.TxManager@104e65
12:03:50,988 INFO [STDOUT] *** Create TransactionTemplate
12:03:50,997 INFO [STDOUT] *** Propagation=0
12:03:51,005 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@401ab1]
12:03:51,007 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Creating new transaction with name [null]
12:03:51,017 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] Initializing transaction synchronization
12:03:51,026 INFO [STDOUT] *** doInTransaction org.springframework.transaction.support.DefaultTransactionStatus@bc60f2
12:03:51,056 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] Fetching JDBC Connection from DataSource
12:03:53,260 DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] Registering transaction synchronization for JDBC Connection
12:03:53,419 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] Bound value [org.springframework.jdbc.datasource.ConnectionHolder@2900c9] for key [org.jboss.resource.adapter.jdbc.WrapperDataSource@bf2c98] to thread [JMS SessionPool Worker-0]
12:03:53,420 INFO [STDOUT] *** doInConnection
12:03:53,420 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@2900c9] for key [org.jboss.resource.adapter.jdbc.WrapperDataSource@bf2c98] bound to thread [JMS SessionPool Worker-0]
12:03:53,421 INFO [STDOUT] === Create TransactionTemplate 2
12:03:53,422 INFO [STDOUT] === Propagation=3
12:03:53,424 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Using transaction object [org.springframework.transaction.jta.JtaTransactionObject@1548ee]
12:03:53,424 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Suspending current transaction, creating new transaction with name [null]
12:03:53,425 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] Removed value [org.springframework.jdbc.datasource.ConnectionHolder@2900c9] for key [org.jboss.resource.adapter.jdbc.WrapperDataSource@bf2c98] from thread [JMS SessionPool Worker-0]
12:03:53,433 DEBUG [org.springframework.transaction.support.TransactionSynchronizationManager] Clearing transaction synchronization
12:03:53,438 DEBUG [org.springframework.transaction.support.TransactionTemplate] Initiating transaction rollback on application exception
java.lang.IllegalStateException: Trying to change transaction TransactionImpl:XidImpl[FormatId=257, GlobalId=samoa.local/20, BranchQual=, localId=20] in enlist!
at org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener.enlist(TxConnectionManager.java:551)
at org.jboss.resource.connectionmanager.TxConnectionManager.transactionStarted(TxConnectionManager.java:357)
at org.jboss.resource.connectionmanager.CachedConnectionManager.userTransactionStarted(CachedConnectionManager.java:403)
at org.jboss.ejb.EnterpriseContext$UserTransactionImpl.begin(EnterpriseContext.java:576)
at org.springframework.transaction.jta.JtaTransactionManager.doJtaBegin(JtaTransactionManager.java:664)
at org.springframework.transaction.jta.JtaTransactionManager.doBegin(JtaTransactionManager.java:622)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction(AbstractPlatformTransactionManager.java:320)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:262)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:111)
at com.springdeveloper.ejb.MyMessageBean.testSpring2(MyMessageBean.java:95)
at com.springdeveloper.ejb.MyMessageBean.access$100(MyMessageBean.java:24)
at com.springdeveloper.ejb.MyMessageBean$1.doInTransactionWithoutResult(MyMessageBean.java:80)
at org.springframework.transaction.support.TransactionCallbackWithoutResult.doInTransaction(TransactionCallbackWithoutResult.java:33)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:114)
at com.springdeveloper.ejb.MyMessageBean.testSpring(MyMessageBean.java:71)
at com.springdeveloper.ejb.MyMessageBean.onMessage(MyMessageBean.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.invocation.Invocation.performCall(Invocation.java:345)
at org.jboss.ejb.MessageDrivenContainer$ContainerInterceptor.invoke(MessageDrivenContainer.java:475)
at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:149)
at org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:48)
at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:106)
at org.jboss.ejb.plugins.AbstractTxInterceptorBMT.invokeNext(AbstractTxInterceptorBMT.java:158)
at org.jboss.ejb.plugins.MessageDrivenTxInterceptorBMT.invoke(MessageDrivenTxInterceptorBMT.java:32)
at org.jboss.ejb.plugins.MessageDrivenInstanceInterceptor.invoke(MessageDrivenInstanceInterceptor.java:101)
at org.jboss.ejb.plugins.RunAsSecurityInterceptor.invoke(RunAsSecurityInterceptor.java:94)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:192)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.MessageDrivenContainer.internalInvoke(MessageDrivenContainer.java:389)
at org.jboss.ejb.Container.invoke(Container.java:873)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker.invoke(JMSContainerInvoker.java:1077)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker$MessageListenerImpl.onMessage(JMSContainerInvoker.java:1379)
at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:256)
at org.jboss.mq.SpyMessageConsumer.sessionConsumerProcessMessage(SpyMessageConsumer.java:904)
at org.jboss.mq.SpyMessageConsumer.addMessage(SpyMessageConsumer.java:160)
at org.jboss.mq.SpySession.run(SpySession.java:333)
at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:180)
at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
at java.lang.Thread.run(Thread.java:613)
12:03:53,447 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Triggering beforeCompletion synchronization
12:03:53,448 ERROR [org.springframework.transaction.support.TransactionTemplate] Application exception overridden by rollback exception
java.lang.IllegalStateException: Trying to change transaction TransactionImpl:XidImpl[FormatId=257, GlobalId=samoa.local/20, BranchQual=, localId=20] in enlist!
at org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener.enlist(TxConnectionManager.java:551)
at org.jboss.resource.connectionmanager.TxConnectionManager.transactionStarted(TxConnectionManager.java:357)
at org.jboss.resource.connectionmanager.CachedConnectionManager.userTransactionStarted(CachedConnectionManager.java:403)
at org.jboss.ejb.EnterpriseContext$UserTransactionImpl.begin(EnterpriseContext.java:576)
at org.springframework.transaction.jta.JtaTransactionManager.doJtaBegin(JtaTransactionManager.java:664)
at org.springframework.transaction.jta.JtaTransactionManager.doBegin(JtaTransactionManager.java:622)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.handleExistingTransaction(AbstractPlatformTransactionManager.java:320)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:262)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:111)
at com.springdeveloper.ejb.MyMessageBean.testSpring2(MyMessageBean.java:95)
at com.springdeveloper.ejb.MyMessageBean.access$100(MyMessageBean.java:24)
at com.springdeveloper.ejb.MyMessageBean$1.doInTransactionWithoutResult(MyMessageBean.java:80)
at org.springframework.transaction.support.TransactionCallbackWithoutResult.doInTransaction(TransactionCallbackWithoutResult.java:33)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:114)
at com.springdeveloper.ejb.MyMessageBean.testSpring(MyMessageBean.java:71)
at com.springdeveloper.ejb.MyMessageBean.onMessage(MyMessageBean.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.invocation.Invocation.performCall(Invocation.java:345)
at org.jboss.ejb.MessageDrivenContainer$ContainerInterceptor.invoke(MessageDrivenContainer.java:475)
at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:149)
at org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:48)
at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:106)
at org.jboss.ejb.plugins.AbstractTxInterceptorBMT.invokeNext(AbstractTxInterceptorBMT.java:158)
at org.jboss.ejb.plugins.MessageDrivenTxInterceptorBMT.invoke(MessageDrivenTxInterceptorBMT.java:32)
at org.jboss.ejb.plugins.MessageDrivenInstanceInterceptor.invoke(MessageDrivenInstanceInterceptor.java:101)
at org.jboss.ejb.plugins.RunAsSecurityInterceptor.invoke(RunAsSecurityInterceptor.java:94)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:192)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.MessageDrivenContainer.internalInvoke(MessageDrivenContainer.java:389)
at org.jboss.ejb.Container.invoke(Container.java:873)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker.invoke(JMSContainerInvoker.java:1077)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker$MessageListenerImpl.onMessage(JMSContainerInvoker.java:1379)
at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:256)
at org.jboss.mq.SpyMessageConsumer.sessionConsumerProcessMessage(SpyMessageConsumer.java:904)
at org.jboss.mq.SpyMessageConsumer.addMessage(SpyMessageConsumer.java:160)
at org.jboss.mq.SpySession.run(SpySession.java:333)
at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:180)
at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
at java.lang.Thread.run(Thread.java:613)
12:03:53,461 INFO [org.jboss.resource.connectionmanager.CachedConnectionManager] Closing a connection for you. Please close them yourself: org.jboss.resource.adapter.jdbc.WrappedConnection@d698d3
java.lang.Throwable: STACKTRACE
at org.jboss.resource.connectionmanager.CachedConnectionManager.registerConnection(CachedConnectionManager.java:333)
at org.jboss.resource.connectionmanager.BaseConnectionManager2.allocateConnection(BaseConnectionManager2.java:482)
at org.jboss.resource.connectionmanager.BaseConnectionManager2$ConnectionManagerProxy.allocateConnection(BaseConnectionManager2.java:894)
at org.jboss.resource.adapter.jdbc.WrapperDataSource.getConnection(WrapperDataSource.java:73)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:107)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at com.springdeveloper.ejb.MyMessageBean$1.doInTransactionWithoutResult(MyMessageBean.java:76)
at org.springframework.transaction.support.TransactionCallbackWithoutResult.doInTransaction(TransactionCallbackWithoutResult.java:33)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:114)
at com.springdeveloper.ejb.MyMessageBean.testSpring(MyMessageBean.java:71)
at com.springdeveloper.ejb.MyMessageBean.onMessage(MyMessageBean.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.jboss.invocation.Invocation.performCall(Invocation.java:345)
at org.jboss.ejb.MessageDrivenContainer$ContainerInterceptor.invoke(MessageDrivenContainer.java:475)
at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:149)
at org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:48)
at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:106)
at org.jboss.ejb.plugins.AbstractTxInterceptorBMT.invokeNext(AbstractTxInterceptorBMT.java:158)
at org.jboss.ejb.plugins.MessageDrivenTxInterceptorBMT.invoke(MessageDrivenTxInterceptorBMT.java:32)
at org.jboss.ejb.plugins.MessageDrivenInstanceInterceptor.invoke(MessageDrivenInstanceInterceptor.java:101)
at org.jboss.ejb.plugins.RunAsSecurityInterceptor.invoke(RunAsSecurityInterceptor.java:94)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:192)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.MessageDrivenContainer.internalInvoke(MessageDrivenContainer.java:389)
at org.jboss.ejb.Container.invoke(Container.java:873)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker.invoke(JMSContainerInvoker.java:1077)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker$MessageListenerImpl.onMessage(JMSContainerInvoker.java:1379)
at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:256)
at org.jboss.mq.SpyMessageConsumer.sessionConsumerProcessMessage(SpyMessageConsumer.java:904)
at org.jboss.mq.SpyMessageConsumer.addMessage(SpyMessageConsumer.java:160)
at org.jboss.mq.SpySession.run(SpySession.java:333)
at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:180)
at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
at java.lang.Thread.run(Thread.java:613)
12:03:53,473 ERROR [org.jboss.ejb.plugins.MessageDrivenTxInterceptorBMT] Application error: BMT stateless bean MyMessageBean should complete transactions before returning (ejb1.1 spec, 11.6.1)
12:03:53,478 ERROR [org.jboss.ejb.plugins.jms.JMSContainerInvoker] Exception in JMSCI message listener
javax.ejb.EJBException: null; CausedByException is:
Application error: BMT stateless bean MyMessageBean should complete transactions before returning (ejb1.1 spec, 11.6.1)
at org.jboss.ejb.plugins.LogInterceptor.handleException(LogInterceptor.java:411)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:196)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.MessageDrivenContainer.internalInvoke(MessageDrivenContainer.java:389)
at org.jboss.ejb.Container.invoke(Container.java:873)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker.invoke(JMSContainerInvoker.java:1077)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker$MessageListenerImpl.onMessage(JMSContainerInvoker.java:1379)
at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:256)
at org.jboss.mq.SpyMessageConsumer.sessionConsumerProcessMessage(SpyMessageConsumer.java:904)
at org.jboss.mq.SpyMessageConsumer.addMessage(SpyMessageConsumer.java:160)
at org.jboss.mq.SpySession.run(SpySession.java:333)
at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:180)
at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
at java.lang.Thread.run(Thread.java:613)
java.rmi.RemoteException: Application error: BMT stateless bean MyMessageBean should complete transactions before returning (ejb1.1 spec, 11.6.1)
at org.jboss.ejb.plugins.AbstractTxInterceptorBMT.checkStatelessDone(AbstractTxInterceptorBMT.java:225)
at org.jboss.ejb.plugins.AbstractTxInterceptorBMT.invokeNext(AbstractTxInterceptorBMT.java:165)
at org.jboss.ejb.plugins.MessageDrivenTxInterceptorBMT.invoke(MessageDrivenTxInterceptorBMT.java:32)
at org.jboss.ejb.plugins.MessageDrivenInstanceInterceptor.invoke(MessageDrivenInstanceInterceptor.java:101)
at org.jboss.ejb.plugins.RunAsSecurityInterceptor.invoke(RunAsSecurityInterceptor.java:94)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:192)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.MessageDrivenContainer.internalInvoke(MessageDrivenContainer.java:389)
at org.jboss.ejb.Container.invoke(Container.java:873)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker.invoke(JMSContainerInvoker.java:1077)
at org.jboss.ejb.plugins.jms.JMSContainerInvoker$MessageListenerImpl.onMessage(JMSContainerInvoker.java:1379)
at org.jboss.jms.asf.StdServerSession.onMessage(StdServerSession.java:256)
at org.jboss.mq.SpyMessageConsumer.sessionConsumerProcessMessage(SpyMessageConsumer.java:904)
at org.jboss.mq.SpyMessageConsumer.addMessage(SpyMessageConsumer.java:160)
at org.jboss.mq.SpySession.run(SpySession.java:333)
at org.jboss.jms.asf.StdServerSession.run(StdServerSession.java:180)
at EDU.oswego.cs.dl.util.concurrent.PooledExecutor$Worker.run(PooledExecutor.java:743)
at java.lang.Thread.run(Thread.java:613)


Affects: 1.2.5

Issue Links:

  • #9591 CLONE -IllegalStateException thrown by JBoss 4.0.5.11 when PROPAGATION_REQUIRES_NEW used during active transaction in MessageBean with BMT ("is duplicated by")
  • #8755 PROPAGATION_REQUIRES_NEW fails on JBoss 4.2.1 when using Hibernate connection release mode "on_close"
@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

spring-issuemaster commented Oct 15, 2005

Thomas Risberg commented

Here is the source for the MessageDrivenBean:

package com.springdeveloper.ejb;

import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import java.sql.Connection;

public class MyMessageBean implements MessageDrivenBean, MessageListener {

private MessageDrivenContext ctx = null;
private DataSource ds = null;

public MyMessageBean() {

}

//--- MessageDrivenBean
public void setMessageDrivenContext(MessageDrivenContext ctx)
        throws EJBException {

    this.ctx = ctx;

}

public void ejbCreate() {
}

public void ejbRemove() {
    ctx = null;
}

//--- MessageListener
public void onMessage(Message message) {

    System.err.println("MyMessageBean got message!");

    init();
    testSpring();

}

private void testSpring() {

    System.err.println("*** Create TransactionManager");
    final JtaTransactionManager transactionManager = new JtaTransactionManager();
    transactionManager.setTransactionManagerName("java:/TransactionManager");
    transactionManager.afterPropertiesSet();

    System.err.println("*** Create TransactionTemplate");
    TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
    transactionTemplate.setPropagationBehavior(TransactionDefinition.
            PROPAGATION_REQUIRED);
    transactionTemplate.afterPropertiesSet();
    System.err.println("*** Propagation=" + transactionTemplate.getPropagationBehavior());
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
        public void doInTransactionWithoutResult(TransactionStatus status) {
            System.err.println("*** doInTransaction " + status);
            // My code goes here
            Connection conn = DataSourceUtils.getConnection(ds);
            System.err.println("*** doInConnection");
            DataSourceUtils.releaseConnection(conn, ds);
            // do the second transactuion
            testSpring2(transactionManager);
        }
    });
    System.err.println("*** Done. ");

}

private void testSpring2(PlatformTransactionManager transactionManager) {

    System.err.println("=== Create TransactionTemplate 2");
    TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
    transactionTemplate.setPropagationBehavior(TransactionDefinition.
            PROPAGATION_REQUIRES_NEW);
    transactionTemplate.afterPropertiesSet();
    System.err.println("=== Propagation=" + transactionTemplate.getPropagationBehavior());
    transactionTemplate.execute(new TransactionCallbackWithoutResult() {
        public void doInTransactionWithoutResult(TransactionStatus status) {
            System.err.println("=== doInTransaction 2 " + status);
            // My code goes here
        }
    });

}

private void init() {
    InitialContext ctx;
    try {
        ctx = new InitialContext();

        System.err.println("// obtain DataSource");
        ds = getDataSource(ctx);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

private DataSource getDataSource(InitialContext ctx)
        throws Exception {
    try {
        // JBoss
        return (DataSource)
                ctx.lookup("java:/XAOracleDS");
    }
        catch (Exception e) {
            e.printStackTrace();
    }
    return null;
}

}

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

spring-issuemaster commented Oct 15, 2005

Juergen Hoeller commented

Interesting... seems that JBoss tries to enlist the Connection handle from the first transaction, which of course is already enlisted with the outer transaction.
Obviously JBoss didn't delist the Connection handle (which is still kept by Spring at that time) on suspend of the outer transaction, but tried to re-enlist it on begin of the inner transaction...

We recently had a report on something similar: http://opensource2.atlassian.com/projects/spring/browse/SPR-1206
JBoss has quite peculiar resource handling. It does not seem to delist active resources if a transaction gets suspended (which it arguably should, and which WebLogic does).
On the other hand, it seems to aggressively try to enlist existing Connection handles that it returned to the application, as per the given issue...

Thomas, could you please give this a try with Spring transaction synchronization turned off: that is, with JtaTransactionManager's "transactionSynchronization" property set to SYNCHRONIZATION_NEVER?
With synchronization off, Spring will return the Connection handle for the outer transaction eagerly, instead of keeping it until completion of the outer transaction.
I would expect the JBoss IllegalStateException to not occur anymore then.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

spring-issuemaster commented Oct 16, 2005

Thomas Risberg commented

You "guessed" right. I can reproduce this error by just holding on to an open connection even without using Spring's connection management. So the isssue is that JBoss does not allow you to suspend a transaction while you are holding on to a connection object.

Everything works fine by setting the "transactionSynchronization" property to SYNCHRONIZATION_NEVER. I assume that the appserver (JBoss) will synchronize connections/transactions but that there is no guarantee that I will use the same connection for all my work within a transaction. Any other drawbacks that this setting brings?

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

spring-issuemaster commented Oct 17, 2005

Juergen Hoeller commented

OK, so this is closely related to that previous JBoss issue. Thanks for confirming this.

The main problem here is that turning off transaction synchronization will even turn off Hibernate Session synchronization and co. Hence, the application would then solely rely on direct JTA synchronization, which will work for Hibernate - but only with proper JTA setup. Similarly for TopLink and JDO.

To keep transaction synchronization on, we could return the JDBC Connection on suspend and fetch a new one on resume. This would guarantee to use the same JDBC Connection for every phase of the transaction, but not guarantee that it's gonna be the same Connection before and after an inner transaction. This might be an acceptable tradeoff, and should work properly even on JBoss, as Spring wouldn't keep hold of an existing Connection handle during suspend anymore. Of course, that would only apply to synchronized Connections - that is, running within transactions driven by JtaTransactionManager -, not to Connections managed by our JDBC DataSourceTransactionManager, which absolutely needs to use the same Connections for every level of transaction.

To make the latter tradeoff work with Hibernate, the Hibernate connection release mode would have to be set to "after_statement", which they recommend for Hibernate3 in a JTA environment anyway. Else, the Hibernate Session would keep hold of an existing Connection handle even on suspend, incurring the original problem again...

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

spring-issuemaster commented Oct 19, 2005

Juergen Hoeller commented

I've addressed this as elaborated in my last comment. Our JTA synchronization will now release a JDBC Connection on suspend (provided that the application doesn't hold an open reference to it) and fetch the handle again after resume, if necessary. This should properly work on JBoss, even with transaction suspension.

Could you please give this a try, Thomas? It's already in CVS.

Juergen

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

spring-issuemaster commented Oct 20, 2005

Thomas Risberg commented

Are you sure it's in CVS - the only recent change (other than polishing) that I can see is "optimized to perform synchronization sort lazily (in "getSynchronizations")".

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

spring-issuemaster commented Oct 26, 2005

Thomas Risberg commented

This did fix it. I was able to verify that after this fix I don't get the IllegalStateExecption anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.