Search code examples
jmsactivemq-artemis

MessageListener for ActiveMQ Artemis consumer is not receiving messages


I am migrating from ActiveMQ "Classic" 5.18.1 to ActiveMQ Artemis.

I updated my producer and consumer code as per documentation. I could get my producer to send messages. But the consumer app is exiting even though I have attached a MessageListener to it. I expected my MessageListener to be always up and running. What am I missing?

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.Topic;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Properties;


public class Consumer1 {
    public static void main(String[] args) throws Exception {
        String topicName = "jms/topic/default_EventTopic";
        final Properties properties = new Properties();
        properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory");
        properties.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");

        Context context = new InitialContext(properties);
        ConnectionFactory factory = (ConnectionFactory) context.lookup("ConnectionFactory");
        Connection connection = factory.createConnection();
        try {
            connection.setClientID("SampleConnection");
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            final Topic topic = (Topic) context.lookup(topicName);
            final MessageConsumer consumer = session.createDurableSubscriber(topic, "EventConsumer");

            connection.start();
            consumer.setMessageListener(message -> {
                try {
                    System.out.println("Type " + message.getStringProperty("type"));
                } catch (JMSException e) {
                    e.printStackTrace();
                }
            });
        } catch (final JMSException | NamingException cause) {
            System.out.println("Error while creating Message Consumer");
            cause.printStackTrace();
        } catch (Exception e ){
            e.printStackTrace();
        }
    }
}

Solution

  • When you set a JMS MessageListener it will receive messages asynchronously in its own thread (invoked by the JMS client implementation). In your case you need to prevent main from exiting and stopping your application because when that happens the MessageListener will be terminated.

    The only reason the application didn't terminate completely with ActiveMQ "Classic" is due to the way the OpenWire JMS client is implemented (i.e. the open connection blocks the JVM process from terminating). This implementation detail is not part of the public contract provided by the JMS API and should therefore not be relied upon. Now that you've switched to the ActiveMQ Artemis core JMS client the application terminates completely as soon as main exits.

    That said, you can continue to use the OpenWire JMS client with ActiveMQ Artemis if you like. ActiveMQ Artemis supports the OpenWire protocol.

    It's worth noting that this is a relatively common problem with JMS applications using a MessageListener. See here: