当前位置: 首页 > news >正文

Listener method could not be invoked with the incoming message

问题描述

  生产者方代码:

    private void rollbackOrder(long orderId, CorrelationData correlationData) {rabbitTemplate.convertAndSend("order-rollback-exchange","rollback.order",new QuotaRollbackTO(orderId,null,null),correlationData);}

  消费者方代码:

    @RabbitListener(queues = "rollback.order.queue")public void handleRollback(QuotaRollbackTO quotaRollbackTO, Message message, Channel channel) throws Exception {try {//回滚订单的逻辑orderMainMapper.deleteById(quotaRollbackTO.getOrderId());orderProductMapper.deleteById(quotaRollbackTO.getOrderId());// 手动ACKchannel.basicAck(message.getMessageProperties().getDeliveryTag(), false);} catch (Exception e) {System.err.println("消息处理失败:" + e.getMessage());// 拒绝消息并转入死信队列channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);}}

  Rabbit MQ发送消息报错:

org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener method could not be invoked with the incoming message
Endpoint handler details:
Method [public void org.ragdollcat.order.mqlistener.OrderMQListener.handleRollback(org.ragdollcat.order.to.QuotaRollbackTO,org.springframework.amqp.core.Message,com.rabbitmq.client.Channel) throws java.lang.Exception]


原因分析:

  由于未配置 RabbitMQ 使用 JSON 消息转换器,Spring Boot 默认采用了 SimpleMessageConverter,导致无法将 JSON 数据反序列化为 QuotaRollbackTO 对象,从而造成监听方法调用失败。在错误信息中,可能会发现以下提示:

Caused by: org.springframework.messaging.converter.MessageConversionException: Cannot convert from [[B] to [org.ragdollcat.order.to.QuotaRollbackTO] for GenericMessage [payload=byte[234], headers={amqp_receivedDeliveryMode=PERSISTENT, amqp_receivedRoutingKey=rollback.order, spring_listener_return_correlation=4e708ed8-bfde-4f43-9282-4701c1b5ef19, amqp_receivedExchange=order-rollback-exchange, spring_returned_message_correlation=4591a034-2ee5-4d4c-8a3c-4c95a3b43572, amqp_deliveryTag=1, amqp_consumerQueue=rollback.order.queue, amqp_redelivered=false, id=58a03a74-a8d4-329c-7d26-c229977f4c15, amqp_consumerTag=amq.ctag-0deI5Ts_m6_K32RdEYyDZA, contentType=application/x-java-serialized-object, timestamp=1747560067493}]

  证实了发送端把对象以JDK默认方式(ObjectOutputStream)序列化成 byte[],接收端尝试用 JSON 的方式将这个 byte[] 解析成 QuotaRollbackTO,失败。


解决方案:

  在配置类中,显式使用 JSON 消息转换器,为 RabbitTemplate 设置 Jackson2JsonMessageConverter(或放在Spring Boot的引导类中也可以,引导类本身也是作为一个配置类),这样后续注入的就是自定义的RabbitTemplate

@Configuration
public class RabbitTemplateConfig {@Beanpublic MessageConverter messageConverter() {return new Jackson2JsonMessageConverter();}@Beanpublic RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory,MessageConverter jacksonMessageConverter) {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);// 开启强制投递,必须配置这个 ReturnCallback 才会生效!rabbitTemplate.setMandatory(true);// 设置 ConfirmCallbackrabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {if (ack) {System.out.println(" 交换机已收到消息:" + correlationData);} else {System.err.println(" 交换机未收到消息:" + cause + ",相关数据:" + correlationData);}});// 设置 ReturnCallbackrabbitTemplate.setReturnCallback((message, replyCode, replyText, exchange, routingKey) -> {System.err.println(" 消息未成功路由到队列:");System.err.println("  原始消息:" + new String(message.getBody()));System.err.println("  应答码:" + replyCode);System.err.println("  原因:" + replyText);System.err.println("  交换机:" + exchange);System.err.println("  路由键:" + routingKey);});//为 RabbitTemplate 设置 `Jackson2JsonMessageConverter`rabbitTemplate.setMessageConverter(jacksonMessageConverter);return rabbitTemplate;}@Beanpublic SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory,MessageConverter jacksonMessageConverter) {SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();factory.setConnectionFactory(connectionFactory);factory.setMessageConverter(jacksonMessageConverter);return factory;}}

  同样地在发送消息时,不应采用对象转换为JSON字符串的写法:

rabbitTemplate.convertAndSend("rollback.order", JSON.toJSONString(rollbackTO));

验证方式:

  临时打印发送内容 headers:

rabbitTemplate.setReturnsCallback(returned -> {Message returnedMessage = returned.getMessage();System.out.println("发送内容类型: " + returnedMessage.getMessageProperties().getContentType());
});

  看到的 contentType 应该是:

“application/json”

http://www.xdnf.cn/news/519445.html

相关文章:

  • 《C++与OpenCV实战:图像增强大核心算法详解》​​
  • [ctfshow web入门] web122
  • Git目录分析与第一个git commit文件
  • 20倍云台球机是一种高性能的监控设备
  • PortSwigger Labs CSRF详细教程
  • C++学习:六个月从基础到就业——C++17:string_view与filesystem
  • Vue3前端xlsx导出
  • 微服务项目->在线oj系统(Java版 - 3)
  • 王树森推荐系统公开课 排序02:Multi-gate Mixture-of-Experts (MMoE)
  • 【AI面试秘籍】| 第15期:大模型如何稳定输出合法JSON?
  • 【Linux笔记】——线程同步条件变量与生产者消费者模型的实现
  • GEE谷歌地球引擎批量下载逐日ERA5气象数据的方法
  • 等于和绝对等于的区别
  • LeetCode 394. 字符串解码详解:Java栈实现与逐行解析
  • 第5章 监控与回归测试:日志收集 · 代码覆盖率 · 静态分析 · 质量门
  • Python爬虫实战:通过PyExecJS库实现逆向解密
  • 院士方复全数学命题证明采用预期理由和循环论证以及类比的错误方法
  • web页面布局基础
  • 【动态规划】路径问题
  • STM32八股【9】-----volatile关键字
  • vim - v
  • Python数据可视化 - Pyecharts绘图示例
  • 中级统计师-统计学基础知识-第三章 参数估计
  • 【Linux】命令行参数和环境变量
  • 【PyQt5实战】五大对话框控件详解:从文件选择到消息弹窗
  • 【typenum】 11 私有模块(private.rs)
  • 【Redis实战篇】Redis消息队列
  • 10.9 LangChain LCEL革命:43%性能提升+声明式语法,AI开发效率飙升实战指南
  • 深入理解递归算法:Go语言实现指南
  • C44-练习