使用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&feedType=atom_1.0</atom> <rss>queueBrowse/ExampleQueue?view=rss&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
相关产品推荐
相关产品推荐

