Hello,

In the following exemple, JmsMessageConverter.toMessage is called before the message is send, but the JmsMessageConverter.fromMessage is not called when the message is recevied.

import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.Session;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.connection.CachingConnectionFactory;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.converter.MessageConversionException;
import org.springframework.jms.support.converter.SimpleMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableJms
public class ActivemqMessageConverterApplication {

    public static void main(String[] args) {
        SpringApplication.run(ActivemqMessageConverterApplication.class, args);
    }

    @Bean
    public ActiveMQConnectionFactory connectionFactory() {
        final var activeMQConnectionFactory = new ActiveMQConnectionFactory(
                "",
                "",
                ""
        );
        activeMQConnectionFactory.setTrustAllPackages(true);
        return activeMQConnectionFactory;
    }

    @Bean
    public JmsMessageConverter jmstMessageConverter() {
        return new JmsMessageConverter();
    }

    @Bean
    public JmsListenerContainerFactory listenerTopic(ActiveMQConnectionFactory activeMQConnectionFactory, JmsMessageConverter jmsMessageConverter) {
        final var factory = new DefaultJmsListenerContainerFactory();
        factory.setPubSubDomain(true);
        factory.setConnectionFactory(activeMQConnectionFactory);
        factory.setMessageConverter(jmsMessageConverter);
        return factory;
    }

    @Bean
    public JmsTemplate senderTopic(ActiveMQConnectionFactory activeMQConnectionFactory, JmsMessageConverter jmsMessageConverter) {
        final var jmsTemplateTopic = new JmsTemplate(new CachingConnectionFactory(activeMQConnectionFactory));
        jmsTemplateTopic.setPubSubDomain(true);
        jmsTemplateTopic.setMessageConverter(jmsMessageConverter);
        return jmsTemplateTopic;
    }

}

class JmsMessageConverter extends SimpleMessageConverter {

    @Override
    public Object fromMessage(Message message) throws JMSException, MessageConversionException {
        System.out.println("fromMessage");
        return super.fromMessage(message);
    }

    @Override
    public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
        System.out.println("toMessage");
        return super.toMessage(object, session);
    }
}

@RestController
@RequestMapping("/")
class TesteController {
    @Autowired
    private JmsTemplate jmsTemplate;

    @GetMapping
    public void sendMessage() {
        jmsTemplate.convertAndSend("topic/teste", "Teste");
    }
}

@Component
class TesteJmsListener {
    @JmsListener(destination = "topic/teste", containerFactory = "listenerTopic")
    public void onReceiverTopic(Object object) {
        System.out.println(object);
    }
}

pom.xml

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.2.1</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
        <java.version>21</java.version>
</properties>
<dependencies>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-activemq</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
</dependencies>

Comment From: wilkinsona

Can you please provide a complete, yet minimal sample that reproduces the problem? The above doesn't provide enough information as we cannot, for example, see how you have configured a connection to ActiveMQ. We could try to guess but that is likely to be a waste of time as we could end up diagnosing a problem other than the one that you have.

Comment From: wilkinsona

On second thought, I don't think this has anything to do with Spring Boot as so much of the JMS infrastructure is being manually configured.

The problem appears to lie in the @JmsListener method where the parameter is an Object. This indicates that your listener can accept anything and, therefore, that no conversion is required. If you use a more specific type for the parameter, conversion should occur.

If you have any further questions, please follow up on Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements. If you still believe that you have found a bug, a Spring Framework issue would be more appropriate given that it provides the JMS infrastructure that you're manually configuring.