You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JMS Topic订阅者未收到消息,调用message.getText()出现空指针求助

JMS Topic Subscriber Issues: Message Not Received & NullPointerException Fixes

Let's break down the problems in your code and walk through how to fix them step by step.

1. Why the NullPointerException Happens

Your subscriber uses receiveNoWait(), which returns immediately if no message is available. If no message is received (either because the publisher ran first, or the subscriber checked before the message arrived), the message variable becomes null. Calling message.getText() on a null object throws the NullPointerException.

Quick Fix for NPE

Add a null check before accessing the message content:

TextMessage message = (TextMessage) topicSubscriber.receiveNoWait();
if (message != null) {
    System.out.println("Message received: " + message.getText());
} else {
    System.out.println("No message available to receive.");
}

2. Why the Subscriber Isn't Receiving Messages

This stems from two key JMS Topic behaviors and code timing issues:

a. Non-Persistent Message Behavior

You're using DeliveryMode.NON_PERSISTENT. For JMS Topics, non-persistent messages are only delivered to subscribers that are actively connected and subscribed at the exact moment the message is published. If the publisher sends the message before the subscriber is ready, the message is discarded forever.

b. Broker & Code Timing

  • Your publisher starts the broker when it runs. If you run the subscriber first, it will fail to connect (since the broker isn't up yet).
  • If you run the publisher first, it sends the message and closes the connection immediately. By the time you start the subscriber, the non-persistent message is already lost.
  • receiveNoWait() doesn't wait for messages to arrive—even if the subscriber runs first, it might check for messages before the publisher finishes starting the broker and sending the message.

Full Fixes to Resolve Both Issues

Option 1: Simplest Fix (Blocking Receive)

Replace receiveNoWait() with a blocking receive that waits for messages to arrive. This ensures the subscriber doesn't give up immediately.

Corrected Subscriber Code

public class Subscriber {
    private static final String CONNECTION_URL = "tcp://localhost:61616";
    public static void main(String[] args) throws Exception {
        TopicConnectionFactory connectionFactory = new ActiveMQConnectionFactory(CONNECTION_URL);
        TopicConnection topicConn = connectionFactory.createTopicConnection();
        TopicSession topicSession = topicConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
        Topic topic = topicSession.createTopic("test");
        TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic);
        
        topicConn.start();
        System.out.println("Waiting for message...");
        
        // Wait up to 10 seconds for a message (adjust timeout as needed)
        TextMessage message = (TextMessage) topicSubscriber.receive(10000);
        
        if (message != null) {
            System.out.println("Message received: " + message.getText());
        } else {
            System.out.println("No message received within timeout.");
        }
        
        topicConn.close();
    }
}

Option 2: Persistent Messages for Offline Subscribers

If you want subscribers to receive messages even when they're not connected, use persistent messages and durable subscriptions. This retains messages on the broker until a durable subscriber connects.

Modified Publisher (Persistent Delivery)

public class Publisher {
    private static final String CONNECTION_URL = "tcp://localhost:61616";
    public static void main(String[] args) throws Exception {
        BrokerService service = BrokerFactory.createBroker(new URI("broker:(" + CONNECTION_URL + ")"));
        service.start();
        TopicConnectionFactory connectionFactory = new ActiveMQConnectionFactory(CONNECTION_URL);
        TopicConnection topicConn = connectionFactory.createTopicConnection();
        TopicSession topicSession = topicConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
        Topic topic = topicSession.createTopic("test");
        TopicPublisher topicPublisher = topicSession.createPublisher(topic);
        
        // Use persistent delivery to retain messages for durable subscribers
        topicPublisher.setDeliveryMode(DeliveryMode.PERSISTENT);
        
        TextMessage message = topicSession.createTextMessage();
        message.setText("Hello World");
        topicPublisher.publish(message);
        System.out.println("Message published: " + message.getText());
        
        // Wait briefly to ensure the broker persists the message
        Thread.sleep(1000);
        
        topicConn.close();
        // Uncomment to stop the broker after publishing
        // service.stop();
    }
}

Modified Subscriber (Durable Subscription)

public class Subscriber {
    private static final String CONNECTION_URL = "tcp://localhost:61616";
    public static void main(String[] args) throws Exception {
        TopicConnectionFactory connectionFactory = new ActiveMQConnectionFactory(CONNECTION_URL);
        TopicConnection topicConn = connectionFactory.createTopicConnection();
        
        // Required for durable subscriptions: set a unique client ID
        topicConn.setClientID("durable-subscriber-1");
        
        TopicSession topicSession = topicConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
        Topic topic = topicSession.createTopic("test");
        
        // Create a durable subscriber with a unique subscription name
        TopicSubscriber topicSubscriber = topicSession.createDurableSubscriber(topic, "test-topic-subscription");
        
        topicConn.start();
        System.out.println("Waiting for message (durable subscriber)...");
        
        TextMessage message = (TextMessage) topicSubscriber.receive(10000);
        
        if (message != null) {
            System.out.println("Message received: " + message.getText());
        } else {
            System.out.println("No message received within timeout.");
        }
        
        topicConn.close();
    }
}

How to Test the Simplest Fix

  1. Run the Subscriber first—it will print "Waiting for message..." and wait up to 10 seconds.
  2. Run the Publisher—it starts the broker, sends the message, and prints the published message.
  3. The Subscriber will receive the message and print it immediately.

内容的提问来源于stack exchange,提问作者Mefisto_Fell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:23:42