spring-bootactivemq-artemisjms-topic

Problem in receiving messages using @JmsListener with ActiveMQ Artemis when send using topic name as String in convertAndSend method


I am sending to an ActiveMQ Artemis topic. The topic is created using the following code:

@Bean
public ActiveMQTopic sampleTopic(){
    return new org.apache.activemq.artemis.jms.client.ActiveMQTopic("topicName");
}

If I send the message to a topic using the convertAndSend with sampleTopic as argument I receive the message in the listener.

@Autowired
private Topic sampleTopic;

jmsTemplate.convertAndSend(sampleTopic, jsonMessage, m -> {
    m.setStringProperty("type", "new");
    m.setStringProperty("sender", "abc");

    return m;
});

But if I send the message using the String name of topic as an argument to the convertAndSend() the message is not received by the listener.

jmsTemplate.convertAndSend("topicName", jsonMessage, m -> {
    m.setStringProperty("type", "new");
    m.setStringProperty("sender", "abc");

    return m;
});

The @JmsListener looks like this:

@JmsListener(destination = "topicName",
             containerFactory = "topicJmsListenerContainerFactory",
             subscription = "new",
             selector = "type = 'new' and sender = 'abc'")
@Transactional
public void onMessage(String payload) {
    
}

Configuration:

@Configuration
@EnableJms
@Profile("local")
@PropertySource("classpath:application-local.properties")
public class MessagingConfigArtemis {

    private static final String ARTEMIS_BROKER_URL = "tcp://localhost:61616";
    private static final String ARTEMIS_USERNAME = "artemis";
    private static final String ARTEMIS_PASSWORD = "artemis";

    @Bean
    public ConnectionFactory jmsConnectionFactory() throws JMSException {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
        connectionFactory.setBrokerURL(ARTEMIS_BROKER_URL);
        connectionFactory.setUser(ARTEMIS_USERNAME);
        connectionFactory.setPassword(ARTEMIS_PASSWORD);
        return connectionFactory;
    }

    @Bean
    public JmsTemplate jmsTemplate() throws JMSException {
        JmsTemplate jmsTemplate = new JmsTemplate(jmsConnectionFactory());
        return jmsTemplate;
    }

    @Bean
    public JmsListenerContainerFactory<DefaultMessageListenerContainer> jmsListenerContainerFactory(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory returnValue = new DefaultJmsListenerContainerFactory();
        returnValue.setConnectionFactory(connectionFactory);
        return returnValue;
    }


    @Bean
    public JmsListenerContainerFactory<DefaultMessageListenerContainer> topicJmsListenerContainerFactory(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory returnValue = new DefaultJmsListenerContainerFactory();
        returnValue.setConnectionFactory(connectionFactory);
        returnValue.setSubscriptionShared(true);
        returnValue.setSubscriptionDurable(true);
        returnValue.setPubSubDomain(Boolean.TRUE);
        return returnValue;
    }
}

As per my understanding the listener should be able to recieve the message from the topic, for both type of convertAndSend() methods (i.e. one with String and other with Topic as argument). Can anyone help?


Solution

  • By default, Spring Boot creates a JmsTemplate configured to transmit to queues by having pubSubDomain set to false. The JmsMessageListenerContainer is also configured the same way. To override and publish to topics, set spring.jms.pub-sub-domain=true through Spring Boot’s property settings (either inside application.properties or by setting an environment variable).