【发布时间】:2019-06-22 12:26:43
【问题描述】:
我有一个 Spring Boot 应用程序,它在从 ActiveMQ 代理检索 TextMessage 类型的 JMS 消息时遇到问题。
如果消费者尝试从代理检索消息,它不能自动将消息转换为 TextMessage,而是将其视为 ByteMessage。有一个 JmsListener 应该将队列中的消息作为 TextMessage 读取:
...
@JmsListener(destination = "foo")
public void jmsConsumer(TextMessage message) {
...
JmsListener 产生如下警告,并丢弃消息:
org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method could not be invoked with incoming message
Endpoint handler details:
Method [public void net.aschemann.demo.springboot.jmsconsumer.JmsConsumer.jmsConsumer(javax.jms.TextMessage)]
Bean [net.aschemann.demo.springboot.jmsconsumer.JmsConsumer@4715f07]; nested exception is org.springframework.messaging.converter.MessageConversionException: Cannot convert from [[B] to [javax.jms.TextMessage] for org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@7c49d298, failedMessage=org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@7c49d298
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:118) ~[spring-jms-5.1.4.RELEASE.jar:5.1.4.RELEASE]
我提取了一个小示例应用程序 调试问题:https://github.com/ascheman/springboot-camel-jms
现实生活中的生产者是一个使用 Apache Camel 的商业应用程序。因此,我几乎无法更改/自定义生产者。我试图构建一个显示相同行为的示例生产者。
我能否以某种方式调整消费者以将消息视为TextMessage?
另外:有什么方法可以直接在 Spring 中以编程方式从消息中检索附加的 AMQP 属性?当然,我仍然可以将消息读取为ByteMessage 并尝试解析属性。但我正在寻找一种由任何 Spring API 支持的更清洁的方式。到目前为止,Spring @Headers 注释没有帮助。
【问题讨论】:
-
您收到的是
byte[],默认情况下会转换为ByteMessage。我建议要么只接收byte[],而不是接收带有特定 JMS 类型消息的消息。尝试String而不是TextMessage。属性不是标题(AFAIK),因此不确定在这种情况下它们被映射到哪里。如果您真的想使用TextMessage,请编写自定义消息转换器将byte[]转换为TextMessage。 -
谢谢,但问题不在于更改类型:我可以获得
byte[]的内容以及String。但是,在这种情况下,消息还包含一些额外的数据 - 所谓的属性(查看提到的 AMQP 规范以获取详细信息)。我对制作人最初发送的正版短信感兴趣。我不想自己从byte[]或String对象中解析它。如果使用的传输与 JMS 兼容,我希望得到一个正确的 JMS 对象,而不是我需要自己处理的字节数。 -
但是您没有使用 JMS 作为传输,这是您使用 AMQP 时的主要问题。您基本上是通过 AMQP(与 JMS 不同)为 JMS 建立隧道。因此消息被改编,
TextMessage将被转换为 AMQP 可以理解的东西,如果你查看 Java API 就是byte[]。事实上,您使用的不是 JMS,而是 AMQP,您试图将其硬塞到 JMS 中。为什么不直接使用 AMQP? -
这真的是 AMQP,还是 ActiveMQ (AMQ)?您可以接收
Message<?>,它是对多个传输(包括 JMS)的弹簧消息传递抽象。它有一个payload和headers(从JMS 消息映射)。 -
为了避免人们浪费时间,这个问题也被cross-posted 作为 Spring Boot 问题。我怀疑这是使用默认
native映射而不是所需的jms映射的代理配置问题。有关各种映射选项的详细信息,请参阅activemq.apache.org/amqp.html。
标签: java spring spring-boot activemq spring-jms