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
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):
application.properties
:
jms.topic=OrderUpdates
jms.consumer1=OrderUpdates::Consumer1
jms.consumer2=OrderUpdates::Consumer2