Hugo sama
Hugo sama

Reputation: 909

Create durable topic and subscriber spring boot jms with ActiveMQ

I need to create a topic and a durable subscriber for ActiveMQ, my problem is that I don't know where to specify that. I am able to create the topic and consume the messages, but when I turn off the subscriber then keep sending messages and turn on the subscriber again, it won't read them.

This is what I have so far:

Sending the message :

    JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
    jmsTemplate.setPubSubDomain(true);
    jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT);
    jmsTemplate.setDeliveryPersistent(true);
    jmsTemplate.convertAndSend("venta.topic",venta);

Receiving the 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 the durable subscriber.

I've also read the spring docs

And I think it has something to do with the DefaultJmsListenerContainerFactory (which I didn't implement, I am using the default configuration), the docs shows:

@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 the durable session. Both my producer and my subscriber are connected to a standalone activemq binary.

I hope you can help me , thanks in advance.

Upvotes: 7

Views: 15378

Answers (3)

Hugo sama
Hugo sama

Reputation: 909

As the previous answers pointed out, it was necessary to set the client id and the durable subscription on the factory :

@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 alone did not register the client as a durable subscriber, that is because the JMSListener needed the containerFactory specified, otherwise it would just take 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 mentioning that, this post was the one that made me realize my mistake.

I Hope this will help someone else

Upvotes: 11

NiranjanK
NiranjanK

Reputation: 437

The DefaultJmsListenerContainerFactory should have unique clientId and durable sub. true set like below code :

@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;
}

Upvotes: 5

Petter Nordlander
Petter Nordlander

Reputation: 22279

Hard to tell for sure, but a common cause to this problem is to forget configuring a unique clientId on the connectionFactory bean. It has to be unique and is the way the broker can tell each client apart.

Upvotes: 3

Related Questions