Build robust spring boot jms theme and subscriber using ActiveMQ
I need to create a theme and a strong subscriber for ActiveMQ, my problem is I don't know where to point this. I can create a topic and consume messages, but when I turn off the subscriber, keep sending messages and turn the subscriber back on, they won't read them.
This is what I have so far:
Sending a message:
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
jmsTemplate.setPubSubDomain(true);
jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT);
jmsTemplate.setDeliveryPersistent(true);
jmsTemplate.convertAndSend("venta.topic",venta);
Receiving a message:
@JmsListener(destination = "venta.topic",id = "comercial",subscription = "venta.topic")
public void receiveMessage(Venta venta) {
logger.log(Level.INFO, "RECEIVED : {0}",venta);
repository.save(venta);
}
I have read this article and I understand that I need to create a lasting subscriber.
I also read the spring docs
And I think it has something to do with DefaultJmsListenerContainerFactory
(which I have not implemented, I am using the default config) the docs show:
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory =
new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setDestinationResolver(destinationResolver());
factory.setConcurrency("3-10");
return factory;
}
But I can't seem to find where to create a long running session. Both my producer and my subscriber are connected to a standalone activemq binary.
Hope you can help me, thanks in advance.
As stated in the previous answers, the factory needed to set the customer ID and persistent subscription:
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory =
new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setDestinationResolver(destinationResolver());
factory.setConcurrency("3-10");
factory.setClientID("brokerClientId");
factory.setSubscriptionDurable(true);
return factory;
}
but that by itself didn't register the client as a permanent subscriber because it JMSListener
had to be specified containerFactory
, otherwise it would just accept the defaults:
@JmsListener(
destination = "venta.topic",
id = "comercial",
subscription = "venta.topic",
//this was also needed with the same name as the bean above
containerFactory = "jmsListenerContainerFactory"
)
public void receiveMessage(Venta venta) {
logger.log(Level.INFO, "RECEIVED : {0}",venta);
repository.save(venta);
}
It's worth noting that this post made me realize my mistake.
Hope this helps someone else
DefaultJmsListenerContainerFactory must have a unique clientId and a durable sub. true as shown below:
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory =
new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setDestinationResolver(destinationResolver());
factory.setConcurrency("3-10");
factory.setClientID("brokerClientId");
factory.setSubscriptionDurable(true);
return factory;
}
It's hard to say for sure, but a common reason for this problem is to forget about setting a unique clientId on the connectionFactory bean. It must be unique and the way the broker can tell each client separately.