Spring Boot JMS Topic not working properly it behave like queue.
Sample code
Application
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
JMSConfig
@Configuration
@EnableJms
public class JMSConfig {
private static final String JMS_BROKER_URL = "vm://embedded?broker.persistent=false,useShutdownHook=false";
public static final String JMS_TOPIC_MAIL = "mailbox.topic";
@Bean
// Serialize message content to json using TextMessage
public MessageConverter jacksonJmsMessageConverter() {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
converter.setTargetType(MessageType.TEXT);
converter.setTypeIdPropertyName("_type");
return converter;
}
@Bean
public ActiveMQConnectionFactory amqConnectionFactory() {
return new ActiveMQConnectionFactory(JMS_BROKER_URL);
}
@Bean
public CachingConnectionFactory connectionFactory() {
return new CachingConnectionFactory(amqConnectionFactory());
}
@Bean
public ActiveMQTopic destinationTopic() {
return new ActiveMQTopic(JMS_TOPIC_MAIL);
}
@Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory());
// jmsTemplate.setDefaultDestination(destinationTopic());;
jmsTemplate.setDefaultDestinationName(JMS_TOPIC_MAIL);
jmsTemplate.setConnectionFactory(connectionFactory());
jmsTemplate.setMessageConverter(jacksonJmsMessageConverter());
return jmsTemplate;
}
@Bean
public JmsListenerContainerFactory<?> jmsListenerContainerFactory(
ConnectionFactory connectionFactory,
DefaultJmsListenerContainerFactoryConfigurer configurer) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setPubSubDomain(true);
factory.setConnectionFactory(connectionFactory());
// This provides all boot's default to this factory, including the
// message converter
configurer.configure(factory, connectionFactory());
// You could still override some of Boot's default if necessary.
return factory;
}
}
Here listeners are
First listener
@Component
public class JMSTopicListener1 {
@JmsListener(destination = JMSConfig.JMS_TOPIC_MAIL, containerFactory = "jmsListenerContainerFactory")
public void receiveTopicMessage(Email email) {
System.out.println("JMSTopicListener#1 Received <" + email + ">");
}
}
Second listener
@Component
public class JMSTopicListener2 {
@JmsListener(destination = JMSConfig.JMS_TOPIC_MAIL, containerFactory = "jmsListenerContainerFactory")
public void receiveTopicMessage(Email email) {
System.out.println("JMSTopicListener#2 Received <" + email + ">");
}
}
Access through web
@RestController
public class WebController {
@Autowired
JmsTemplate jmsTemplate;
@RequestMapping("/sendEmail")
public String sendEmail() {
System.out.println("Sending ************************ .");
jmsTemplate.convertAndSend(JMSConfig.JMS_TOPIC_MAIL, new Email(
"[email protected]", "Hello"));
return "Email send success!!!";
}
}
Ouput is
Sending ************************ . JMSTopicListener#2 Received
But message should be subscribed by both listener because it attached with Topic