I have a Spring Boot application which has problems retrieving JMS messages of type TextMessage
from an ActiveMQ broker.
If the consumer tries to retrieve messages from the broker it cannot automatically convert a message to TextMessage but treats it as ByteMessage. There is a JmsListener which should read the messages from the queue as TextMessage:
...
@JmsListener(destination = "foo")
public void jmsConsumer(TextMessage message) {
...
The JmsListener
produces warnings like the following, and drops the messages:
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]
I have extracted a small sample application to debug the problem: https://github.com/ascheman/springboot-camel-jms
The producer in real life is a commercial application which makes use of Apache Camel. Hence, I can hardly change/customize the producer. I have tried to build a sample producer which shows the same behavior.
Could I somehow tweak the consumer to treat the message as TextMessage
?
Besides: Is there any way to retrieve the additional AMQP properties from the message programmatically directly in Spring? Of course, I could still read the message as ByteMessage
and try to parse properties away. But I am looking for a cleaner way which is backed by any Spring API. The Spring @Headers
annotation didn't help so far.
byte[]
and that by default gets converted to aByteMessage
. I would suggest to either just receive thebyte[]
and not message with specific JMS typed messages. TryString
instead ofTextMessage
. Properties aren't headers (AFAIK) so not sure where they get mapped to in this scenario. If you really want to use aTextMessage
write a custom message converter to convert abyte[]
into aTextMessage
. – M. Deinumbyte[]
contents as well as aString
. However, in this case the message also contains some additional data - so called properties (check out the mentioned AMQP spec. for details). I am interested in the genuine text message which was originally sent by the producer. I would not like to parse it from thebyte[]
orString
object myself. I expect to get a correct JMS object if the used transport is JMS compatible, not a number of bytes which I need to handle myself. – Gerd AschemannTextMessage
will get converted to something that AMQP understands, which if you look at the Java API is abyte[]
. Fact is you aren't using JMS but rather AMQP which you try to shoehorn into JMS. Why not simply use AMQP instead? – M. DeinumMessage<?>
instead, which is a spring-messaging abstraction over multiple transports (including JMS). It has apayload
andheaders
(which are mapped from the JMS message). – Gary Russellnative
mapping being used rather than the desiredjms
mapping. See activemq.apache.org/amqp.html for details on the various mapping options. – Andy Wilkinson