Announcement Announcement Module
Collapse
No announcement yet.
DefaultMessageListenerContainer, CachingConnectionFactory tomcat and WebSphere MQ Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • DefaultMessageListenerContainer, CachingConnectionFactory tomcat and WebSphere MQ

    Hi,
    let me depict the scenario I am using.

    I configure a DMLC based on a CachingConnectionFactory referencing an WebSphere MQ Connectionfactory. I am using 2.5.6 spring version.
    The WebSphere MQ runs on a separate machine.

    I want to test the following scenario:
    I start my Web application, the DMLC connects to MQ and waits for incoming messages.
    I disconnect my network cable in order to simulate a network error, I wait till the spring framework indicates the network error.

    Now I connect the network cable and wait for spring to re-establish the connection - but this does not happen ???

    Spring continuously tries to re-establish the connection at my big surprise.

    So I decided tu debug cod to find out what is happening and here are the results of my investigation:
    according to JMS 1.1 specification 4.3.8 Exception Listener:
    The exceptions delivered to ExceptionListener are those that have no other place to be reported. If an exception is thrown on a JMS call it, by definition, must not be delivered to an ExceptionListener (in other words, ExceptionLsener is not for the purpose of monitoring all exceptions thrown by a connection).
    , this fact is also explained in IBM http://www-01.ibm.com/support/docvie...id=swg21314744.

    In fact the CachingConnectionFactory registers an exceptionlistener that is never called so the cleanup method resetConnection() is never called.
    The DMLC receiving loop catches the exception and invokes method clearResources.
    But here again the clearResources may be called in two different contexts:
    the nominal context when the receiving loop ends
    the exception context when the receiving loop catches an exception
    The problem is that the code of clearResources does not take into account the fact the cleaning is required because of an exception, in that case it makes more sense to talk of invalidating resources.
    The implementation of method clearResources tries to close the messageconsumer and the JMS session but since a CachingConnectionFactory is in use only a logicalClose of the session is performed so the bogus session is put back in the cache and will be reused later.

    After searching for a while, the only workaround I found is to inject an ExceptionListener to the DMLC, inject the CachingConnectionFactory to the ExceptionListener and implement my ExceptionListener like this:
    Code:
    import javax.jms.ExceptionListener;
    import javax.jms.JMSException;
    
    import org.springframework.jms.connection.CachingConnectionFactory;
    
    public class MyExceptionListener implements ExceptionListener {
    	CachingConnectionFactory cachingConnectionFactory;
    	
    	public void onException(JMSException arg0) {
    		System.err.println("Exception occurred "+arg0);
    		cachingConnectionFactory.onException(arg0);
    	}
    
    	public CachingConnectionFactory getCachingConnectionFactory() {
    		return cachingConnectionFactory;
    	}
    
    	public void setCachingConnectionFactory(CachingConnectionFactory cachingConnectionFactory) {
    		this.cachingConnectionFactory = cachingConnectionFactory;
    	}
    
    }
    So just to summarize the situation, the CachingConnectionFactory registers an ExceptionListener that is never called, the exception being caught by the receiving loop from DMLC.


    Maybe there is another way to fix the problem, your ideas are welcome, here is my configuration:
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ws="http://jax-ws.dev.java.net/spring/core"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans
    	http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
    
    	<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
    		<property name="environment">
    			<props>
    				<prop key="java.naming.factory.initial">
    					com.sun.jndi.fscontext.RefFSContextFactory
    				</prop>
    				<prop key="java.naming.provider.url">
    					file:MYLOCATION
    				</prop>
    			</props>
    		</property>
    	</bean>
    
    
    	<!--  -->
    	<bean id="queue" class="org.springframework.jndi.JndiObjectFactoryBean">
    		<property name="jndiName" value="jms/myqueue" />
    		<property name="jndiTemplate" ref="jndiTemplate" />
    	</bean>
    	<bean id="qcf" class="org.springframework.jndi.JndiObjectFactoryBean">
    		<property name="jndiName" value="jms/myqcf" />
    		<property name="jndiTemplate" ref="jndiTemplate" />
    	</bean>
    	<!-- Use a cache for connectionfactory -->
    	<bean id="cachingConnectionFactory"
    		class="org.springframework.jms.connection.CachingConnectionFactory">
    		<property name="targetConnectionFactory" ref="qcf" />
    
    	</bean>
    
    	<!-- Listener for  messages -->
    	<bean
    		class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    		<property name="connectionFactory" ref="cachingConnectionFactory" />
    		<property name="destination" ref="queue" />
    		<property name="messageListener" ref="messageListener" />
    		<property name="exceptionListener" ref="exceptionListener" />
    	</bean>
    
    	<bean id="messageListener" class="com.test.MyMessageListener">
    	</bean>
    
    	<bean id="exceptionListener" class="com.test.MyExceptionListener">
    		<property name="cachingConnectionFactory" ref="cachingConnectionFactory"></property>
    	</bean>
    
    
    </beans>
    Thanks for your attention,
    Franck

  • #2
    DMLC recovery not working

    Hi,

    I am trying to simulate a failover scenario, by disconnecting the cable and connecting it in a similar fashion you mentioned above. Within my MessageListener code I put the thread to sleep for 30 seconds (sufficient to disconnect the cable and reconnect it). In the DMLC I set recoveryInterval=60000. But recovery doesn't seem to occur.

    My Spring config goes like this.

    Code:
        <bean id="com.ibm.mq.jms.JMSC.MQJMS_TP_CLIENT_MQ_TCPIP" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
    
        <bean id="mqQueueConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
            <property name="transportType" ref="com.ibm.mq.jms.JMSC.MQJMS_TP_CLIENT_MQ_TCPIP"/>
            <property name="queueManager" value="SX2"/>
            <property name="hostName" value="10.1.6.189"/>
            <property name="channel" value="SX2CHL"/>
            <property name="port" value="1417"/>
        </bean>
    
        <bean id="jmsConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
            <property name="targetConnectionFactory" ref="mqQueueConnectionFactory"/>
            <property name="username" value="MUSR_MQADMIN"/>
            <property name="password" value=""/>
        </bean>
    
        <bean id="failoverExceptionListener" class="com.nri.sx.core.console.service.FailoverExceptionListener" />
    
        <bean id="cachingConnectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
            <property name="targetConnectionFactory" ref="jmsConnectionFactory" />
            <property name="sessionCacheSize" value="10" />
            <property name="reconnectOnException" value="true" />
            <!--<property name="exceptionListener" ref="failoverExceptionListener" />-->
        </bean>
    
        <bean id="connectionFactory" class="org.springframework.jms.connection.TransactionAwareConnectionFactoryProxy">
            <property name="targetConnectionFactory" ref="cachingConnectionFactory"/>
            <property name="synchedLocalTransactionAllowed" value="true"/>
        </bean>
    
        <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
            <property name="connectionFactory" ref="connectionFactory"/>
            <property name="receiveTimeout" value="100"/>
            <property name="sessionTransacted" value="true"/>
        </bean>
    
        <bean id="com.ibm.mq.jms.JMSC.MQJMS_CLIENT_JMS_COMPLIANT" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
        <bean id="com.ibm.mq.jms.JMSC.MQJMS_PRI_APP" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
        <bean id="com.ibm.mq.jms.JMSC.MQJMS_PER_QDEF" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
    
    
        <bean id="inQueue" class="com.ibm.mq.jms.MQQueue">
            <property name="baseQueueManagerName" value="SX"/>
            <property name="baseQueueName" value="BBH2XENOSIN"/>
            <property name="targetClient" value="0"/>
            <property name="priority" value="-2"/>
            <property name="persistence" value="-1"/>
        </bean>
    
        <bean id="messageListener" class="com.nri.sx.core.console.service.GatewayMessageListener">
            <property name="jmsTemplate" ref="jmsTemplate" />
        </bean>
    
        <bean id="transactionManager" class="org.springframework.jms.connection.JmsTransactionManager">
            <property name="connectionFactory" ref="connectionFactory" />
        </bean>
    
        <bean id="exceptionListener" class="com.nri.sx.core.console.service.DelegatingExceptionListener">
            <property name="cachingConnectionFactory" ref="cachingConnectionFactory" />
        </bean>
    
        <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="connectionFactory" />
            <property name="sessionTransacted" value="true" />
            <property name="transactionManager" ref="transactionManager" />
            <property name="destination" ref="inQueue" />
            <property name="messageListener" ref="messageListener" />
            <property name="exceptionListener" ref="exceptionListener" />
            <property name="concurrentConsumers" value="${jms.receive.maxConsumers}" />
            <property name="recoveryInterval" value="60000" />
        </bean>
    Any help/idea would be appreciated.

    Regards,
    Kalyan Sarkar

    Comment


    • #3
      Struggling to reconnect DMLC with JMS provider

      I am working on a similar problem where ActiveMQ goes down and all queues with it. When ActiveMQ comes back again, I am still thinking for a right approach to reregister all DMLCs with activeMq.

      Recovery is an option but is that going to register DMLC with activemq again?

      Still researching this topic.

      Comment


      • #4
        Hi Franck,

        There's actually no reason to implement a custom JMS ExceptionListener. CachingConnectionFactory already implements the JMS ExceptionListener interface, and CachingConnectionFactory's onException() method will internally reset the connection (i.e., clear the cache). So all you need to do is configure the CachingConnectionFactory as both the connectionFactory and the exceptionListener properties of the DefaultMessageListenerContainer. The configuration looks odd, but it works without any custom code:

        Code:
        <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        	<property name="connectionFactory" ref="cachingConnectionFactory" />
        	<property name="exceptionListener" ref="cachingConnectionFactory" />
        	<property name="destinationName" value="my.queue.name" />
        	<property name="messageListener" ref="myMessageListener" />
        </bean>
        Note, however, that the exceptionListener property is unfortunately not exposed as an attribute via Spring's <jms:listener-container> XML namespace. So if you run into this issue, you will have to define your DefaultMessageListenerContainer bean explicitly.

        Regards,

        Sam
        Last edited by Sam Brannen; Aug 14th, 2011, 06:02 PM.

        Comment

        Working...
        X