Crystal
Crystal

Reputation: 15

JMS consumer not receiving messages

I just finished a tutorial on JMS, so it's super new to me and I'm trying to understand the basics. I'm using ActiveMQ Artemis if that matters. I created two simple applications, one named Producer and the other named Consumer. I run Producer first then run Consumer. The Consumer application never terminates and does not print the messages to the console. Weirdly, if I do not manually terminate Consumer and run Producer a second time, then I see the messages that Consumer should have received printed on the console. What's going on here? How do I get Consumer to receive and print messages from Producer?

Here's Producer:

public class Producer {

    public static void main(String[] args) throws Exception {
        
        InitialContext initialContext = null;
        Connection connection = null;
        
        initialContext = new InitialContext();
        ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
        connection = cf.createConnection();
        Session session = connection.createSession();
        
        Queue queue = (Queue) initialContext.lookup("queue/myQueue");
        Topic topic = (Topic) initialContext.lookup("topic/myTopic");
        
        MessageProducer queueProducer = session.createProducer(queue);
        MessageProducer topicProducer = session.createProducer(topic);
        
        TextMessage queueMessage = session.createTextMessage("This message is for the queue2");
        TextMessage topicMessage = session.createTextMessage("This message is for the topic2");
    
        queueProducer.send(queueMessage);
        topicProducer.send(topicMessage);
        
        System.out.println("Message to queue sent: "+ queueMessage.getText());
        System.out.println("Message to topic sent: "+ topicMessage.getText());
        
        initialContext.close();
        
    }

}

Here's Consumer:

public class Consumer {

    public static void main(String[] args) throws Exception {
        
        InitialContext initialContext = null;
        Connection connection = null;
        
        initialContext = new InitialContext();
        ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
        connection = cf.createConnection();
        Session session = connection.createSession();
        
        Queue queue = (Queue) initialContext.lookup("queue/myQueue");
        Topic topic = (Topic) initialContext.lookup("topic/myTopic");
        
        MessageConsumer queueConsumer = session.createConsumer(queue);
        MessageConsumer topicConsumer1 = session.createConsumer(topic);
        MessageConsumer topicConsumer2 = session.createConsumer(topic);
        
        connection.start();
        
        TextMessage messageReceivedByQueueConsumer = (TextMessage) queueConsumer.receive();
        TextMessage messageReceivedByTopicConsumer1 = (TextMessage) topicConsumer1.receive();
        TextMessage messageReceivedByTopicConsumer2 = (TextMessage) topicConsumer2.receive();
        
        System.out.println("Message received by queue consumer: "+ messageReceivedByQueueConsumer.getText());
        System.out.println("Message received by topic consumer 1: "+ messageReceivedByTopicConsumer1.getText());
        System.out.println("Message received by topic consumer 2: "+ messageReceivedByTopicConsumer2.getText());
        
        connection.close();
        initialContext.close();
        
    }
}

Upvotes: 0

Views: 2167

Answers (1)

Justin Bertram
Justin Bertram

Reputation: 35008

What you're observing is, in fact, the expected behavior.

Since you run the Producer application first a message is being sent to a queue and a topic when no consumer/subscriber exists on either. The message sent to the queue is stored in the queue because that's how JMS queues work. The message sent to the topic is discarded since there are no subscriptions to receive the message. Again, this is how JMS topics work.

Then when your Consumer application runs the queueConsumer receives the message sent to the queue, but since you're invoking receive() with no timeout on topicConsumer1 the application will simply block forever since there are no messages in the topic consumer's subscription. This blocking prevents the message received from the queue from being printed.

You should run your consuming application first and then run your producer while the consuming application is still running. Then you should see all the messages received and printed as you assumed they would be.

Upvotes: 2

Related Questions