简体   繁体   English

将动态创建的队列添加到侦听器 RabbitMq Spring

[英]Adding Dynamically created queues to a listener RabbitMq Spring

I am creating a Web Application for events-planners to better manage their events.我正在为活动策划者创建一个 Web 应用程序,以更好地管理他们的活动。 Each event they create needs a queue which means the app needs to create a queue when an event is created.他们创建的每个事件都需要一个队列,这意味着应用程序需要在创建事件时创建一个队列。 So far I have been able to create the queues and they appear in the rabbitmq management console but when I try to add a queue to a listener it brings this error: java.lang.NullPointerException: Cannot invoke "org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.addQueueNames(String[])" because the return value of "co.ke.mpango.backend.config.webSocket.RabbitQueueServiceImpl.getMessageListenerContainerById Here is the code:到目前为止,我已经能够创建队列,它们出现在 rabbitmq 管理控制台中,但是当我尝试向侦听器添加队列时,它会带来此错误: java.lang.NullPointerException: Cannot invoke "org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.addQueueNames(String[])" because the return value of "co.ke.mpango.backend.config.webSocket.RabbitQueueServiceImpl.getMessageListenerContainerById这里是代码:

@Service @Log4j2 public class RabbitQueueServiceImpl implements RabbitQueueService { @Autowired private RabbitAdmin rabbitAdmin; @Autowired private RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry; @Override public void addNewQueue(String queueName, String exchangeName, String routingKey) { Queue queue = new Queue(queueName, true, false, false); Binding binding = new Binding( queueName, Binding.DestinationType.QUEUE, exchangeName, routingKey, null ); rabbitAdmin.declareQueue(queue); rabbitAdmin.declareBinding(binding); this.addQueueToListener(exchangeName,queueName); } @Override public void addQueueToListener(String listenerId, String queueName) { log.info("adding queue : " + queueName + " to listener with id : " + listenerId); if (!checkQueueExistOnListener(listenerId,queueName)) { this.getMessageListenerContainerById(listenerId).addQueueNames(queueName); log.info("queue "); } else { log.info("given queue name : " + queueName + " not exist on given listener id : " + listenerId); } } @Override public void removeQueueFromListener(String listenerId, String queueName) { log.info("removing queue : " + queueName + " from listener : " + listenerId); if (checkQueueExistOnListener(listenerId,queueName)) { this.getMessageListenerContainerById(listenerId).removeQueueNames(queueName); log.info("deleting queue from rabbit management"); this.rabbitAdmin.deleteQueue(queueName); } else { log.info("given queue name : " + queueName + " not exist on given listener id : " + listenerId); } } @Override public Boolean checkQueueExistOnListener(String listenerId, String queueName) { try { log.info("checking queueName : " + queueName + " exist on listener id : " + listenerId); log.info("getting queueNames"); String[] queueNames = this.getMessageListenerContainerById(listenerId).getQueueNames(); if (queueNames != null) { log.info("checking " + queueName + " exist on active queues"); for (String name : queueNames) { log.info("name : " + name + " with checking name : " + queueName); if (name.equals(queueName)) { log.info("queue name exist on listener, returning true"); return Boolean.TRUE; } } return Boolean.FALSE; } else { log.info("there is no queue exist on listener"); return Boolean.FALSE; } } catch (Exception e) { log.error("Error on checking queue exist on listener"); return Boolean.FALSE; } } private AbstractMessageListenerContainer getMessageListenerContainerById(String listenerId) { log.info("getting message listener container by id : " + listenerId); return ((AbstractMessageListenerContainer) this.rabbitListenerEndpointRegistry .getListenerContainer(listenerId) ); } }

Added: How could then one listener be defined?补充:那么怎么定义一个监听器呢?

RabbitListenerEndpointRegistry class is storage for all listener containers( SimpleRabbitListenerContainer , DirectRabbitListenerContainer ) and for managing their life cycle. RabbitListenerEndpointRegistry class 是所有侦听器容器( SimpleRabbitListenerContainerDirectRabbitListenerContainer )和管理它们的生命周期的存储。 Before taking MessageListenerContainer from RabbitListenerEndpointRegistry you need to register this container inside the registry like this:在从RabbitListenerEndpointRegistry获取MessageListenerContainer之前,您需要像这样在注册表中注册此容器:

SimpleRabbitListenerEndpoint endpoint = new SimpleRabbitListenerEndpoint();
endpoint.setId(LISTENER_CONTAINER_ID);
endpoint.setMessageListener(message -> {
        RabbitMQMessage<QueueItem> rabbitMQMessage = (RabbitMQMessage<QueueItem>) SerializationUtils.deserialize(message.getBody());
        rabbitMQService.onMessage(rabbitMQMessage); //method where your message will be processed
});

//listenerContainerFactory is instance of DirectRabbitListenerContainerFactory or SimpleRabbitListenerContainerFactory
registry.registerListenerContainer(endpoint, listenerContainerFactory, true);

//start the registry if it is created manually
//registry.start();

and then you can take that container from registry by LISTENER_CONTAINER_ID然后您可以通过LISTENER_CONTAINER_ID从注册表中获取该容器

registry.getListenerContainer(LISTENER_CONTAINER_ID);

To manage dynamic queues it is better to use DirectMessageListenerContainer , this container will open a separate channel for each queue without restarting the container like SimpleRabbitListenerContainer does after adding a new queue and it will take some time until SimpleRabbitListenerContainer will be ready to receive messages from the queues.要管理动态队列,最好使用DirectMessageListenerContainer ,此容器将为每个队列打开一个单独的通道,而无需像SimpleRabbitListenerContainer添加新队列后那样重新启动容器,并且SimpleRabbitListenerContainer准备好从队列接收消息需要一些时间.

See more differences here: https://docs.spring.io/spring-amqp/reference/html/#choose-container在此处查看更多差异: https://docs.spring.io/spring-amqp/reference/html/#choose-container

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM