[英]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 是所有侦听器容器( SimpleRabbitListenerContainer
, DirectRabbitListenerContainer
)和管理它们的生命周期的存储。 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.