activemq-artemisjms-topic

ActiveMQ Artemis JMS Topic message does not pass down to consumers


I am using JDK 17 and Apache ActiveMQ Artemis 2.38.0. I have simple following example for sending message to topic, but messages never gets through to consumers of that topic. There is no error or any other log on ActiveMQ Artemis or app side.

@Configuration
public class JmsConfig {

    @Bean
    public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setPubSubDomain(true); // Enable Pub/Sub for Topics
        return factory;
    }
}

Rest Controller

import com.codeforgeyt.artemisdemo.service.DispatcherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MessageController {

    @Autowired
    DispatcherService dispatcherService;

    @PostMapping(value = "/queue")
    public ResponseEntity<String> sendToQueue(@RequestBody String message){
        dispatcherService.sendMessage(message);
        return new ResponseEntity<>("Message sent: " + message, HttpStatus.OK);
    }

    @PostMapping(value = "/topic")
    public ResponseEntity<String> sendToTopic(@RequestBody String message){
        dispatcherService.sendTopic(message);
        return new ResponseEntity<>("Message sent to topic: " + message, HttpStatus.OK);
    }
}

My Service

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;

@Service
public class DispatcherService {

    @Autowired
    JmsTemplate jmsTemplate;

    @Value("${jms.queue}")
    private String jmsQueue;
    @Value("${jms.topic}")
    private String jmsTopic;
    Logger log = LoggerFactory.getLogger(this.getClass());

    public void sendMessage(String message){
        jmsTemplate.setPubSubDomain(false);
        jmsTemplate.convertAndSend(jmsQueue, message);
        log.info("Message sent To Queue.");
    }
    public void sendTopic(String message){
        jmsTemplate.setPubSubDomain(true);
        jmsTemplate.convertAndSend(jmsTopic, message);
        log.info("Message sent To Topic.");
    }
}

Receiver

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Service;

@Service
public class ReceiverService {

    Logger log = LoggerFactory.getLogger(ReceiverService.class);

    @JmsListener(destination = "${jms.queue}", containerFactory = "jmsListenerContainerFactory")
    public void receiveMessage(String message){
        log.info("Received Queue message: " + message);
    }

    @JmsListener(destination = "${jms.consumer1}", containerFactory = "jmsListenerContainerFactory")
    public void receiveTopicA(String topic){
        log.info("Received topic Consumer.A Message: " + topic);
    }
    @JmsListener(destination = "${jms.consumer2}", containerFactory = "jmsListenerContainerFactory")
    public void receiveTopicB(String topic){
        log.info("Received topic Consumer.B Message: " + topic);
    }
}

Springboot starter

@SpringBootApplication
public class ArtemisDemoApplication {

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

}

following is my application.properties:

spring.artemis.mode=native
spring.artemis.host=localhost
spring.artemis.port=61616
spring.artemis.user=admin
spring.artemis.password=test

jms.queue=Q.Test
jms.topic=VirtualTopic.OrderUpdates
jms.consumer1=Consumer.ClientA.VirtualTopic.OrderUpdates
jms.consumer2=Consumer.ClientB.VirtualTopic.OrderUpdates

Solution

  • It looks like you're using the "virtual topic" feature from ActiveMQ Classic, but I don't see any evidence that you've properly configured support for this as described in the documentation.

    Also, unless you're specifically porting an application directly from ActiveMQ Classic to ActiveMQ Artemis I would suggest not using the "virtual topic" feature and instead using (in order of preference):