I am looking at using JmsMessagingTemplate
instead of JmsTemplate
because I would like to use convertSendAndReceive
. The messages should be send in JSON format. I am having difficulties convincing JmsMessagingTemplate
to use MappingJackson2MessageConverter
instead of the SimpleMessageConverter
. The documentation seems to indicate that having a bean for MappingJackson2MessageConverter
is enough to have it been used.
I created a small reproducing project. Given the following files:
// pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <name>demo</name> <description>Demo project for Spring Boot</description> <properties> <java.version>15</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
// Payload.java package com.example.demo; public class Payload { public String value; public Payload(String v) { value = v; } public Payload() {} } // Listener.java package com.example.demo; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; import javax.jms.JMSException; import javax.jms.Message; @Component public class Listener { @JmsListener(destination = "my-topic") public String listen(Message msg) throws JMSException { System.out.println(msg.getJMSDestination().toString()); return "reply"; } } // Sender.java package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.event.EventListener; import org.springframework.jms.core.JmsMessagingTemplate; import org.springframework.stereotype.Component; @Component public class Sender { @Autowired JmsMessagingTemplate jms; @EventListener(ApplicationReadyEvent.class) public void send() { final var result = jms.convertSendAndReceive("my-topic", new Payload("hello"), String.class); System.out.println(result); } } // Config.java package com.example.demo; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.converter.MappingJackson2MessageConverter; @Configuration public class Config { @Bean MappingJackson2MessageConverter messageConverter() { return new MappingJackson2MessageConverter(); } }
I get the following exception:
org.springframework.messaging.converter.MessageConversionException: Could not convert 'GenericMessage [payload=com.example.demo.Payload@5f8dd865, headers={id=d39f719b-4120-ceb1-a2ea-6468aeed5e13, timestamp=1639682065670}]'; nested exception is org.springframework.jms.support.converter.MessageConversionException: Cannot convert object of type [com.example.demo.Payload] to JMS message. Supported message payloads are: String, byte array, Map<String,?>, Serializable object. at org.springframework.jms.core.JmsMessagingTemplate$MessagingMessageCreator.createMessage(JmsMessagingTemplate.java:476) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsTemplate.doSendAndReceive(JmsTemplate.java:915) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsTemplate.lambda$sendAndReceive$11(JmsTemplate.java:896) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsTemplate.executeLocal(JmsTemplate.java:954) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsTemplate.sendAndReceive(JmsTemplate.java:894) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsMessagingTemplate.doSendAndReceive(JmsMessagingTemplate.java:411) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsMessagingTemplate.sendAndReceive(JmsMessagingTemplate.java:297) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsMessagingTemplate.convertSendAndReceive(JmsMessagingTemplate.java:349) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsMessagingTemplate.convertSendAndReceive(JmsMessagingTemplate.java:319) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsMessagingTemplate.convertSendAndReceive(JmsMessagingTemplate.java:305) ~[spring-jms-5.3.13.jar:5.3.13] at com.example.demo.Sender.send(Sender.java:16) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na] at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:344) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:229) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:166) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.boot.context.event.EventPublishingRunListener.ready(EventPublishingRunListener.java:114) ~[spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplicationRunListeners.lambda$ready$6(SpringApplicationRunListeners.java:82) ~[spring-boot-2.6.1.jar:2.6.1] at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) ~[na:na] at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120) ~[spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114) ~[spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplicationRunListeners.ready(SpringApplicationRunListeners.java:82) ~[spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:317) ~[spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[spring-boot-2.6.1.jar:2.6.1] at com.example.demo.DemoApplication.main(DemoApplication.java:10) ~[classes/:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na] at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:563) ~[na:na] at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na] Caused by: org.springframework.jms.support.converter.MessageConversionException: Cannot convert object of type [com.example.demo.Payload] to JMS message. Supported message payloads are: String, byte array, Map<String,?>, Serializable object. at org.springframework.jms.support.converter.SimpleMessageConverter.toMessage(SimpleMessageConverter.java:79) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.support.converter.MessagingMessageConverter.createMessageForPayload(MessagingMessageConverter.java:144) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.support.converter.MessagingMessageConverter.toMessage(MessagingMessageConverter.java:111) ~[spring-jms-5.3.13.jar:5.3.13] at org.springframework.jms.core.JmsMessagingTemplate$MessagingMessageCreator.createMessage(JmsMessagingTemplate.java:473) ~[spring-jms-5.3.13.jar:5.3.13] ... 38 common frames omitted
Debugging the JmsMessagingTemplate
I end up in AbstractMessageSendingTemplate
where the message converter is of type SimpleMessageConverter
in stead of the expected MappingJackson2MessageConverter
.
I hope someone can show me the missing configuration or relevant docs.
Advertisement
Answer
You’re not setting the MessageConverter to the jmsMessagingTemplate
bean that you’re using. You need to set the message converter using setJmsMessageConverter()
method before calling convertSendAndReceive()
.