Announcement Announcement Module
Collapse
No announcement yet.
Infinite loop 4 transactions in a test with a jms:listener-container & task-executor Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Infinite loop 4 transactions in a test with a jms:listener-container & task-executor

    Hello,

    I have this listener container:

    Code:
        <jms:listener-container connection-factory="jmsConnectionFactory" task-executor="myTaskExecutor" transaction-manager="jmsTransactionManager">
        	<jms:listener id="myListenerContainer"			destination="${jms.my.queue}"		ref="myListenerContainerConsumer"	method="myMethod" />
        	<!-- 3 more -->
        </jms:listener-container>
    With:

    Code:
    	 	<task:executor id="myTaskExecutor" pool-size="8" queue-capacity="10" />
    Being:

    Code:
    	    <!-- Similar problem with <amq:connectionFactory brokerURL="vm://localhost" id="jmsFactory"/>  -->
    	    <amq:connectionFactory brokerURL="tcp://localhost:61616" id="jmsFactory"/>
    
    	    <bean class="org.springframework.jms.connection.CachingConnectionFactory" id="jmsConnectionFactory">
    	        <property name="targetConnectionFactory">
    	        	<ref bean="jmsFactory"/>
    	        </property>
    	    </bean>
    
    	    <bean id="jmsTransactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
    	    	<constructor-arg ref="jmsConnectionFactory" />
    	    </bean>
    In a JAR module that dependens on another JAR module created with Roo (Hibernate/Oracle) that has:

    Code:
    	<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManagerOracle">
    		<property name="entityManagerFactory" ref="emfOracle" />
    	</bean>
    	<tx:annotation-driven mode="aspectj" transaction-manager="transactionManagerOracle" />
    When I execute this test:

    Code:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath*:META-INF/spring/applicationContext*.xml")
    @TransactionConfiguration(transactionManager="transactionManagerOracle", defaultRollback=true)
    @Transactional
    public class MyTest {
    
    	@Test
    	public void myTest() throws Exception {
    Each of the four DefaultMessageListenerContainer gets assigned the taskExecutor (a ThreadPoolTaskExecutor) and the transactionManager (the JmsTransactionManager) when the application is loaded.

    Then, the RunBeforeTestMethodCallbacks evaluates, that is, the TestContextManager executes the beforeTestMethod that gets a Transaction (via TransactionalTestExecutionListener)

    So the main thread calls the JpaTransactionManager (doBegin in getTransaction, that Exposes "JPA transaction as JDBC transaction")

    But...

    The DefaultMessageListenerContainer calls the AsyncMessageListenerInvoker's run method once per thread corresponding to the ThreadPoolTaskExecutor that it has.

    As a result, each thread calls the receiveAndExecute that also tries to get a Transaction using the JmsTransactionManager (doBegin in getTransaction, that Exposes "JPA transaction as JDBC transaction"):

    [ActiveMQ Transport: tcp://localhost/127.0.0.1:61616@57985][org.apache.activemq.transport.WireFormatNegotiator] Received WireFormat: WireFormatInfo { version=9, properties={CacheSize=1024, MaxFrameSize=9223372036854775807, CacheEnabled=true, SizePrefixDisabled=false, TcpNoDelayEnabled=true, MaxInactivityDurationInitalDelay=10000, MaxInactivityDuration=30000, TightEncodingEnabled=true, StackTraceEnabled=true}, magic=[A,c,t,i,v,e,M,Q]}
    [myTaskExecutor-4][org.apache.activemq.transport.WireFormatNegotiator] Sending: WireFormatInfo { version=9, properties={MaxFrameSize=9223372036854775807, CacheSize=1024, CacheEnabled=true, SizePrefixDisabled=false, MaxInactivityDurationInitalDelay=10000, TcpNoDelayEnabled=true, MaxInactivityDuration=30000, TightEncodingEnabled=true, StackTraceEnabled=true}, magic=[A,c,t,i,v,e,M,Q]}
    [myTaskExecutor-4][org.apache.activemq.transport.InactivityMonitor] Using min of local: WireFormatInfo { version=9, properties={MaxFrameSize=9223372036854775807, CacheSize=1024, CacheEnabled=true, SizePrefixDisabled=false, MaxInactivityDurationInitalDelay=10000, TcpNoDelayEnabled=true, MaxInactivityDuration=30000, TightEncodingEnabled=true, StackTraceEnabled=true}, magic=[A,c,t,i,v,e,M,Q]} and remote: WireFormatInfo { version=9, properties={CacheSize=1024, MaxFrameSize=9223372036854775807, CacheEnabled=true, SizePrefixDisabled=false, TcpNoDelayEnabled=true, MaxInactivityDurationInitalDelay=10000, MaxInactivityDuration=30000, TightEncodingEnabled=true, StackTraceEnabled=true}, magic=[A,c,t,i,v,e,M,Q]}
    [ActiveMQ Transport: tcp://localhost/127.0.0.1:61616@57985][org.apache.activemq.transport.WireFormatNegotiator] tcp://localhost/127.0.0.1:61616@57985 before negotiation: OpenWireFormat{version=9, cacheEnabled=false, stackTraceEnabled=false, tightEncodingEnabled=false, sizePrefixDisabled=false, maxFrameSize=9223372036854775807}
    [ActiveMQ Transport: tcp://localhost/127.0.0.1:61616@57985][org.apache.activemq.transport.WireFormatNegotiator] tcp://localhost/127.0.0.1:61616@57985 after negotiation: OpenWireFormat{version=9, cacheEnabled=true, stackTraceEnabled=true, tightEncodingEnabled=true, sizePrefixDisabled=false, maxFrameSize=9223372036854775807}
    [myTaskExecutor-4][org.springframework.jms.connection.CachingConnecti onFactory] Established shared JMS Connection: ActiveMQConnection {id=ID:XXXX-XY-57984-1366202377216-1:1,clientId=null,started=false}
    [myTaskExecutor-4][org.springframework.jms.connection.CachingConnecti onFactory] Creating cached JMS Session for mode 0: ActiveMQSession {id=ID:XXXX-XY-57984-1366202377216-1:1:1,started=false}
    [myTaskExecutor-4][org.springframework.jms.connection.JmsTransactionM anager] Created JMS transaction on Session [Cached JMS Session: ActiveMQSession {id=ID:XXXX-XY-57984-1366202377216-1:1:1,started=false}] from Connection [Shared JMS Connection: ActiveMQConnection {id=ID:XXXX-XY-57984-1366202377216-1:1,clientId=ID:XXXX-XY-57984-1366202377216-0:1,started=false}]
    The code seems to stay in an infinite loop trying to listen to incoming messages, what I really don't care, but it seems a little bit weird.

    [myTaskExecutor-2][org.springframework.jms.connection.JmsTransactionM anager] Initiating transaction commit
    [myTaskExecutor-2][org.springframework.jms.connection.JmsTransactionM anager] Committing JMS transaction on Session [Cached JMS Session: ActiveMQSession {id=ID:XXXX-XY-57984-1366202377216-1:1:2,started=true}]
    [myTaskExecutor-2][org.apache.activemq.ActiveMQSession] ID:XXXX-XY-57984-1366202377216-1:1:2 Transaction Commit :null
    [myTaskExecutor-2][org.springframework.jms.connection.JmsTransactionM anager] Creating new transaction with name [respuestaListenerContainer]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
    [myTaskExecutor-2][org.springframework.jms.connection.JmsTransactionM anager] Created JMS transaction on Session [Cached JMS Session: ActiveMQSession {id=ID:XXXX-XY-57984-1366202377216-1:1:2,started=true}] from Connection [Shared JMS Connection: ActiveMQConnection {id=ID:XXXX-XY-57984-1366202377216-1:1,clientId=ID:XXXX-XY-57984-1366202377216-0:1,started=true}]
    Besides, the test suite is no working due to transaction errors (for instance, org.springframework.transaction.TransactionSystemE xception: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly)

    ...Can anyone tell me if I'm doing something wrong?
Working...
X