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

使用ActiveMQ Classic时出现NameNotFoundException问题求助

问题描述

通过Docker容器运行ActiveMQ Classic,端口为61616,未修改任何配置。已在Web界面创建示例队列ExampleQueue,队列定义如下:

<queues>
  <queue name="ExampleQueue">
    <stats size="0" consumerCount="0" enqueueCount="0" dequeueCount="0"/>
    <feed>
      <atom>queueBrowse/ExampleQueue?view=rss&amp;feedType=atom_1.0</atom>
      <rss>queueBrowse/ExampleQueue?view=rss&amp;feedType=rss_2.0</rss>
    </feed>
  </queue>
</queues>

使用以下Java代码尝试访问该队列:

package messageListener;

import javax.naming.*;
import java.util.Properties;
import javax.jms.*;

public class MessageListenerSender {

    // Member-Variables
    InitialContext initialContext;
    ConnectionFactory connectionFactory;
    Connection connection;
    Session session;

    Queue queue;
    MessageProducer queueMessageProducer;

    Topic topic;
    MessageProducer topicMessageProducer;

    // Connect to Message-Broker
    public void connectToMessageBroker() throws Exception {
        Properties properties = new Properties();
        properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.activemq.jndi.ActiveMQInitialContextFactory");
        properties.setProperty(Context.PROVIDER_URL, "tcp://localhost:61616");

        initialContext = new InitialContext(properties);

        connectionFactory = (ConnectionFactory) initialContext.lookup("ConnectionFactory");
        
        connection = connectionFactory.createConnection();

        session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    }

    // Access Point-To-Point Queue
    public void accessPointToPointQueue() throws Exception {
        queue = (Queue) initialContext.lookup("/queue/ExampleQueue");
        queueMessageProducer = session.createProducer(queue);
    }

    // Access Topic-Orientated Queue
    public void accessTopicQueue() throws Exception {
        topic = (Topic) initialContext.lookup("/topic/ExampleTopic");
        topicMessageProducer = session.createProducer(topic);
    }

    // Send Messages
    public void sendMessages() throws Exception {
        Message message0 = session.createTextMessage("Hello World!");
        queueMessageProducer.send(message0);

        Message message1 = session.createTextMessage("Goodbye World!");
        topicMessageProducer.send(message1);
    }

    // Close all Connections
    public void closeConnections() throws Exception {
        if (initialContext != null) {
            initialContext.close();
        }

        if (connection != null) {
            connection.close();
        }
    }

    public static void main(String[] args) throws Exception {
        MessageListenerSender messageListenerSender = new MessageListenerSender();

        messageListenerSender.connectToMessageBroker();
        messageListenerSender.accessPointToPointQueue();
        messageListenerSender.accessTopicQueue();
        messageListenerSender.sendMessages();
        messageListenerSender.closeConnections();
    }
}

执行代码时出现如下错误:

Exception in thread "main" javax.naming.NameNotFoundException: queue/ExampleQueue
    at org.apache.activemq.jndi.ReadOnlyContext.lookup(ReadOnlyContext.java:235)
    at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
    at messageListener.MessageListenerSender.accessPointToPointQueue(MessageListenerSender.java:40)
    at messageListener.MessageListenerSender.main(MessageListenerSender.java:74)

无法确定需要修改何处来解决该问题,是否是路径使用错误?希望搭建基于ActiveMQ Classic的消息收发端。


解决方案

问题核心是:ActiveMQ默认不会自动将Web界面创建的队列/主题注册到JNDI上下文,且你当前的JNDI查找路径和配置不匹配。以下两种方法可以解决:

方法1:配置JNDI映射,修正查找路径

在connectToMessageBroker方法中,添加队列和主题的JNDI映射属性,明确将目标名称绑定到JNDI上下文:

properties.setProperty("queue.ExampleQueue", "ExampleQueue");
properties.setProperty("topic.ExampleTopic", "ExampleTopic");

同时修改查找代码,去掉路径前缀,直接使用绑定的名称查找:

// Access Point-To-Point Queue
public void accessPointToPointQueue() throws Exception {
    queue = (Queue) initialContext.lookup("ExampleQueue");
    queueMessageProducer = session.createProducer(queue);
}

// Access Topic-Orientated Queue
public void accessTopicQueue() throws Exception {
    topic = (Topic) initialContext.lookup("ExampleTopic");
    topicMessageProducer = session.createProducer(topic);
}

方法2:跳过JNDI,直接创建目标对象

这种方式更简洁,不需要配置JNDI映射,直接通过Session创建队列/主题:

// Access Point-To-Point Queue
public void accessPointToPointQueue() throws Exception {
    queue = session.createQueue("ExampleQueue");
    queueMessageProducer = session.createProducer(queue);
}

// Access Topic-Orientated Queue
public void accessTopicQueue() throws Exception {
    topic = session.createTopic("ExampleTopic");
    topicMessageProducer = session.createProducer(topic);
}

同时可以简化连接逻辑,去掉InitialContext相关代码:

// Connect to Message-Broker
public void connectToMessageBroker() throws Exception {
    connectionFactory = new org.apache.activemq.ActiveMQConnectionFactory("tcp://localhost:61616");
    connection = connectionFactory.createConnection();
    session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
}

额外注意事项

  • 确保Docker容器的61616端口已正确映射到主机端口
  • 发送消息前建议调用connection.start(),虽然ActiveMQ会自动启动连接,但显式调用更规范
  • 若使用JNDI方式,需确保项目中包含ActiveMQ的JNDI依赖

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 11:45:06