The problem is in Jencks code, which PooledSpringXAConnectionFactory can't work in multithreaded environment. I tried to run this simple context:
Code:
<beans>
<bean id="broker" class="org.apache.activemq.broker.BrokerService" init-method="start" destroy-method="stop">
<property name="persistent" value="false"/>
<property name="transportConnectorURIs">
<list>
<value>tcp://localhost:5000</value>
</list>
</property>
</bean>
<bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
<bean id="jotmTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="jotm"/>
</bean>
<bean id="connectionFactory" class="org.jencks.pool.PooledSpringXAConnectionFactory">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://localhost:5000" />
</bean>
</property>
<property name="transactionManager" ref="jotm"/>
</bean>
<bean id="messageReceiver" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="jotmTransactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
<property name="target">
<bean class="simple.MessageReceiver">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
</property>
<property name="proxyTargetClass" value="true"/>
</bean>
</beans>
with this code:
Code:
public class MessageReceiver {
private Log log = LogFactory.getLog(getClass());
private ConnectionFactory connectionFactory;
public void setConnectionFactory(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
public void receive() {
Thread readerThread = new Thread(new Runnable(){
public void run() {
try {
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("messages.input");
MessageConsumer consumer = session.createConsumer(destination);
log.debug("receive message ...");
while (true) {
Message message = consumer.receive(Long.MAX_VALUE);
log.debug("received message : "+message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
readerThread.start();
}
}
and got:
Code:
INFO BrokerService - ActiveMQ null JMS Message Broker (localhost) is starting
INFO BrokerService - For help or more information please see: http://incubator.apache.org/activemq/
INFO TransportServerThreadSupport - Listening for connections at: tcp://prokopiev.stc.donpac.ru:5000
INFO TransportConnector - Connector tcp://prokopiev.stc.donpac.ru:5000 Started
INFO BrokerService - ActiveMQ JMS Message Broker (localhost, ID:prokopiev.stc.donpac.ru-38166-1155892764301-0:0) started
INFO jotm - JOTM started with a local transaction factory which is not bound.
INFO jotm - CAROL initialization
INFO ConfigurationRepository - No protocols were defined for property 'carol.protocols', trying with default protocol = 'jrmp'.
INFO jta - JOTM 2.0.10
INFO JtaTransactionManager - Using JTA UserTransaction: org.objectweb.jotm.Current@19836ed
INFO JtaTransactionManager - Using JTA TransactionManager: org.objectweb.jotm.Current@19836ed
INFO ManagementContext - JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
INFO DefaultAopProxyFactory - CGLIB2 available: proxyTargetClass feature enabled
DEBUG MessageReceiver - receive message ...
DEBUG PooledSpringXAConnection - -->> ENTERING PooledSpringXAConnection.createXASession()
DEBUG PooledSpringXAConnection - -->> THERE IS NO ACTIVE TRANSACTION, SO JUST RETURNING BORROWED SESSION...
DEBUG XASessionPool - ---->>>>> BORROWING JMS SESSION FROM POOL...
DEBUG XASessionPool - ---->>>>> CREATING NEW SESSION TO SATISFY REQUEST!!
DEBUG XASessionPool - ---->>>>> BORROWED SESSION: org.jencks.pool.PooledSpringXASession@4c47db
javax.jms.JMSException: Session's XAResource has not been enlisted in a distributed transaction.
at org.apache.activemq.ActiveMQXASession.doStartTransaction(ActiveMQXASession.java:109)
at org.apache.activemq.ActiveMQMessageConsumer.ackLater(ActiveMQMessageConsumer.java:658)
at org.apache.activemq.ActiveMQMessageConsumer.beforeMessageIsConsumed(ActiveMQMessageConsumer.java:610)
at org.apache.activemq.ActiveMQMessageConsumer.receive(ActiveMQMessageConsumer.java:469)
at simple.MessageReceiver$1.run(MessageReceiver.java:35)
at java.lang.Thread.run(Thread.java:595)
After extracting JMS code from separate thread I got:
Code:
INFO BrokerService - ActiveMQ null JMS Message Broker (localhost) is starting
INFO BrokerService - For help or more information please see: http://incubator.apache.org/activemq/
INFO TransportServerThreadSupport - Listening for connections at: tcp://prokopiev.stc.donpac.ru:5000
INFO TransportConnector - Connector tcp://prokopiev.stc.donpac.ru:5000 Started
INFO BrokerService - ActiveMQ JMS Message Broker (localhost, ID:prokopiev.stc.donpac.ru-38153-1155892708903-0:0) started
INFO jotm - JOTM started with a local transaction factory which is not bound.
INFO jotm - CAROL initialization
INFO ConfigurationRepository - No protocols were defined for property 'carol.protocols', trying with default protocol = 'jrmp'.
INFO jta - JOTM 2.0.10
INFO JtaTransactionManager - Using JTA UserTransaction: org.objectweb.jotm.Current@949f69
INFO JtaTransactionManager - Using JTA TransactionManager: org.objectweb.jotm.Current@949f69
INFO ManagementContext - JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi
INFO DefaultAopProxyFactory - CGLIB2 available: proxyTargetClass feature enabled
DEBUG MessageReceiver - receive message ...
DEBUG PooledSpringXAConnection - -->> ENTERING PooledSpringXAConnection.createXASession()
DEBUG PooledSpringXAConnection - -->> ACTUAL TRANSACTION IS ACTIVE!
DEBUG PooledSpringXAConnection - -->> NO ACTIVE SESSION ASSOCIATED WITH CURRENT THREAD, BORROWING...
DEBUG XASessionPool - ---->>>>> BORROWING JMS SESSION FROM POOL...
DEBUG XASessionPool - ---->>>>> CREATING NEW SESSION TO SATISFY REQUEST!!
DEBUG XASessionPool - ---->>>>> BORROWED SESSION: org.jencks.pool.PooledSpringXASession@1402d5a
DEBUG PooledSpringXAConnection - -->> ENLISTING NEW SESSION'S XAResource WITH TRANSACTION...
DEBUG PooledSpringXAConnection - -->> BINDING NEW SESSION WITH TRANSACTION...
DEBUG PooledSpringXAConnection - -->> REGISTERING SYNCHRONIZATION WITH TRANSACTION...
DEBUG MessageReceiver - received message : ActiveMQObjectMessage {commandId = 5, responseRequired = true, messageId = ID:prokopiev.stc.donpac.ru-38161-1155892719980-0:0:1:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:prokopiev.stc.donpac.ru-38161-1155892719980-0:0:1:1, destination = queue://messages.input, transactionId = null, expiration = 0, timestamp = 1155892720450, arrival = 0, correlationId = null, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activeio.packet.ByteSequence@b40ec4, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = true, readOnlyBody = true}
So, in single thread all works fine.
Can I enlist my XAResource (JMS Session) in distributed transaction by hand? Can anybody give me a simple example of this?