Camel RabbitMQ connection using camel amqp - rabbitmq
I am trying to connect to rabbitmq in my camel route using camel-amqp (version 2.17) component.
I have configured it as below :
#Bean
CachingConnectionFactory jmsCachingConnectionFactory(){
JmsConnectionFactory pool = new JmsConnectionFactory();
pool.setRemoteURI("amqp://127.0.0.1:5672");
pool.setUsername("guest");
pool.setPassword("guest");
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
cachingConnectionFactory.setTargetConnectionFactory(pool);
return cachingConnectionFactory;
}
#Bean
JmsConfiguration jmsConfig(){
JmsConfiguration configuration = new JmsConfiguration();
configuration.setConnectionFactory(jmsCachingConnectionFactory());
// configuration.setCacheLevelName("CACHE_CONSUMER");
return configuration;
}
#Bean
AMQPComponent amqp(){
AMQPComponent component = new AMQPComponent();
component.setConfiguration(jmsConfig());
return component;
}
The error I am getting is
javax.jms.JMSException: An existing connection was forcibly closed by
the remote host
at
org.apache.qpid.jms.exceptions.JmsExceptionSupport.create(JmsExceptionSupport.java:66)
~[qpid-jms-client-0.8.0.jar:0.8.0]
In my rabbitmq log I can see the below message which I am not able to understand
*
** Reason for termination ==
** {function_clause,
[{rabbit_amqp1_0_link_util,'-outcomes/1-lc$^0/1-0-',
[{list,
[{symbol,<<"amqp:accepted:list">>},
{symbol,<<"amqp:rejected:list">>},
{symbol,<<"amqp:released:list">>},
{symbol,<<"amqp:modified:list">>}]}],
[{file,"src/rabbit_amqp1_0_link_util.erl"},{line,49}]},
{rabbit_amqp1_0_link_util,outcomes,1,
[{file,"src/rabbit_amqp1_0_link_util.erl"},{line,49}]},
{rabbit_amqp1_0_outgoing_link,attach,3,
[{file,"src/rabbit_amqp1_0_outgoing_link.erl"},{line,41}]},
{rabbit_amqp1_0_session_process,with_disposable_channel,2,
[{file,"src/rabbit_amqp1_0_session_process.erl"},{line,377}]},
{rabbit_amqp1_0_session_process,handle_control,2,
[{file,"src/rabbit_amqp1_0_session_process.erl"},{line,197}]},
{rabbit_amqp1_0_session_process,handle_cast,2,
[{file,"src/rabbit_amqp1_0_session_process.erl"},{line,134}]},
{gen_server2,handle_msg,2,[{file,"src/gen_server2.erl"},{line,1049}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,240}]}]}
=ERROR REPORT==== 8-Jul-2016::17:09:27 ===
closing AMQP connection <0.29082.0> (127.0.0.1:55479 -> 127.0.0.1:5672):
{handshake_error,running,<0.29104.0>,
{{symbol,<<"amqp:internal-error">>},
"Session error: ~p~n~p~n",
[function_clause,
[{rabbit_amqp1_0_link_util,'-outcomes/1-lc$^0/1-0-',
[{list,
[{symbol,<<"amqp:accepted:list">>},
{symbol,<<"amqp:rejected:list">>},
{symbol,<<"amqp:released:list">>},
{symbol,<<"amqp:modified:list">>}]}],
[{file,"src/rabbit_amqp1_0_link_util.erl"},{line,49}]},
{rabbit_amqp1_0_link_util,outcomes,1,
[{file,"src/rabbit_amqp1_0_link_util.erl"},{line,49}]},
{rabbit_amqp1_0_outgoing_link,attach,3,
[{file,"src/rabbit_amqp1_0_outgoing_link.erl"},{line,41}]},
{rabbit_amqp1_0_session_process,with_disposable_channel,2,
[{file,"src/rabbit_amqp1_0_session_process.erl"},{line,377}]},
{rabbit_amqp1_0_session_process,handle_control,2,
[{file,"src/rabbit_amqp1_0_session_process.erl"},{line,197}]},
{rabbit_amqp1_0_session_process,handle_cast,2,
[{file,"src/rabbit_amqp1_0_session_process.erl"},{line,134}]},
{gen_server2,handle_msg,2,[{file,"src/gen_server2.erl"},{line,1049}]},
{proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,240}]}]]}}
*
I have enabled amqp_1_0 plugin in rabbitmq.
Can someone help me resolve this.
This seems a bug in rabbitmq amqp 1.0 plugin. An issue has been logged with rabbitmq.
https://github.com/rabbitmq/rabbitmq-amqp1.0/issues/31
Related
Java Spring Stomp AMQP
I have three project: Javascript SockJS STOMP client Spring-boot STOMP endpoint and AMQP Spring-boot AMQP (RabbitListener) client for testing I am using RabbitMQ message broker (+Stomp plugin) and configured amqp and stomp endpoint normally..When I send message to queue with RabbitTemplate and third project (spring-boot amqp client for testing) normally subscribed this message , everything works fine !! But Javascript STOMP client didn't received this message.. P.S. When I send message with SimpMessagingTemplate , JS client receives message fine ! Javascript SockJS STOMP Client var socket = new SockJS('http://localhost:8090/hello'); stompClient = Stomp.over(socket); stompClient.connect('guest','guest', function(frame) { setConnected(true); console.log('Connected: ' + frame); stompClient.subscribe('/topic/testqueue', function(greeting){ showGreeting(JSON.parse(greeting.body).content); }); }); spring-boot STOMP endpoint and AMQP #Controller public class SampleController { Logger logger = Logger.getLogger(SampleController.class); #Autowired private RabbitTemplate rabbitTemplate; private SimpMessagingTemplate messagingTemplate; #Autowired public SampleController(SimpMessagingTemplate messagingTemplate) { this.messagingTemplate = messagingTemplate; } #GetMapping("/emit/{message}") #ResponseBody String queue1(#PathVariable("message") String message) throws Exception { logger.info("Emit to testqueue"); rabbitTemplate.convertAndSend("/topic/testqueue", new Greeting("Salam olsun " + message)); Thread.sleep(60000); // simulated delay return "Emit to testqueue"; } } spring-boot amqp client for testing #Component public class RabbitMqListener { Logger logger = Logger.getLogger(RabbitMqListener.class); #RabbitListener(queues = "/topic/testqueue") public void processQueue1(String message) { logger.info("Received from queue : " + message); } } How I can mix amqp and stomp protocols in RabbitMQ ? I want to send message from another project with amqp protocol (RabbitTemplate) and receive this message from JS STOMP client (SockJS) .. Thanks.
I was changed rabbitTemplate.convertAndSend("/topic/testqueue", ...) to rabbitTemplate.convertAndSend("amq.topic","testqueue" ...) and everythink works fine ))) Especially thanks to Artem Bilan for support. Good Luck
Spring AMQP Inbound Adapter with empty queue name
I'm developing a consumer application using Spring AMQP that receives messages from RabbitMQ. There is a topic exchange declared. To connect to Rabbit I create a queue with an empty name, because the broker will provide an automatic queue name, see the InterCor M4 Upgraded Specifications Hybrid specifications: #Bean public TopicExchange exchange() { TopicExchange topicExchange = new TopicExchange(topicExchangeName); topicExchange.setShouldDeclare(false); return topicExchange; } #Bean public Queue queue() { return new Queue("", queueDurable, queueExclusive, queueAutoDelete, queueParameters); } #Bean public Binding binding(Queue queue, TopicExchange exchange) { return BindingBuilder.bind(queue).to(exchange).with(routingKey); } But when I try to configure an AMQP Inbound Channel Adapter using the Spring Integration Java DSL: #Autowired private Queue queue; #Bean public IntegrationFlow amqpInbound(ConnectionFactory connectionFactory) { return IntegrationFlows.from(Amqp.inboundAdapter(connectionFactory, queue)) .handle(m -> System.out.println(m.getPayload())) .get(); } I get an error 'queueName' cannot be null or empty 2018-05-25 13:39:15.080 ERROR 14636 --- [erContainer#0-1] o.s.a.r.l.SimpleMessageListenerContainer : Failed to check/redeclare auto-delete queue(s). java.lang.IllegalArgumentException: 'queueName' cannot be null or empty at org.springframework.util.Assert.hasText(Assert.java:276) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE] at org.springframework.amqp.rabbit.core.RabbitAdmin.getQueueProperties(RabbitAdmin.java:337) ~[spring-rabbit-2.0.3.RELEASE.jar:2.0.3.RELEASE] at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.redeclareElementsIfNecessary(AbstractMessageListenerContainer.java:1604) ~[spring-rabbit-2.0.3.RELEASE.jar:2.0.3.RELEASE] at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:963) [spring-rabbit-2.0.3.RELEASE.jar:2.0.3.RELEASE] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_162] How can I set a value of the message queue name to an empty string?
That is not a good solution. The problem is that with a broker-generated queue name, if the connection is lost and re-established, the queue name will change, but the container won't know about the new queue and will try to consume from the old one. AnonymousQueue solves this problem by the framework generating the random name. But, anonymous queues are not durable, are exclusive and are auto-delete. If you want a Queue with different properties to that, but still want a random name, use #Bean public Queue queue() { return new Queue(new AnonymousQueue.Base64UrlNamingStrategy().generateName(), queueDurable, queueExclusive, queueAutoDelete, queueParameters); } That way, if the connection is lost and re-established, the queue will get the same name.
The AMQP-816 issue has been fixed and now is available in Spring Boot 2.1.0. Updating the parent of the project fixes the issue: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> </parent> Empty queue name spring: rabbitmq: queue: name: durable: false exclusive: true autoDelete: true creates an automatic queue name amq.gen-U1vKiSfIvy8bO11jLD29Sw: Non-empty queue name spring: rabbitmq: queue: name: abc durable: false exclusive: true autoDelete: true creates a queue named abc:
Spring AMQP client hangs
There is a behavior in RabbitMQ server that it will not accept subsequent connections / operations when it reaches to watermark value till the time it rebalances itself. RabbitMQ client elegantly gets timeout when such situations happen after the connection timeout , But we are using Spring AMQP it continues to hang. Steps to Reproduce o Create a RabbitMQ HA cluster o Create a simple program which produces and consumes message a) Using Spring AMQP b) Using RabbitMQ client o Make RabbitMQ server reach high watermark value in memory so that it cannot accept any new connections or perform any operations say for 10 min o Create Q, Send message from a) Spring AMQP ( It will hang ) b) RabbitMQ client ( It will get timeout ) say after 1 min if connection timeout is being set as 1 min. Spring Binaries Version a) spring-rabbit-1.6.7.RELEASE.jar b) spring-core-4.3.6.RELEASE.jar c) spring-amqp-1.6.7.RELEASE.jar We tried upgrading to Spring Rabbit and AMQP 2.0.2 version as well , But it didn’t helped.
You don't describe what your "RabbitMQ Client" is, but the java amqp-client uses classic Sockets by default. So you should get the same behavior with both (since Spring AMQP uses that client). Perhaps you are referring to some other language client. With java Sockets, when the connection is blocked, the thread is "stuck" in socket write which is not interruptible, nor does it timeout. To handle this condition, you have to use the 4.0 client or above and use NIO. Here is an example application that demonstrates the technique. #SpringBootApplication public class So48699178Application { private static Logger logger = LoggerFactory.getLogger(So48699178Application.class); public static void main(String[] args) { SpringApplication.run(So48699178Application.class, args); } #Bean public ApplicationRunner runner(RabbitTemplate template, CachingConnectionFactory ccf) { ConnectionFactory cf = ccf.getRabbitConnectionFactory(); NioParams nioParams = new NioParams(); nioParams.setWriteEnqueuingTimeoutInMs(20_000); cf.setNioParams(nioParams); cf.useNio(); return args -> { Message message = MessageBuilder.withBody(new byte[100_000]) .andProperties(MessagePropertiesBuilder.newInstance() .setDeliveryMode(MessageDeliveryMode.NON_PERSISTENT) .build()) .build(); while (true) { try { template.send("foo", message); } catch (Exception e) { logger.info(e.getMessage()); } } }; } #Bean public Queue foo() { return new Queue("foo"); } } and 2018-02-09 12:00:29.803 INFO 9430 --- [ main] com.example.So48699178Application : java.io.IOException: Frame enqueuing failed 2018-02-09 12:00:49.803 INFO 9430 --- [ main] com.example.So48699178Application : java.io.IOException: Frame enqueuing failed 2018-02-09 12:01:09.807 INFO 9430 --- [ main] com.example.So48699178Application : java.io.IOException: Frame enqueuing failed
Delay message to send to listener using Spring AMQP
I have a requirement to send message to MessageListener after certain duration , So is there any way to achieve using Spring AMQP. Eg . Producer produces the message and message goes to RabbitMQ Q , The message gets received Listener listening to that Q immediately, I want to delay that message to be received at consumer side say after some configuration parameter say 1000ms
The RabbitMQ provides for this purpose Delayed Exchange feature. Starting with version 1.6 Spring AMQP also provides a high level API on the matter: http://docs.spring.io/spring-amqp/reference/html/_reference.html#delayed-message-exchange: <rabbit:topic-exchange name="topic" delayed="true" /> MessageProperties properties = new MessageProperties(); properties.setDelay(15000); template.send(exchange, routingKey, MessageBuilder.withBody("foo".getBytes()).andProperties(properties).build()); UPDATE Before Spring AMQP 1.6 you should do like this: #Bean CustomExchange delayExchange() { Map<String, Object> args = new HashMap<String, Object>(); args.put("x-delayed-type", "direct"); return new CustomExchange("my-exchange", "x-delayed-message", true, false, args); } ... MessageProperties properties = new MessageProperties(); properties.setHeader("x-delay", 15000); template.send(exchange, routingKey, MessageBuilder.withBody("foo".getBytes()).andProperties(properties).build()); Also see this question and its answer: Scheduled/Delay messaging in Spring AMQP RabbitMq
If you use spring boot, it can be like this: #Bean Queue queue() { return QueueBuilder.durable(queueName) .withArgument("x-dead-letter-exchange", dlx) .withArgument("x-dead-letter-routing-key", dlq) .build(); } #Bean TopicExchange exchange() { return (TopicExchange) ExchangeBuilder.topicExchange(topicExchangeName) .delayed() .build(); #Bean Binding binding() { return BindingBuilder.bind(queue()).to(exchange()).with(queueName); }
ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN
I have installed "erlang" and "rabbitmq" in my windows 7 machine. But when I am trying to run this code I am getting One exception. package com.rabbitmq; import com.rabbitmq.client.Channel; import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; public class SendMessage { private final static String QUEUE_NAME = "hello"; public static void main(String[] argv) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); String message = "Hello World!"; channel.basicPublish("", QUEUE_NAME, null, message.getBytes("UTF-8")); System.out.println(" [x] Sent '" + message + "'"); channel.close(); connection.close(); } } I am getting this Exception. Exception in thread "main" com.rabbitmq.client.AuthenticationFailureException: ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN. For details see the broker logfile. This is the log: 11-Apr-2016::12:45:06 === Adding vhost 'localhost' =INFO REPORT==== 11-Apr-2016::14:08:52 === accepting AMQP connection <0.360.0> (127.0.0.1:55327 -> 127.0.0.1:5672) =ERROR REPORT==== 11-Apr-2016::14:08:52 === Error on AMQP connection <0.360.0> (127.0.0.1:55327 -> 127.0.0.1:5672, state: starting): =INFO REPORT==== 11-Apr-2016::14:08:52 === closing AMQP connection <0.360.0> (127.0.0.1:55327 -> 127.0.0.1:5672) When I am trying to list the users I am not getting any existing user and add_user is also not working in cmd link
In your ConnectionFactory you need to set your username and password, if your have created any or you can use the default user "guest" with password "guest", which can be accessible only from localhost.
you can create new user (userA) and password (userA123). And set factory.setHost("your_pc_ip"); factory.setUsername("userA"); factory.setPassword("userA123"); in sender and receiver classes.