Skip to content
Advertisement

How to configure JmsMessagingTemplate to use MappingJackson2MessageConverter

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().

Here’s the javadocs – https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/jms/core/JmsMessagingTemplate.html#setJmsMessageConverter-org.springframework.jms.support.converter.MessageConverter-

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement