Announcement Announcement Module
Collapse
No announcement yet.
Tomcat Hangs on Shutdown after subscribing to ActiveMQ topic from Flex client Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Tomcat Hangs on Shutdown after subscribing to ActiveMQ topic from Flex client

    My Problem

    After running my Flex client application that subscribes to a JMS topic, Tomcat hangs on shutdown. The DefaultMessageListenerContainer-1 thread continues to run (it is not a daemon thread). The applicationContext does get closed, but for some reason this thread lives on. Subsequently killing the aforementioned thread allows the JavaVM to die and Tomcat then stops.

    My Environment

    Java JDK 1.6.0_12
    Tomcat 6.0.20
    ActiveMQ 5.3.0
    Spring 2.5.6
    Spring-Flex 1.0.1
    BlazeDS 3.2
    Flex SDK 3.4
    Adobe Flex Builder 3
    Eclipse 3.4.2

    Client ActionScript

    MyAppJmsClient.initialize() is called from the Application creationComplete. Basically, this subscribes to one topic per client instance. It also kindly unsubscribes after the client disconnects.

    Code:
    	public class MyAppJmsClient {
    		private static const CHANNELSET_ID:String = "my-streaming-amf";
    		private static const CHANNELSET_URI:String = "/MyApp/messagebroker/amfstreaming";
    		private static const CONSUMER_ID:String = "MyAppBuilder";
    		private static const JMS_DEST:String = "MyAppBuilderDestination";
    		
    		private static var log:ILogger = Log.getLogger("com.eri.MyApp.flex.sampleplan.util.MyAppJmsClient");
    		
    		private var channelSet:ChannelSet;
    		private var consumer:Consumer;
    
    		/**
    		 * Default constructor
    		 */		
    		public function MyAppJmsClient() {
    			// empty constructor
    		}
    
    		/**
    		 * Registers application as JMS client
    		 */
    		public function initialize():void {
    		    trace("JmsClient:registerClient");
    			this.initializeChannelSet();
    			this.initializeConsumer();
    			this.subscribe();
    		}
    	
    		private function initializeChannelSet():void {
    			if (!this.channelSet) {
    				this.channelSet = new ChannelSet();
    				this.channelSet.addEventListener(ChannelEvent.CONNECT, handleChannelConnect);
    				this.channelSet.addEventListener(ChannelFaultEvent.FAULT, handleChannelFault);
    				this.channelSet.addEventListener(ChannelEvent.DISCONNECT, handleChannelDisconnect);
    				this.channelSet.addChannel(new StreamingAMFChannel(CHANNELSET_ID, CHANNELSET_URI));
    			}
    		}
    		
    		private function initializeConsumer():void {
    			if (!this.consumer) {
    				this.consumer = new Consumer();
    				this.consumer.id = CONSUMER_ID;
    				this.consumer.destination = JMS_DEST;
    				this.consumer.resubscribeAttempts = -1;		// keep trying
    				this.consumer.resubscribeInterval = 5000;	// every 5 sec.
    				this.consumer.channelSet = this.channelSet;
    				this.consumer.addEventListener(MessageFaultEvent.FAULT, handleMessageFault);
    				this.consumer.addEventListener(MessageEvent.MESSAGE, messageHandler);
    			}
    		}
    		
    		private function subscribe():void {
    			if (!this.consumer.subscribed) {
    				this.consumer.subscribe();
    			}
    		}
    		
    		private function handleChannelConnect(event:ChannelEvent):void {
    		    trace(event.toString());
    		    if (event.reconnecting) {
    		    	this.subscribe();
    		    }
    		}
    		
    		private function handleChannelDisconnect(event:ChannelEvent):void {
    		    trace(event.toString());
    		}
    		
    		private function messageHandler(event:MessageEvent):void {
    			// TODO
    		    trace(event.toString());
    		}
    
            private function handleMessageFault(event:MessageFaultEvent):void {
            	try {log.error(event.message.toString());} finally {}
            }
    
            private function handleChannelFault(event:ChannelFaultEvent):void {
            	try {log.error(event.toString());} finally {}
            }
    	}
    applicationContext.xml

    Code:
    	<flex:message-broker>
    		<flex:message-service
    			default-channels="my-polling-amf,my-longpolling-amf,my-streaming-amf" />
    		<!-- We are not currently using flex session -->
    		<!--
    			<flex:secured access-decision-manager="accessDecisionManager"
    			per-client-authentication="true" />
    		-->
    	</flex:message-broker>
    	<!--
    		flex:message-broker needs SimpleControllerHandlerAdapter to prevent
    		startup error.
    	-->
    	<bean
    		class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
    
    	<!-- Embedded ActiveMQ Broker -->
    	<amq:broker useJmx="true" persistent="false" >
    		<amq:managementContext>
    			<amq:managementContext createConnector="false" jmxDomainName="org.apache.activemq"/>
    		</amq:managementContext>
    		
    		<amq:networkConnectors>
    			<amq:networkConnector uri="multicast://default"
    				dynamicOnly="true" networkTTL="3" prefetchSize="1"
    				decreaseNetworkConsumerPriority="true" />
    		</amq:networkConnectors>
    
    		<amq:transportConnectors>
    			<amq:transportConnector name="openwire"
    				uri="tcp://0.0.0.0:61616" discoveryUri="multicast://default" />
    		</amq:transportConnectors>
    	</amq:broker>
    
    	<amq:connectionFactory id="jmsFactory" brokerURL="vm://localhost" />
    	
    	<amq:topic id="builderTopic" physicalName="MyApp.builder.topic" />
    
    	<flex:jms-message-destination id="MyAppBuilderDestination" 
    		jms-destination="builderTopic" connection-factory="jmsFactory"
    		channels="my-polling-amf,my-longpolling-amf,my-streaming-amf" 
    		allow-subtopics="true" subtopic-separator="." />
    My web.xml contains the following:

    Code:
        <context-param>
        	<param-name>contextConfigLocation</param-name>
        	<param-value>/WEB-INF/applicationContext.xml</param-value>
        </context-param>
        
        <listener>
        	<listener-class>
        		myapp.web.context.ContextLoaderListener
        	</listener-class>
        </listener>
        
    	<listener>
    	  <listener-class>org.springframework.security.ui.session.HttpSessionEventPublisher</listener-class>
    	</listener>
    	
    	<!-- Http Flex Session attribute and binding listener support -->
        <listener>
            <listener-class>flex.messaging.HttpFlexSession</listener-class>
        </listener>
    and the subclassed ContextLoaderListener code is below:
    Code:
    public class ContextLoaderListener extends
    		org.springframework.web.context.ContextLoaderListener {
    
    	/* (non-Javadoc)
    	 * @see org.springframework.web.context.ContextLoaderListener#contextDestroyed(javax.servlet.ServletContextEvent)
    	 */
    	@Override
    	public void contextDestroyed(ServletContextEvent event) {
    		// clean up after ActiveMQ
    		Scheduler amqScheduler = Scheduler.getInstance();
    		if (amqScheduler != null) {
    			amqScheduler.shutdown();
    		}
    		
    		super.contextDestroyed(event);
    	}
    
    }
    I can see that the client subscribes and unsubscribes from these logs:

    Code:
    2009-12-29 10:58:09,890 INFO  JmsAdapter - client [6C943EDF-E31F-9A9F-BEA7-C2184E1D4C63] subscribed to destination [MyAppBuilderDestination]
    2009-12-29 11:44:38,681 INFO  JmsAdapter - client [6C943EDF-E31F-9A9F-BEA7-C2184E1D4C63] unsubscribed from destination [MyAppBuilderDestination]
    When I stop Tomcat the logs indicate that the Broker, NetworkConnector and TransportConnectors are stopped.

    Code:
    Dec 29, 2009 11:47:17 AM org.apache.coyote.http11.Http11NioProtocol pause
    INFO: Pausing Coyote HTTP/1.1 on http-8080
    Dec 29, 2009 11:47:18 AM org.apache.catalina.core.StandardService stop
    INFO: Stopping service Catalina
    2009-12-29 11:47:22,078 INFO  BrokerService - ActiveMQ Message Broker (localhost, ID:PCERI2109-3958-1262105704883-0:0) is shutting down
    2009-12-29 11:47:22,078 INFO  NetworkConnector - Network Connector localhost Stopped
    2009-12-29 11:47:24,015 INFO  TransportConnector - Connector openwire Stopped
    2009-12-29 11:47:24,171 INFO  TransportConnector - Connector vm://localhost Stopped
    2009-12-29 11:47:24,234 INFO  BrokerService - ActiveMQ JMS Message Broker (localhost, ID:PCERI2109-3958-1262105704883-0:0) stopped
    log4j:ERROR LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository.
    Dec 29, 2009 11:47:29 AM org.apache.coyote.http11.Http11NioProtocol destroy
    INFO: Stopping Coyote HTTP/1.1 on http-8080
    JConsole does not detect a deadlock, but shows:
    Code:
    Name: DefaultMessageListenerContainer-1
    State: WAITING on java.lang.Object@5b309a
    Total blocked: 8  Total waited: 4,039
    
    Stack trace: 
    java.lang.Object.wait(Native Method)
    java.lang.Object.wait(Object.java:485)
    org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:961)
    org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:876)
    java.lang.Thread.run(Thread.java:619)
    Is there something I can call from the contextDestroyed method to cause this thread to exit? I looked at the MessageDestinationFactory (flex:jms-message-destination), and tried calling it's destroy method, but this did not work. How can I get a reference to DefaultMessageListenerContainer?

  • #2
    Hi

    I had a similar problem.
    Search for a post with title Testdrive jms chat around the beginning of December.

    Regards
    Alex

    Comment


    • #3
      Thanks. Here's the link to the JIRA ticket for anyone that stumbles across this:
      https://jira.springsource.org/browse/FLEX-87

      Comment

      Working...
      X