Uploaded image for project: 'FUSE Mediation Router'
  1. FUSE Mediation Router
  2. MR-698

camel-jms component tries to use deleted temp destination

    XMLWordPrintable

Details

    Description

      Suppose the following Camel route definition

      <route>
        <from uri="activemq:TEST.IN"/>
        <inOut uri="activemq2:TEST.OUT" />
        <to uri="log:ReplyLogger?level=INFO" />
      </route>
      

      where both activemq and activemq2 use pretty much the same configuration but connect to different brokers.

          <bean id="activemq2" class="org.apache.activemq.camel.component.ActiveMQComponent" >
              <property name="configuration" ref="AMQListenerJMSConfig2" />
          </bean>
      
          <bean id="AMQListenerJMSConfig2" class="org.apache.camel.component.jms.JmsConfiguration">
      	  <property name="connectionFactory" ref="AMQPooledConnectionFactory2" />
      	  <property name="transacted" value="false" />
      	  <property name="concurrentConsumers" value="1" />
      	  <property name="cacheLevelName" value="CACHE_CONSUMER" />
      	  <property name="acknowledgementMode" value="1"/>
      	</bean>
      
      	<bean id="AMQPooledConnectionFactory2" class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
      	  <property name="maxConnections" value="1" />
      	  <property name="connectionFactory" ref="AMQJMSConnectionFactory2" />
      	</bean>
      
      	<bean id="AMQJMSConnectionFactory2" class="org.apache.activemq.ActiveMQConnectionFactory">
      	  <property name="brokerURL" value="tcp://otherhost:61616" />
      	</bean>
      

      If a message is sent to TEST.IN it is consumed by the Camel route, sent to TEST.OUT and any reply received (from an external JMS consumer) is correctly logged by the logger component.
      If however this route remains idle for 31 seconds and then receives another message on TEST.IN, that message is processed by the Camel route, written to TEST.OUT but instead of a receiving a reply message the following error is thrown:

      2013-02-28 11:31:36,169 [ager[temporary]] WARN  ultJmsMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'temporary' - trying to recover. Cause: The Session is closed
      javax.jms.IllegalStateException: The Session is closed
      	at org.apache.activemq.ActiveMQSession.checkClosed(ActiveMQSession.java:731)
      	at org.apache.activemq.ActiveMQSession.getTransacted(ActiveMQSession.java:521)
      	at org.apache.activemq.pool.PooledSession.getTransacted(PooledSession.java:256)
      	at org.springframework.jms.listener.AbstractMessageListenerContainer.commitIfNecessary(AbstractMessageListenerContainer.java:571)
      	at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:358)
      	at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263)
      	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058)
      	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1050)
      	at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:947)
      	at java.lang.Thread.run(Thread.java:680)
      2013-02-28 11:31:36,184 [ager[temporary]] INFO  PooledConnection               - failed to delete Temporary Queue "temp-queue://ID:mac.fritz.box-61188-1362047321410-5:2:1" on closing pooled connection: The connection is already closed
      

      This is whats happening:

      • The msg to be sent to TEST.OUT is constructed and the JMSReplyTo header is set to the already created temp queue with the help of the ReplyManager
      • Before the msg is sent to TEST.OUT a connection is requested from the PooledConnectionFactory, which internally uses commons-pool.
      • commons-pool has smarts built in and checks if the connection is still valid. This invokes a check on the PooledConnectionFactory.
      • The PooledCF checks if the expiry time has elapsed (default to 30 secs) and if it has it closes the connection which cleans up the temp destination.
      • commons-pool gets to know that the resource was closed and creates a new connection under the covers which is returned to camel (spring).
      • Camel (spring) will use that connection to send the msg. Notice the JMSReplyTo is still set to the previous temp destination which does not exist anymore as the old connection got closed and the temp dest got deleted.
      • The external consumer receives the msg, prepares a reply but sending the reply fails as the temp dest is gone. An error is raised on the consumer, the reply however is lost. The error reads: "javax.jms.InvalidDestinationException: Cannot publish to a deleted Destination: temp-queue://ID:mac.fritz.box-64291-1362071410028-5:10:1"
      • Camel tries to read the reply from the temp dest but since its gone it also raises an error: "Setup of JMS message listener invoker failed for destination 'TEST.IN' - trying to recover. Cause: The Session is closed"

      So root cause problem is that the ReplyManager sets a JMSReplyTo address that will be deleted when doing the connection expiry check right thereafter. The PooledConnectionFactory transparently closes the expired connection (which deletes the temp destination) and gives out a new connection.

      Attachments

        Activity

          People

            cibsen@redhat.com Claus Ibsen
            rhn-support-tmielke Torsten Mielke
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: