Unable to connect Spring AMQP / Rabbit MQ : org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect - rabbitmq

I am new to Spring AMQP / Rabbit MQ.
Am using a Spring AMQP / Rabbit MQ in my project. I am facing following error after running a tomcat:
org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer
- Consumer raised exception, processing can restart if the connection factory supports it.
Exception summary: org.springframework.amqp.AmqpConnectException:
java.net.ConnectException: Connection refused: connect
Below is the configuration file :
spring-amqp.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rabbit="http://www.springframework.org/schema/rabbit"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
<rabbit:connection-factory id="connectionFactory" host="127.0.0.1"/>
<rabbit:admin connection-factory="connectionFactory"/>
<rabbit:template connection-factory="connectionFactory" id="rabbitTemplate" channel-transacted="true"/>
<rabbit:queue name="proposalQueue" />
<rabbit:listener-container connection-factory="connectionFactory">
<rabbit:listener ref="listener" queue-names="proposalQueue"/>
</rabbit:listener-container>
<bean id="rabbitMQTransactionManager" class="org.springframework.amqp.rabbit.transaction.RabbitTransactionManager">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
<rabbit:direct-exchange name="myExchange">
<rabbit:bindings>
<rabbit:binding queue="proposalQueue" key="userMesssage" />
</rabbit:bindings>
</rabbit:direct-exchange>
<bean id="listener" class="com.xxx.xxxx.rabbitmq.QueueServer"/>
</beans>
QueueServer.java
#Override
public void onMessage(Message message) {
Map<String, Object> result = new HashMap<>();
MessageProperties props = message.getMessageProperties();
BasicProperties replyProps = new BasicProperties.Builder().correlationId(new String(message.getMessageProperties().getCorrelationId())).build();
String inputParameterStr = new String(message.getBody());
try {
Map<String,Object> inputParameters = (Map<String, Object>) Utility.StringToObject(inputParameterStr, "java.util.Map");
result = service.createQueue(inputParameters);
} catch (ClassNotFoundException e) {
logger.error("Error :::: "+getClass()+proposalID, e);
result.put(Constants.FAILURE, e.getMessage());
} catch (Exception e) {
logger.error("Error :::: "+getClass()+proposalID, e);
result.put(Constants.FAILURE, e.getMessage());
}
}
Please help to resolve.

java.net.ConnectException: Connection refused: connect
That simply means that RabbitMQ is not running on localhost (127.0.0.1) on the standard port (5672).
Did you download and install/run RabbitMQ? It is not like ActiveMQ - it can't run embedded in a java application.

Check the host and port value
In application.properties
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
See RabbitMQ site is running on port 15672 whereas in code using amqp protocol.

There's one more aspect to the problem.
By default, the RabbitMQ is accessible to the local machine only. If you want to access it from some other machine, you generally create one entry in "rabbitmq.config" file. Location of this file varies from OS to OS. In Linux, you can find this at: "/etc/rabbitmq/rabbitmq.config" and in Windows machine, you can find it at: "C:\Program Files\RabbitMQ Server\rabbitmq_server-3.6.9\etc\rabbitmq.config".
There's a possibility that you don't find this file at the mentioned location. This is an optional file and you need not to worry if it is missing even. You can create your own. This entry is something like:
[{rabbit, [{tcp_listeners, [{"<IP_OF_MACHINE>", 5672}]},{loopback_users, []}]}].
With this, you can access the server from any remote machine.
If after this you get the server inaccessible you can modify the entry to:
[{rabbit, [{tcp_listeners, [{"0.0.0.0", 5672}]},{loopback_users, []}]}].
You will definitely get the server connected to any client as well as through management console (if plugin enabled)

i'm confronted the same problem (when using docker). Above answers didn't help me. I switched to a different version rabbitmq.
was:
rabbitmq:3.9.14-management-alpine
now:
rabbitmq:3.9.8-management-alpine

In order to access the RabbitMQ remote , you need to allow inbound TCP traffic on ports 4369, 25672, 5671, 5672, 15672, 61613, 61614, 1883, and 8883.
sudo firewall-cmd --zone=public --permanent --add-port=4369/tcp --add-port=25672/tcp --add-port=5671-5672/tcp --add-port=15672/tcp --add-port=61613-61614/tcp --add-port=1883/tcp --add-port=8883/tcp
sudo firewall-cmd --reload

Related

How to setup jms in Red Hat middleware to RabbitMQ

I run Red Hat middleware with CodeReady Studio 12.16.0.GA on standalone Spring-boot environment as local Camel context. I have local RabbitMQ running in Docker.
I have failed to setup any scenario using tutorials on web in/out JMS using Camel.
All tutorials don't use camel-context.xml configuration only pure java spring.
Please help me to configure camel-context.xml and all resource to use RabbitMQ or just any JMS.
Thanks in advance.
Here is simple camel-context.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring https://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route id="simple-route">
<from id="_to1" uri="jms:myQeue?connectionFactory=#myConnectionFactory&jmsMessageType=Text"/>
<log id="route-log" message=">>> ${body}"/>
</route>
</camelContext>
</beans>
and simple spring application to run it
package org.mycompany;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
#SpringBootApplication
#ImportResource({"classpath:spring/camel-context.xml"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
But it went to exception
Caused by: org.apache.camel.ResolveEndpointFailedException: Failed to resolve endpoint: jms://myQeue?connectionFactory=%23myConnectionFactory&jmsMessageType=Text due to: No bean could be found in the registry for: myConnectionFactory of type: javax.jms.ConnectionFactory
I have added registration of ConnectionFactory
ConnectionFactory myCF = new ConnectionFactory();
myCF.setUsername("guest");
myCF.setPassword("guest");
myCF.setVirtualHost("/");
myCF.setHost("localhost");
myCF.setPort(5672);
SimpleRegistry reg = new SimpleRegistry();
reg.put("myConnectionFactory", myCF);
CamelContext camContext = new DefaultCamelContext(reg);
but new exception arose I think because of using com.rabbitmq.client.ConnectionFactory
Caused by: org.apache.camel.FailedToCreateRouteException: Failed to create route simple-route: Route(simple-route)[[From[jms:queue:myQeue?connectionFactory... because of connectionFactory must be specified
How to define javax.jms.ConnectionFactory to registry?

CXF with Camel - HTTPS

I am trying to implement a module to send messages from a CXF client to a server (SOAP endpoint) using HTTPS. I am able to achieve this by following the guide here: https://camel.apache.org/how-to-switch-the-cxf-consumer-between-http-and-https-without-touching-the-spring-configuration.html
The following configuration is key:
<ctx:property-placeholder location="classpath:orderEntry.cfg" />
<!-- other properties -->
<http:conduit name="{http://www.company.com/product/orderEntry/service/1}OrderEntry.http-conduit">
<http:tlsClientParameters disableCNCheck="true">
<sec:trustManagers>
<sec:keyStore type="JKS" password="${trustStore.password}" file="${trustStore.file}"/>
</sec:trustManagers>
<!-- other config -->
</http:tlsClientParameters>
</http:conduit>
The above configuration refers to a config file that has these properties stored:
orderEntry.cfg
--------------
endpointUri=https://localhost:8181/OrderEntry
trustStore.password=password
trustStore.file=etc/myApp.ts
As noted earlier, I am able to send messages via https when I follow the guide.
But I am concerned about the password being stored in plain text here. Is there a way that I can have the password wired from Java code (which can probably read the password from an encrypted source) and provide it to the http conduit when it needs it?
Have you tried location attribute value with file prefix?
E.g. location="file:/my/custom/location/orderEntry.cfg"
See: https://stackoverflow.com/a/17303537
Update:
If it works with your custom bean, you can try create trust managers as a bean and inject it into the conduit configuration like bellow:
blueprint.xml
<bean id="serviceTrustManager"
class="my.app.security.KeyStores" factory-method="loadTrustManagers">
<argument index="0" value="${my.app.service.trustStorePath}"/>
<argument index="1" value="${my.app.service.trustStoreEncryptedPassword}"/>
</bean>
<http:conduit name="{http://www.company.com/product/orderEntry/service/1}OrderEntry.http-conduit">
<http:tlsClientParameters disableCNCheck="true">
<sec:trustManagers ref="serviceTrustManager"/>
</http:tlsClientParameters>
</http:conduit>
Java code:
public class KeyStores {
public static TrustManager[] loadTrustManagers(String trustStorePath, String trustStoreEncryptedPassword) {
String trustStoreDecryptedPassword = PasswordDescriptor.decryptPassword(trustStoreEncryptedPassword); //Password decryption logic here
KeyStore trustStore = KeyStores.loadKeyStore("JKS", trustStorePath, trustStoreDecryptedPassword); //IO logic here
TrustManagerFactory trustFactory;
try {
trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(trustStore);
} catch (NoSuchAlgorithmException | KeyStoreException ex) {
throw new IllegalStateException(ex);
}
return trustFactory.getTrustManagers();
}
}

ava RabbitMQ client (amqp-client-3.6.5.jar) is blocking indefinitely on "Channel.Open" command

I am using Spring Integration AMQP 4.1.2, Spring Rabbit 1.4.3, Spring Amqp 1.4.3, amqp-client-3.6.5.jar to publish messages to RabbitMQ server 3.5.3
As part of negative testing, I am sending messages to Non Existing Exchange.
I have a negative acknowledgement handler configured using Spring Integration Amqp. This negative acknowledgement handler got invoked with the failed message and even this message contains the reason for negative acknowledgement.
Everything is perfect up to here.
I need to Retry the failed message again as part of requirement. So the negative acknowledgement handler retires to publish the same message again.
At this time, when the Java RabbitMQ client (amqp-client-3.6.5.jar) trying to issue the command "Channel.Open" to the RabbitMQ server.
But this call getting blocked indefinitely (AMQP Connection thread is indefinitely waiting on the Object BlockingValueOrException which is responsible to notify)
and the Java client is indefinitely waiting for the response to the command "Channel.Open". But I could see a new channel got created in RabbitMQ server using the admin console.
Why my "Channel.Open" call getting blocked? Is RabbitMQ server failed to send response to the command "Channel.Open"?
How to check the command requests and responses passed in between Java RabbitMQ client and RabbitMQ server? Do we have any plugins that need be installed in RabbitMQ server?
Please help me in this regard. Configuration information is below.
Spring Integration Amqp configuration that publishes messages and registers ack/nack, return handlers
<!-- AMQP/RMQ Publishing -->
<int-amqp:outbound-channel-adapter
default-delivery-mode="PERSISTENT" exchange-name="${prism.rabbitmq.exchange}"
routing-key-expression="headers['${prism.rabbitmq.message.header.routingKey}']" amqp-template="amqpTemplate"
mapped-request-headers="*" channel="outgoingRabbit"
confirm-ack-channel="successfullyPublishedChannel"
confirm-nack-channel="mailPublishingExceptionChannel"
confirm-correlation-expression="#this" lazy-connect="false" return-channel="mailPublishingExceptionChannel"/>
<!-- AMQP client connection factory -->
<bean id="amqpClientConnectionFactory" class="com.rabbitmq.client.ConnectionFactory">
<property name="uri"
value="amqp://guest:guest#127.0.0.1:5672" />
<property name="automaticRecoveryEnabled"
value="true" />
</bean>
<rabbit:connection-factory id="amqpConnectionFactory"
host="127.0.0.1" connection-factory="amqpClientConnectionFactory"
publisher-confirms="true" publisher-returns="true" channel-cache-size="5"/>
<rabbit:template id="amqpTemplate" connection-factory="amqpConnectionFactory"
exchange="${prism.rabbitmq.exchange}" retry-template="retryTemplate" mandatory="true"/>
<bean id="retryTemplate" class="org.springframework.retry.support.RetryTemplate">
<property name="retryPolicy">
<bean class="org.springframework.retry.policy.SimpleRetryPolicy">
<property name="maxAttempts" value="4" />
</bean>
</property>
<property name="backOffPolicy">
<bean class="org.springframework.retry.backoff.ExponentialBackOffPolicy">
<property name="initialInterval" value="1000" />
<property name="multiplier" value="5.0" />
<property name="maxInterval" value="60000" />
</bean>
</property>
</bean>
Negative Acknowledgement Handler configuration
<int:service-activator input-channel="mailPublishingExceptionChannel" ref="mailPublishingExceptionHandler" method="handleError" />
Negative Acknowledgement Handler class's handle method.
#Autowired
#Qualifier("outgoingRabbit")
private MessageChannel outgoingRabbit;
#Override
public void handleError(Message<?> genMessage) {
try {
// Retry !!
// Get the failed RMQ Message whose payload is JSON and has Message
// Headers as well.
Message failedRMQMessage = (Message) genMessage.getPayload();
MessageBuilder rmqMessageWithRetry = MessageBuilder.withPayload(failedRMQMessage.getPayload());
rmqMessageWithRetry.copyHeaders(failedRMQMessage.getHeaders());
new MessagingTemplate().send(outgoingRabbit, rmqMessageWithRetry.build()); --> this call again publishes the payload
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

ActiveMQ failover seems not to work

I have super simple scenario: one broker and one consumer with durable subscription.
This is the code of my consumer app:
package test;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import org.apache.activemq.ActiveMQConnectionFactory;
import pojo.Event;
import pojo.StockUpdate;
public class Consumer
{
private static transient ConnectionFactory factory;
private transient Connection connection;
private transient Session session;
public static int counter = 0;
public Consumer(String brokerURL) throws JMSException
{
factory = new ActiveMQConnectionFactory(brokerURL);
connection = factory.createConnection();
connection.setClientID("CLUSTER_CLIENT_1");
connection.start();
session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}
public void close() throws JMSException
{
if (connection != null)
{
connection.close();
}
}
public static void main(String[] args) throws JMSException
{
try
{
// extract topics from the rest of arguments
String[] topics = new String[2];
topics[0] = "CSCO";
topics[1] = "ORCL";
// define connection URI
Consumer consumer = new Consumer("failover:(tcp://localhost:61616)?maxReconnectAttempts=-1&useExponentialBackOff=true");
for (String stock : topics)
{
try
{
Destination destination = consumer.getSession().createTopic("STOCKS." + stock);
// consumer.getSession().
MessageConsumer messageConsumer = consumer.getSession().createDurableSubscriber((Topic) destination, "STOCKS_DURABLE_CONSUMER_" + stock);
messageConsumer.setMessageListener(new Listener());
}
catch (JMSException e)
{
e.printStackTrace();
}
}
}
catch (Throwable t)
{
t.printStackTrace();
}
}
public Session getSession()
{
return session;
}
}
class Listener implements MessageListener
{
public void onMessage(Message message)
{
try
{
TextMessage textMessage = (TextMessage) message;
String json = textMessage.getText();
Event event = StockUpdate.fromJSON(json, StockUpdate.class);
System.out.println("Consumed message #:" + ++Consumer.counter + "\n" + event);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
Here is my activemq.xml
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd">
<!-- Allows us to use system properties as variables in this configuration file -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>file:${activemq.conf}/credentials.properties</value>
</property>
</bean>
<!--
The <broker> element is used to configure the ActiveMQ broker.
-->
<broker xmlns="http://activemq.apache.org/schema/core" brokerName="R6_cluster_broker1" persistent="true">
<networkConnectors>
<networkConnector uri="static:(failover:(tcp://remote_master:61616,tcp://remote_slave:61617))"/>
</networkConnectors>
<destinationPolicy>
<policyMap>
<policyEntries>
<policyEntry topic=">" >
<!-- The constantPendingMessageLimitStrategy is used to prevent
slow topic consumers to block producers and affect other consumers
by limiting the number of messages that are retained
For more information, see:
http://activemq.apache.org/slow-consumer-handling.html
-->
<pendingMessageLimitStrategy>
<constantPendingMessageLimitStrategy limit="1000"/>
</pendingMessageLimitStrategy>
</policyEntry>
</policyEntries>
</policyMap>
</destinationPolicy>
<!--
The managementContext is used to configure how ActiveMQ is exposed in
JMX. By default, ActiveMQ uses the MBean server that is started by
the JVM. For more information, see:
http://activemq.apache.org/jmx.html
-->
<managementContext>
<managementContext createConnector="false"/>
</managementContext>
<!--
Configure message persistence for the broker. The default persistence
mechanism is the KahaDB store (identified by the kahaDB tag).
For more information, see:
http://activemq.apache.org/persistence.html
-->
<persistenceAdapter>
<kahaDB directory="/work/temp/kahadb"/>
</persistenceAdapter>
<!--
The systemUsage controls the maximum amount of space the broker will
use before disabling caching and/or slowing down producers. For more information, see:
http://activemq.apache.org/producer-flow-control.html
-->
<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage percentOfJvmHeap="70" />
</memoryUsage>
<storeUsage>
<storeUsage limit="100 gb"/>
</storeUsage>
<tempUsage>
<tempUsage limit="50 gb"/>
</tempUsage>
</systemUsage>
</systemUsage>
<!--
The transport connectors expose ActiveMQ over a given protocol to
clients and other brokers. For more information, see:
http://activemq.apache.org/configuring-transports.html
-->
<transportConnectors>
<!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<!-- <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/>
<transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&wireFormat.maxFrameSize=104857600"/> -->
</transportConnectors>
<!-- destroy the spring context on shutdown to stop jetty -->
<shutdownHooks>
<bean xmlns="http://www.springframework.org/schema/beans" class="org.apache.activemq.hooks.SpringContextHook" />
</shutdownHooks>
</broker>
<!--
Enable web consoles, REST and Ajax APIs and demos
The web consoles requires by default login, you can disable this in the jetty.xml file
Take a look at ${ACTIVEMQ_HOME}/conf/jetty.xml for more details
-->
<import resource="jetty.xml"/>
</beans>
When I have both broker and consumer running and then stop the broker my consumer exits few moments after. As far I understood it must attempt to reconnect, but it is not the case. What am I doing wrong, please advise.
!NOTE! I launch my consumer in Eclipse, i do not build a standalone jar for this task.
I have updated my broker to the latest 5.9.1 and did the same to my consumer. Result is the same - after I stop the broker my consumer dies few seconds after. It works fine if broker is up and running.
For anyone who can't setup the failover via the URI/URL parameter in the ConnectionFactory ,because of schema not found in ARTEMIS :
As far as I know in the ActiveMQ the URL is the following:
failover:(tcp://localhost:61616,tcp://localhost:51516)?randomize=false
But in Artemis the above will fail ,because of schema not found so remove just the failover: prefix:
(tcp://localhost:61616,tcp://localhost:51516)?randomize=false
Alright, the problem was actually in my code: there was nothing that would prevent main thread from exiting. Since thread that implements failover is a daemon thread, consumer app terminated right after there was nothing to hold on to (no non-daemon threads).
Most likely you are using a version of ActiveMQ that has a bug which causes there to be all daemon threads which means there's nothing to keep the client running. Upgrade to a later version such as v5.9.1 and see if that helps. If not post more information as you haven't really provided much.

JmsTemplate does not close connections even with PooledConnectionFactory

We use AMQ broker 5.5 and Spring 3.0 for configuring connection factory and other stuffs.
The connection factory we are using is PooledConnectionFactory and a part of my config looks like this:
<bean id="jmsFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="some_url"/>
</bean>
</property>
</bean>
<!-- Spring JMS Template -->
<bean id="jmsTemplate"
class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref local="jmsFactory" />
</property>
<property name="explicitQosEnabled" value="true"/>
<property name="timeToLive" value="86400000"/>
</bean
A few days back our broker crashed and kept restarting with this error:
java.lang.OutOfMemoryError: requested
369384 bytes for Chunk::new. Out of swap space?
At that point of time, from jconsole, I could not find anything unusual with the broker, except that one of our client application
which talks with the server (via broker) by sending and listening to messages every minute had created ~3000 connections (saw it on jconsole).
Once we had shut it down, everything was back to normal.
So, to avoid this I tried closing the connection in finally block doing something like this.
try {
connection = myJmsTemplate.getConnectionFactory().createConnection();
session = connection.createSession(false, 1);
String messageSelector = "JMSCorrelationID='" + correlationId + "'";
responseConsumer = session.createConsumer(receiveDestination, messageSelector);
LOG.info("Starting connection");
connection.start();
myJmsTemplate.send(sendDestination, new SimpleTextMessageCreator(
message, receiveDestination, correlationId));
LOG.info("Waiting for message with " + messageSelector + " for " + DEFAULT_TIMEOUT + " ms");
TextMessage responseMessage = (TextMessage) responseConsumer.receive(DEFAULT_TIMEOUT);
}
catch (Someexception e) {do something}
finally {
responseConsumer.close();
session.close();
connection.close();
}
But even then I can see the connections floating around in jconsole and are only lost if the client app which publishes the messages is brought down.
Can someone please help me understand what's happening here and how I can close the connections after each pub sub cycle.
Thank you in advance,
Hari
False alarm. There was another piece of code that was leaving the connection open. Closing it solved the issue.