How to timeout queueConnectionFactory create connection - java

I'm facing a timeout while invoking javax.jms.QueueConnectionFactory.createQueueConnection()
¿Is there any way to customize timout time for creating connection?
javax.jms.QueueConnectionFactory connectionFactory; //look up in context here
connectionFactory.createConnection();

This depends to how you connect to jms, for spring you can see How to set waiting timeout on JmsMessagingTemplate.sendAndReceive for ibm mq IBM MQ Connect Factory CLIENTRECONNECTTIMEOUT without using CLIENTRECONNECTOPTIONS

Related

Quarkus ActiveMQ JMS

I have an ActiveMQ queue that does seem not seem to be supported by Quarkus. When I try to use the Quarkus JMS implementation described here I get the following error:
AMQP SASL header mismatch value 0, expecting 41. In state: HEADER0
I assume that this is because the ActiveMQ server does not support AMQP. The code I wrote to try and connect to the ActiveMQ server.
ConnectionFactory connectionFactory = new ConnectionFactory();
connection = connectionFactory.createConnection();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("inQue");
producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
messageMap = session.createMapMessage();
While the above does not work. If i change it to using
ActiveMQConnectionFactory from ActiveMQ it works just fine:
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
connection = connectionFactory.createConnection("admin", "admin");
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createQueue("inQue");
producer = session.createProducer(destination);
producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
messageMap = session.createMapMessage();
But if i change to the Quarkus version of ConnectionFactory it no longer works and I get the error above. So is it possible to solve this somehow? Or do I need to use ActiveMQConnectionFactory? If so, how can I get Quarkus to register my MessageListener? Right now, just to test, I write:
MessageListener listener = new MyListener();
consumer.setMessageListener(listener);
But I would like Quarkus to do this when the application starts. But I'm not sure how to do it.
Depending on which version of ActiveMQ you are using you should be able to use the Quarkus JMS extension which is based on Qpid JMS and speaks AMQP. The trick is that you need to connect to the transport connector that was configured to speak AMQP and not one that uses the native Openwire protocol which normally resides on port 61616.
The ActiveMQ documentation defines how this is done. Essentially in your broker configuration you need a definition similar to this:
<transportConnectors>
<transportConnector name="amqp" uri="amqp://0.0.0.0:5672"/>
</transportConnectors>
Of course if using ActiveMQ Artemis this configuration would be different but you didn't specify which specific version of ActiveMQ you are running.
The error message you provided (If it is from the server logs) indicates that the client did indeed connect to an AMQP endpoint but it got something that it did not expect which implies something else strange is going on such as you are not using Qpid JMS but some other client since the initial byte of the expected AMQP header is reported to have been zero which is definitely wrong since an AMQP header always starts with the letter 'A'.
NOTE: Given the comments the error message in the question is likely from the client which would indicate the client read the normally sent Openwire header meaning the transport connector in play was an Openwire variant.

Unacked message if RabbitMQ server restarts in between the consumer consumes message

I am using Spring AMQP and this is my connection factory code:
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setAcknowledgeMode(AcknowledgeMode.AUTO);<br/>
factory.setDefaultRequeueRejected(false);
During consuming the message if RabbitMQ server restarts or there is a connection lost I will get the below exception:
org.springframework.amqp.rabbit.connection.AutoRecoverConnectionNotCurrentlyOpenException: Auto recovery connection is not currently open
If server comes up my application will be connected again
but with a new connection and there will be an unacked messsage.
How to handle this? I want the message to be requeued and my old connection should be killed.
Consider to use the latest Spring AMQP 1.7.2 which turns off that:
connectionFactory.setAutomaticRecoveryEnabled(false);
on the target com.rabbitmq.client.ConnectionFactory in favor of its own recovery mechanism.

Jms Broker connection - Test the connection before listening to the queue - java

We have a message listener that listens to the Queue configured. When the Message broker is stopped or down, the application exits abruptly. Is there way to check the JMS broker connection before listening to the queue. The listener code must be enabled only if the JMS Broker is up. We are getting the below exception when we listen to the Queue (with the JMS broker down)
org.springframework.context.ApplicationContextException: Failed to start bean 'xx'; nested exception is org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is javax.jms.JMSException: Could not connect to broker URL: tcp://xx:61616. Reason: java.net.ConnectException: Connection refused: connect
at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:176)
at org.springframework.context.support.DefaultLifecycleProcessor.access$200(DefaultLifecycleProcessor.java:51)
at org.springframework.context.support.DefaultLifecycleProcessor$LifecycleGroup.start(DefaultLifecycleProcessor.java:346)
at org.springframework.context.support.DefaultLifecycleProcessor.startBeans(DefaultLifecycleProcessor.java:149)
at org.springframework.context.support.DefaultLifecycleProcessor.onRefresh(DefaultLifecycleProcessor.java:112)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:773)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.finishRefresh(EmbeddedWebApplicationContext.java:142)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:485)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
you can not test your connection to be active, as whenever you setup connection with activemq it only succeeds if you have an activemq server running.
A good option can be to do it in Java code by handling 'connection exceptions' and trying to re-connect after specific intervals till no exception occurs.This will help in scenario where ActiveMQ is down before you try and setup connection with it.
Hope it helps,
Good Luck!
Use the failover transport in your clients: failover:(tcp://host:port?TCP_OPTIONS)?FAILOVER_OPTIONS
When the connection isn't available (via the inner TCP transport), the failover transport will continue retrying until it is available and then establish the connection and let your client proceed as normal. This will look like the client is hung, but it's just waiting for the broker to become available before continuing. This configuration will also try to re-connect if the connection is broken for some reason (e.g. you restart your broker).
Most people use the failover transport to allow you to connect to whichever broker out of a group of N is available, but it's completely fine to use it with just one inner TCP transport; it will still try to reconnect periodically whenever it fails to connect to the single TCP transport.

cant connect from my desktop to rabbitmq on ec2

I am trying to create an ubuntu vm with rabbitmq on EC2.
I can telnet my rabbit but cant connect with java client.
Here is my code
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("172.31.4.61");
factory.setPort(5672);
Connection connection = factory.newConnection();
I get the following
java.net.ConnectException: Connection timed out: connect
Any ideas?
Make sure you add a rule to allow inbound traffic for port 5672 in the EC2 Security Group.

How do I connect to a Multi-Instance Queue Manager on Tomcat using Spring?

I need to hook up a Multi-instance queue manager on a Tomcat server. I have found all kinds of "properties" that I have to set to do it, but where do they go? Tomcat, in the server XML has some settings but most of the settings needed in the IBM documentation do not map. Currently we have hooked up a "single" instance queue like this:
<Resource
name="jms/TelematicsQCF"
CHAN="JAVA.Z1LC.CLIENT"
HOST="blah.blah.com"
PORT="1111"
QMGR="MQB3"
TRAN="1" auth="Container"
description="JMS Queue Connection Factory for sending messages"
factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
type="com.ibm.mq.jms.MQQueueConnectionFactory"
/>
How do I hook up a multi-instance one? AND, Can I still use the Spring DefaultMessageListenerContainer? AND (o man...) what settings do I need?
I don't have much of Tomcat knowledge but I come from WebSphere MQ background. Looking at the Context you provided, I think the below would work for Multi-instance queue manager.
I am setting CRHOSTS to multiple connection names. I am assuming, on blah.blah.com host, active instance of queue manager runs and listens at port 1414 and standby instance runs on b2.b3.com and listens at port 1544.
CROPT is reconnect option and is set to WMQ_CLIENT_RECONNECT_Q_MGR whose value is 67108864. You can find the value of these constants from cmqc.h file.
CRT is the reconnection timeout value which tells, for how long the client will try to reconnect. After the timeout period, client stops reconnecting if a connection attempt was not successful. In this case I have set the value to 500 seconds.
<Resource
name="jms/TelematicsQCF"
CHAN="JAVA.Z1LC.CLIENT"
CRHOSTS="blah.blah.com(1414), b2.b3.com(1544)"
CROPT="67108864"
CRT="500"
QMGR="MQB3"
TRAN="1" auth="Container"
description="JMS Queue Connection Factory for sending messages"
factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
type="com.ibm.mq.jms.MQQueueConnectionFactory"
/>
Hope this helps.
So the answer is this:
<Resource name="jms/XXXQCF1"
CHAN="TMAX.CHANNEL"
CRSHOSTS="blah1.example.com(1420),blah2.example.com(1420)"
CROPT="67108864"
CRT="500"
QMGR="tmax.lrd.qmgr.a"
TRAN="1"
auth="Container"
description="JMS Queue Connection Factory for sending messages"
factory="com.ibm.mq.jms.MQQueueConnectionFactoryFactory"
type="com.ibm.mq.jms.MQQueueConnectionFactory" />
Notice that Shashi above has "CRHOSTS" and the IBM documentation has the same, however when we tried that it did not work. We put in a ticket to IBM and they said the documentation is incorrect on their website (and by the way, they wanted a ticket to fix their docs!).
I tried Shashi's "CRHOSTS" and it did not work and CRSHOSTS did work. Not sure why that is. We also had to upgrade our jars to 7.5.*. The "CROPT" and "CRT" I am not sure about but these settings work.

Categories

Resources