Spring JMS CachingConnectionFactory doesn't seem to reconnect on exception - spring

The JMS connection didn't get reconnected when this exception happened:
2014-08-16 10:51:36,724 WARN [TIBCO EMS TCPLink Reader (Server-12486338)] connection.CachingConnectionFactory - Encountered a JMSException - resetting the underlying JMS Connection
javax.jms.JMSException: Connection has been terminated
at com.tibco.tibjms.Tibjmsx.buildException(Tibjmsx.java:502)
at com.tibco.tibjms.TibjmsConnection._onDisconnected(TibjmsConnection.java:2286)
at com.tibco.tibjms.TibjmsConnection$ServerLinkEventHandler.onEventDisconnected(TibjmsConnection.java:341)
at com.tibco.tibjms.TibjmsxLinkTcp$LinkReader.work(TibjmsxLinkTcp.java:320)
at com.tibco.tibjms.TibjmsxLinkTcp$LinkReader.run(TibjmsxLinkTcp.java:247)
2014-08-16 10:51:40,286 WARN [TIBCO EMS TCPLink Reader (Server-12494013)] connection.CachingConnectionFactory - Encountered a JMSException - resetting the underlying JMS Connection
javax.jms.JMSException: Connection has been terminated
at com.tibco.tibjms.Tibjmsx.buildException(Tibjmsx.java:502)
at com.tibco.tibjms.TibjmsConnection._onDisconnected(TibjmsConnection.java:2286)
at com.tibco.tibjms.TibjmsConnection$ServerLinkEventHandler.onEventDisconnected(TibjmsConnection.java:341)
at com.tibco.tibjms.TibjmsxLinkTcp$LinkReader.work(TibjmsxLinkTcp.java:320)
at com.tibco.tibjms.TibjmsxLinkTcp$LinkReader.run(TibjmsxLinkTcp.java:247)
The exact same error happened a few seconds apart and I wonder if Spring tried to reconnect and gave up after two tries.
I checked Spring source code and didn't find reconnection logic in onException() method in either CachingConnectionFactory or its parent class SingleConnectionFactory. We're using spring-jms 3.1.2 but I looked at the latest Spring source code as well.
Thanks for your help.

I had similar issue where DefaultMessageListenerContainer is unable to reconnect once an exception happens(when TIBCO primary server stops and switch over to secondary TIBCO server).
I was using SingleConnectionFactory and it was causing the issue.
Fetching the connectionFactory directly from Websphere using java:comp/env/jms/TIBCOConnectionFactory resolved this issue.

Related

Spring Boot JMS listener won't deploy on EAP 7.3 (JBoss/Wildfly)

I'm trying to deploy on EAP 7.3 (ex JBoss, commercial release of Wildfly) an JMS listener like below:
...
#JmsListener(destination = "${jms.destination.name}")
public void onMessage(final Message msg) throws JMSException {
logger.info("*** MessageReceiver.onMessage(): got message {}", ((TextMessage) msg).getText());
}
...
Deploying it on the app server I get the following warning:
2021-06-03 15:57:45,836 WARN [org.springframework.jms.listener.DefaultMessageListenerContainer] (DefaultMessageListenerContainer-7) Setup of JMS message listener invoker failed for destination 'jms.queue.BanQ' - trying to recover. Cause: There is no queue with name jms.queue.BanQ
The deployment gets stuck and the warning above is displayed continuously, every couple of seconds.
So what seems to happen is that the mention queue doesn't exist. However, looking in the console I can see that:
So, as shown in the figure above, the queue named jms.queue.Bank exists. What might be the problem here ?
Many thanks in advance for any help.
Kind regards,
Seymour

Azure service bus javax.jms.IllegalStateException: The MessageProducer was closed due to an unrecoverable error

I am using ASB for enqueue/dequeue messages between components. Component A consumes messages from queue A and produces messages from queue B. It consumes then produces when consume. Both queues are using same Azure service bus with different queue name (A and B).
My problem is that once the component becomes idle for more than like 10~15 minutes, and then tries to consumes/produces, it throws
javax.jms.IllegalStateException: The MessageProducer was closed due to an unrecoverable error.
and
Caused by: javax.jms.JMSException: The link 'G5S1:40611071:qpid-jms:sender:ID:bbc3fc62-4377-4aeb-bb80-117d74e780de:1:47:1:queueB' is force detached. Code: publisher(link578). Details: AmqpMessagePublisher.IdleTimerExpired: Idle timeout: 00:10:00. [condition = amqp:link:detach-forced]
After observing the stack trace and behavior, it is having problems when it tries to produce a message to queueB. For consumer and producer, I am using same name bean cachingConnectionFactory() in MessageGateway beans (not sure it matters).
My guess is that when it consumes, it restart connection with queueA, and when it tries to restart connection with queueB, something is wrong.
Anyone has any idea? If need more information, please let me know.
Did you try to disable the cache producers? something similar to :
CachingConnectionFactory connectionFactory = (CachingConnectionFactory) jmsTemplte.getConnectionFactory();
connectionFactory.setCacheProducers(false);

Is it possible to have a remote pooled JMS connection factory (WildFly 10)?

I have a remote java client which looks up a JMS connection factory on Wildfly 10, and everything works fine as expected. It is just a test program; a simple JMS chat system. When I start more than one instance of the chat client sometimes the following message appears:
WARN: AMQ212051: Invalid concurrent session usage. Sessions are not supposed to be used by more than one thread concurrently.
Followed by a trace.
Now I want to fix this warning, therefore I need a pooled connection factory. But the pooled connection factory isn't available remotely (and as I read it shouldn't be available remotely).
What can I do to fix this warning when I want to start multiple JMS chat clients locally?
I know that the error won't appear when I just different machines.
This is the working non-pooled remote code (but with warning)
final Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
properties.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
try {
context = new InitialContext(properties);
ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup("jms/RemoteConnectionFactory");
jmsContext = connectionFactory.createContext("quickstartUser", "quickstartPwd1!");
} catch (NamingException e) {
e.printStackTrace();
}
The problem isn't caused by not using a pooled connection factory and won't be solved by using a pooled connection factory. The problem is the way your application is using the same JMS session concurrently between multiple threads (as the WARN message indicates). The stack-trace which is logged will show you which class & method is triggering the WARN message.
You need to ensure that your application does not use the same JMS session concurrently between multiple threads. You can do this by giving each thread its own JMS session or by setting up concurrency controls around the session so that only one thread at a time can access it.

IBM MQ ignores JMS ExceptionListener registered by Camel + Spring Boot based app

We develop a microservice based on Apache Camel JMS component and Spring Boot. IBM MQ is used as messaging middleware. There is an issue with exception listener - IBM MQ classes can't find registered exception listener and print it's own stack trace in system out when connection with MQ is broken:
com.ibm.msg.client.jms.internal.JmsProviderExceptionListener
The exception is ignored as no exception listener is registered: '
Message : com.ibm.msg.client.jms.DetailedJMSException: JMSWMQ1107: A problem with this connection has occurred.
An error has occurred with the IBM MQ JMS connection.
Use the linked exception to determine the cause of this error.
org.springframework.jms.connection.CachingConnectionFactory is used for connection setup.
#Bean
protected final ConnectionFactory createMqJmsConnectionFactory() {
MQQueueConnectionFactory mqFactory = new MQQueueConnectionFactory();
// Factory setup
CachingConnectionFactory cachingFactory = new CachingConnectionFactory(mqFactory);
return cachingFactory;
}
CachingConnectionFactory's ancestor implementes javax.jms.ExceptionListener and, as I found on Spring forum, registers itself as exceptionListener. From stack trace I can see that onException() method is invoked after exception, resets connection and writes log.
So we have a situation when IBM MQ ignores CachingConnectionFactory as exception listener. Camel JMS component has exceptionListener endpoint configuration option - I assume, adding of the CachingConnectionFactory here would be redundantly.
Any other settings need to be done in order to register CachingConnectionFactory as exception listener?

Spring JMS Message Redelivery not working as expected for CLIENT_ACKNOWLEDGE mode

My environment: spring 4.1, JBoss EAP 6.4, IBM MQ 8.0:
Messages are not redelivered in the case where Listener throws RuntimeException.
I have the following in JmsConfig:
#Bean
DefaultMessageListenerContainer defaultMessageListenerContainer(QueueConnectionFactory connectionFactory, JndiDestinationResolver dr, MessageListener ml) {
DefaultMessageListenerContainer mlc = new DefaultMessageListenerContainer();
mlc.setConnectionFactory(connectionFactory);
mlc.setMessageListener(ml);
mlc.setDestinationName(jndiInQueue);
mlc.setDestinationResolver(dr);
mlc.setSessionTransacted(true);
mlc.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
return mlc;
}
If I use a JmsTransactionManager and pass it to the above method and use like so:
mlc.setTransactionManager(tm)
Following warnings are written to the log:
It is not valid to commit a non-transacted session, and the behavior is the same, no redelivery.
ConnectionFactory is obtained via JNDI, I wonder if sourcing the ConnectionFactory through jndi has something to do with this?
From the AbstractMessageListenerContainer Javadocs:
In order to consistently arrange for redelivery with any container variant, consider "CLIENT_ACKNOWLEDGE" mode or - preferably - setting "sessionTransacted" to "true" instead
There is a similar question on SO.
Flip your ack mode to Session.SESSION_TRANSACTED instead of CLIENT_ACKNOWLEDGE.
Client Ack mode doesn't work as most folks want it.. and is a common "gotcha" in JMS. It acknowledges current message AND all previous messages in the session. It is not per-message acknowledgement.
Edit:
Also check related post-- IBM MQ may require you to use the "XA" versions of the connection factory class.
ref: Websphere Liberty profile - transacted Websphere MQ connection factory

Resources