spring-bootactivemq-classicjms-topic

Cannot create durable subcriber in Topic


With reference to Link, I created durable Subscriber using JMS+ActiveMQ+SpringBoot. I also generated Unique client ID using UUID.randomUUID().toString(). However,while starting Subscriber(Receiver), application is throwing following warning message

Cause: Durable consumer is in use for client: 8f1019fd-50d4-457b-b417-2058917ed7bb and subscriptionName: org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter


Pleae help me to remove the above warning message.

Durable topic with client id - '8f1019fd-50d4-457b-b417-2058917ed7bb' is create in ActiveMQ server enter image description here Following is the source code

ReceiverTopicApplicaton.java

@SpringBootApplication
@EnableJms
public class ReceiverTopicApplicaton {
public static void main(String[] args) {
        SpringApplication.run(ReceiverTopicApplicaton.class, args);
    }


    private ConnectionFactory connectionFactory() {
        return new ActiveMQConnectionFactory("tcp://localhost:61616");
    }

    @Bean
    public DefaultJmsListenerContainerFactory topicListenerFactory() {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        //we need to set destinationResolver() to remove the warning message
        factory.setDestinationResolver(destinationResolver());
        factory.setPubSubDomain(true); 
        factory.setSubscriptionDurable(true);
        factory.setConcurrency("3-10");
        factory.setClientId(UUID.randomUUID().toString());
        factory.setSubscriptionDurable(true);
        return factory;
    }

Receiver.java

@Component
public class Receiver {

    @JmsListener(destination = "durable.topic", containerFactory = "topicListenerFactory")
    public void receiveMessage(final Message message) throws JMSException {
        if (message instanceof ObjectMessage) {
            Object object = ((ObjectMessage) message).getObject();
            StudentDto studentDto = (StudentDto) object;
            System.out.println("Receiver :: Student Object Received..." + studentDto);
        }
    }

}

StudentDto.java

public class StudentDto implements Serializable {

    private Long studentId; 
    private String studentName; 
    private String gender;
    private Long age;   
    private String studentClass;    
    private LocalDate birthDate;

    public StudentDto() {}

    public StudentDto(Long studentId, String studentName,String gender,Long age,String studentClass, LocalDate birthDate) {
        this.studentId = studentId;
        this.studentName = studentName;
        this.gender = gender;
        this.age = age;
        this.studentClass = studentClass;
        this.birthDate = birthDate;
    }

    @Override
    public String toString() {
        return "Student [studentId=" + studentId + ", studentName=" + studentName + ", Gender=" + gender + ", Age="
                + age + ", studentClass=" + studentClass + ", birthDate=" + birthDate + "]";
    }
}

SendMessageApplication.java

@SpringBootApplication
@EnableJms
public class SendMessageApplication {

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

    @Bean
    public JmsListenerContainerFactory<?> topicListenerFactory(
            ConnectionFactory connectionFactory,
            DefaultJmsListenerContainerFactoryConfigurer configurer)       
    {
        DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        factory.setPubSubDomain(true); 
        return factory;
    }

TopicSendMessage.java

@RestController
@RequestMapping(path = "/schoolDashboard/topic")
class TopicSendMessage {

    @Autowired
    private JmsTemplate jmsTemplate;

    @GetMapping(path = "/publishMessage")
    public void sendMessage() throws Exception{
        String birthDate = "1978-10-05";
        StudentDto studentDto = new StudentDto(new Long(1), "Ritesh", "Male", new Long(12), "Class-V", LocalDate.parse(birthDate));
        System.out.println("TopicSendMessage.java :: Topic - Publishing Student Object....");               
        jmsTemplate.setPubSubDomain(true);
        jmsTemplate.convertAndSend("student.topic", studentDto);
    }
}

Solution

  • Since you're using ActiveMQ 5.x you're using JMS 1.1 and the JMS 1.1 specification states that there can only be one subscriber attached to a durable subscription. Since you're using setConcurrency("3-10") Spring is attempting to create multiple subscribers on the same durable subscription which results in the error you're seeing. You should either: