Issue Details (XML | Word | Printable)

Key: SPR-1384
Type: Bug Bug
Status: Resolved Resolved
Resolution: Fixed
Priority: Major Major
Assignee: Juergen Hoeller
Reporter: Thomas Risberg
Votes: 0
Watchers: 0
Operations

If you were logged in you would be able to see more operations.
Spring Framework

IllegalStateException thrown by JBoss 4.0.3 when PROPAGATION_REQUIRES_NEW used during active transaction in MessageBean with BMT

Created: 15/Oct/05 11:16 AM   Updated: 13/Jun/08 02:37 AM
Component/s: SpringTX
Affects Version/s: 1.2.5
Fix Version/s: 1.2.6

Time Tracking:
Not Specified

Environment: JBoss 4.0.3 and Spring 1.2.5 and current CVS
Issue Links:
Duplicate
 
Related
 

Platform: JBoss - 4.0


 Description  « Hide
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)




 All   Comments   Work Log   Change History   FishEye   Related Builds      Sort Order: Ascending order - Click to sort in descending order
Thomas Risberg added a comment - 15/Oct/05 12:29 PM
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;
    }
}

Juergen Hoeller added a comment - 16/Oct/05 05:39 AM
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

Thomas Risberg added a comment - 16/Oct/05 11:05 AM
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?

Juergen Hoeller added a comment - 17/Oct/05 12:31 PM
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

Juergen Hoeller added a comment - 19/Oct/05 08:59 AM
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

Thomas Risberg added a comment - 20/Oct/05 08:22 PM
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")".

Thomas Risberg added a comment - 26/Oct/05 07:58 PM
This did fix it. I was able to verify that after this fix I don't get the IllegalStateExecption anymore.