[英]How to fix error “Only one ConfirmCallback is supported by each RabbitTemplate” on subsequent requests
I am new to RabbitMQ and currently working on RabbitMQ publish confirms acknowledgments in my web application. 我是RabbitMQ的新手,目前正在RabbitMQ上进行发布,以确认我的Web应用程序中的确认。 On every new request, sending message to RabbitMQ server to process it asynchronously and also enabled confirms to get acknowledgments from the RMQ server.
在每个新请求上,都将消息发送到RabbitMQ服务器以异步处理它,并且还启用确认以从RMQ服务器获得确认。
When trying in local, on the first request it is fine but on subsequent requests, getting following error "Only one ConfirmCallback is supported by each RabbitTemplate". 在本地尝试时,在第一个请求上很好,但在随后的请求上,出现以下错误“每个RabbitTemplate仅支持一个ConfirmCallback”。
After some research, if I add a check (template.isConfirmListener()) before setting confirm callback, not getting error. 经过一番研究,如果我在设置确认回调之前添加了一个检查(template.isConfirmListener()),不会出错。 But how can we override Confirm Callbacks for different requests if required?
但是,如果需要,我们如何覆盖针对不同请求的确认回调? Is this expected behaviour or am I am doing anything wrong here?
这是预期的行为还是我在这里做错了什么?
Environment: 环境:
Please find the code as below. 请找到下面的代码。
Controller file 控制器文件
package com.example.apis;
import java.util.UUID;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.core.RabbitTemplate.ConfirmCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ProducerController {
@Autowired
private RabbitTemplate template;
private String exchange = "test";
private String routingKey = "test";
@GetMapping("/send")
@ResponseBody
public String sendRequestToRMQ() {
template.convertAndSend(exchange, routingKey, "Test Message", getCorrelationData());
template.setMandatory(true);
template.setConfirmCallback(new ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println("Confirm Callback!");
System.out.println(correlationData.getId());
System.out.println(ack);
}
});
return "Success";
}
@GetMapping("/send1")
@ResponseBody
public String sendRequestToRMQ2() {
template.convertAndSend(exchange, routingKey, "Test Message", getCorrelationData());
template.setMandatory(true);
template.setConfirmCallback(new ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
System.out.println("Confirm Callback!");
System.out.println(correlationData.getId());
System.out.println(ack);
}
});
return "Success";
}
private CorrelationData getCorrelationData() {
return new CorrelationData(UUID.randomUUID().toString());
}
}
Configuration file 配置文件
package com.example.conf;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConnectionConfig {
@Value("${spring.rabbitmq.host:localhost}")
public String host;
@Value("${spring.rabbitmq.port:5672}")
public int port;
@Value("${spring.rabbitmq.username:guest}")
public String username;
@Value("${spring.rabbitmq.password:guest}")
public String password;
@Value("${spring.rabbitmq.virtual-host:/}")
public String virtualHost;
@Bean
public ConnectionFactory getConnectionFactory(){
CachingConnectionFactory factory=new CachingConnectionFactory();
factory.setHost(host);
factory.setPort(port);
factory.setUsername(username);
factory.setPassword(password);
factory.setVirtualHost(virtualHost);
factory.setPublisherConfirms(true);
factory.setPublisherReturns(true);
return factory;
}
}
Please help me. 请帮我。 Thanks
谢谢
No, it is expected behavior: only one ConfirmCallback
can be injected into the RabbitTemplate
. 不,这是预期的行为:只能将一个
ConfirmCallback
注入RabbitTemplate
。 You need consider to do that only once, somewhere in the @PostConstrcut
, but not for every single request. 您只需要考虑在
@PostConstrcut
某个位置执行一次此操作,而不是针对每个单个请求执行一次。 Of course, you might need to revise your logic since now a ConfirmCallback
is going to be shared for all the request initiated into RabbitTemplate
. 当然,您可能需要修改逻辑,因为现在将对所有初始化到
RabbitTemplate
的请求共享一个ConfirmCallback
。
You may consider some smart logic in your common ConfirmCallback
to store request in the map based on the getCorrelationData()
and restore that entry from the callback method. 您可以在常见的
ConfirmCallback
考虑一些智能逻辑,以基于getCorrelationData()
将请求存储在映射中,并从回调方法中还原该条目。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.