Atomikos Forum |
|
Hi Guys,
We are using Atomikos 3.6 as with Spring 2 and JPA (Hibernate 3.3). We have an interface with other systems where via IBM MQ 5. There are some memory issues with our application and sometimes need to restart our Tomcat. When the server does not respond to the stop command we do a force stop. If a message is received during that time, the message is lost and it is not saved in the database either. As far as I understand, the transaction manager commits both at the database level and MQ level or rolls back. Then in this case, the messages should not have been committed at the MQ level and must be available when the server starts up. Is there something that I missed in my understanding or configuration ? Thanks, Midhun
Hi Midhun,
the JMS transaction configuration for Spring has some challenges. It is easily possible start in transaction mode but reading the queue is auto committed. This would lead to your problem with missing messages and produce memory leaks. This memory leak can be checked with jmap/jhat from jdk. If you spot lots of MQQueueReceiver/Sender and Atomikos classes, your configuration needs to be improved. But without your Spring xml files I can only guess. Regards, Rainer
Hi Rainer,
Thank you for the response. I checked the Spring documentation which says that we need to configure a JtaTransactionManager for XA Transactions. Our configuration has been setup for XA transactions. The configurations are as below : Spring Listner : <!-- Abstract Message Listener Container --> <bean id="abstractMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer" abstract="true"> <property name="connectionFactory" ref="jmsConnectionFactory" /> <property name="transactionManager" ref="transactionManager" /> <property name="sessionTransacted" value="true" /> </bean> <bean id="InQueueMessageListenerContainer" parent="abstractMessageListenerContainer"> <property name="destination" ref="InQueue" /> <property name="messageListener"> <bean class="org.springframework.jms.listener.adapter.MessageListenerAdapter"> <constructor-arg index="0"> <bean class="com.xxxxxx.cccccc.vvvvvv.tttttt.ffffff.jjjjjj.impl.QueueProcessor" /> </constructor-arg> </bean> </property> </bean> JMS Connection Factory : <bean id="jmsConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter" depends-on="sysPropsLoader"> <property name="targetConnectionFactory"> <bean class="com.atomikos.jms.QueueConnectionFactoryBean" init-method="init"> <property name="xaQueueConnectionFactory"> <bean class="com.ibm.mq.jms.MQXAQueueConnectionFactory"> <property name="transportType" value="${jms.transportType}" /> <property name="hostName" value="${jms.hostName}" /> <property name="port" value="${jms.port}" /> <property name="channel" value="${jms.channel}" /> <property name="SSLCipherSuite" value="${jms.ssl.cipherSuite}" /> </bean> </property> <property name="resourceName" value="${jms.queue.manager}_MQSeries_XA_RMI" /> </bean> </property> <property name="username" value=" " /> <property name="password" value=" " /> </bean> Transaction Manager Config : <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <property name="forceShutdown" value="true" /> </bean> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> <property name="transactionTimeout" value="${transaction.timeout}" /> </bean> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager" ref="atomikosTransactionManager" /> <property name="userTransaction" ref="atomikosUserTransaction" /> </bean> Thanks, Midhun
Hi Midhun,
the Spring documentation refers to a J2EE environment. But Spring/Tomcat/Atomikos is no J2EE environment. Therefore you have to add properties to the spring configuration to get the expected workflow. I your case sessionAcknoledgeMode has to be added to prevent auto commit on read which is the default setting of Spring. <bean id="abstractMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer" abstract="true"> <property name="connectionFactory" ref="jmsConnectionFactory" /> <property name="transactionManager" ref="transactionManager" /> <property name="sessionTransacted" value="true" /> <property name="sessionAcknowledgeMode" value="0" /> </bean>
Hi Rainer,
Thank you. I read about sessionAcknowledgeMode and I think a value of 2 (CLIENT_ACKNOWLEDGE) is what I am looking for. References : http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/jms/listener/AbstractMessageListenerContainer.html http://docs.oracle.com/javaee/1.4/api/constant-values.html#javax.jms.Session.CLIENT_ACKNOWLEDGE Let me know if I am on the wrong track. Thanks, Midhun
Hi Midhun,
sessionAcknowledgeMode should only be set if you do not use transactions. So you should set either sessionAcknowledgeMode or sessionTransacted as stated by Spring's documentation. A "hack" is needed in your environment to work. sessionTransacted has to be set to true AND sessionAcknowledgeMode to 0. A have not compared Spring and Atomikos to the spec's. Therefore I can not say if it is a bug or a feature. But this hack works for me with MQSeries or ActiveMQ as JMS provider. Cheers, Rainer |