CachingConnectionFactory and request-reply pattern

View: New views
4 Messages — Rating Filter:   Alert me  

CachingConnectionFactory and request-reply pattern

by batalbot :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I'm aware that springsupport's SingleSharedConnectionFactory class can be used to cache connection, session, producer and consumer objects for better performance.  However, we sometimes have spring-based JMS-provider agnostic programs connecting to the swiftmq server.  These programs sometimes use spring's CachingConnectionFactory which also caches those objects.

When the CachingConnectionFactory is used with transactions enabled in a request-reply pattern, transactions fail to commit.  The exception is: com.swiftmq.swiftlet.queue.QueueHandlerClosedException: queue handler is closed!

The spring SingleConnectionFactory, which only caches connections, seems to not have this issue.  The springsupport SingleSharedConnectionFactory also doesn't have this issue.

In some cases, it is possible to re-configure the application to use springsupport or SingleConnectionFactory, doing so is painful, hinders deployment and maintenance, and seems like it should not be necessary.  

While it may be desirable to use the springsupport classes for a performance improvement, swiftmq should still operate correctly for applications written to be used with generic JMS providers not using vendor extensions.

Once the error occurs, (it always occurs when replying to the first request) all processing is blocked while the message is redelivered endlessly.

Below is a snip from a log file with spring debug enabled from a small sample program that reproduces the error.  I'll attach the sample program source.  This is produced using swiftmq 7.5.1.

spring-replyto.tgz


2009-05-29 18:27:06,347 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Initiating transaction commit
2009-05-29 18:27:06,347 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Committing JMS transaction on Session [Cached JMS Session: com.swiftmq.jms.v750.SessionImpl@4816ef71]
2009-05-29 18:27:06,347 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Creating new transaction with name [jmsContainer]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2009-05-29 18:27:06,347 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Created JMS transaction on Session [Cached JMS Session: com.swiftmq.jms.v750.SessionImpl@4816ef71] from Connection [Shared JMS Co
nnection: com.swiftmq.jms.v750.ConnectionImpl@29f01a29]
2009-05-29 18:27:06,806 [jmsContainer-1] DEBUG org.springframework.jms.listener.DefaultMessageListenerContainer - Received message of type [class com.swiftmq.jms.TextMessageImpl] from consumer [Cached JMS MessageConsumer: testqueue@rou
ter1] of transactional session [Cached JMS Session: com.swiftmq.jms.v750.SessionImpl@4816ef71]
2009-05-29 18:27:06,806 [jmsContainer-1] INFO  bat.Responder - Processed message and sending response: GIVE ME INFO!
2009-05-29 18:27:06,806 [jmsContainer-1] DEBUG bat.SwiftMQAdapter - Listener method returned result [GIVE ME INFO!] - generating response message for it
2009-05-29 18:27:06,807 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Initiating transaction commit
2009-05-29 18:27:06,807 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Committing JMS transaction on Session [Cached JMS Session: com.swiftmq.jms.v750.SessionImpl@4816ef71]
2009-05-29 18:27:06,809 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Creating new transaction with name [jmsContainer]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2009-05-29 18:27:06,809 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Created JMS transaction on Session [Cached JMS Session: com.swiftmq.jms.v750.SessionImpl@4816ef71] from Connection [Shared JMS Co
nnection: com.swiftmq.jms.v750.ConnectionImpl@29f01a29]
2009-05-29 18:27:07,811 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Initiating transaction commit
2009-05-29 18:27:07,811 [jmsContainer-1] DEBUG org.springframework.jms.connection.JmsTransactionManager - Committing JMS transaction on Session [Cached JMS Session: com.swiftmq.jms.v750.SessionImpl@4816ef71]
2009-05-29 18:27:07,813 [jmsContainer-1] INFO  org.springframework.jms.listener.DefaultMessageListenerContainer - Setup of JMS message listener invoker failed for destination 'testqueue' - trying to recover. Cause: Could not commit JMS
 transaction; nested exception is javax.jms.JMSException: com.swiftmq.swiftlet.queue.QueueHandlerClosedException: queue handler is closed!
org.springframework.transaction.TransactionSystemException: Could not commit JMS transaction; nested exception is javax.jms.JMSException: com.swiftmq.swiftlet.queue.QueueHandlerClosedException: queue handler is closed!
        at org.springframework.jms.connection.JmsTransactionManager.doCommit(JmsTransactionManager.java:242)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
        at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:255)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:982)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:974)
        at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:876)
        at java.lang.Thread.run(Thread.java:619)
Caused by: javax.jms.JMSException: com.swiftmq.swiftlet.queue.QueueHandlerClosedException: queue handler is closed!
        at com.swiftmq.jms.ExceptionConverter.convert(Unknown Source)
        at com.swiftmq.jms.v750.SessionImpl.commit(Unknown Source)
        at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.jms.connection.CachingConnectionFactory$CachedSessionInvocationHandler.invoke(CachingConnectionFactory.java:332)
        at $Proxy1.commit(Unknown Source)
        at org.springframework.jms.connection.JmsTransactionManager.doCommit(JmsTransactionManager.java:236)
        ... 7 more
2009-05-29 18:27:07,814 [jmsContainer-1] INFO  org.springframework.jms.listener.DefaultMessageListenerContainer - Successfully refreshed JMS Connection
2009-05-29 18:27:07,815 [jmsContainer-2] DEBUG org.springframework.jms.connection.JmsTransactionManager - Creating new transaction with name [jmsContainer]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2009-05-29 18:27:07,815 [jmsContainer-2] DEBUG org.springframework.jms.connection.JmsTransactionManager - Created JMS transaction on Session [Cached JMS Session: com.swiftmq.jms.v750.SessionImpl@4816ef71] from Connection [Shared JMS Co
nnection: com.swiftmq.jms.v750.ConnectionImpl@29f01a29]
2009-05-29 18:27:07,815 [jmsContainer-2] DEBUG org.springframework.jndi.JndiTemplate - Looking up JNDI object with name [testqueue]
2009-05-29 18:27:07,829 [jmsContainer-2] DEBUG org.springframework.jms.support.destination.JndiDestinationResolver - Located object with JNDI name [testqueue]
2009-05-29 18:27:07,830 [jmsContainer-2] DEBUG org.springframework.jms.connection.CachingConnectionFactory - Creating cached JMS MessageConsumer for destination [testqueue@router1]: testqueue@router1
2009-05-29 18:27:08,832 [jmsContainer-2] DEBUG org.springframework.jms.connection.JmsTransactionManager - Initiating transaction commit
2009-05-29 18:27:08,832 [jmsContainer-2] DEBUG org.springframework.jms.connection.JmsTransactionManager - Committing JMS transaction on Session [Cached JMS Session: com.swiftmq.jms.v750.SessionImpl@4816ef71]

Re: CachingConnectionFactory and request-reply pattern

by IIT Software :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Yes, that's a bug. We try to close a "markedForClose" producer on a deleted temp queue (the reply queue) which then throws the QueueHandlerClosedException. Will be fixed ASAP.

Re: CachingConnectionFactory and request-reply pattern

by IIT Software :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

It's fixed in 7.5.2 which has been released today. Look here.

Re: CachingConnectionFactory and request-reply pattern

by batalbot :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

7.5.2 seems to resolve the issue.

Thanks,
Bryan