使用ActiveMQ Artemis与OpenLiberty时JMS ConnectionFactory注入为空问题
问题根源与解决方案
你的核心问题是Jakarta EE 9.1与旧JMS API包的命名空间不匹配,以及server.xml缺少ActiveMQ Artemis集成特性,导致JNDI无法正确找到ConnectionFactory实例。
1. 替换JMS API包命名空间
Jakarta EE 9+将Java EE的API从javax.*迁移到jakarta.*,你的代码中混用了旧的javax.jms和新的jakarta.*注解,导致类型匹配失败。需要将所有JMS相关的导入替换为jakarta.jms:
修改JMSConfig类
package com.demo.rest; import jakarta.annotation.Resource; import jakarta.enterprise.context.ApplicationScoped; import jakarta.jms.ConnectionFactory; // 替换javax.jms为jakarta.jms import jakarta.jms.Queue; @ApplicationScoped public class JMSConfig { @Resource(lookup = "jms/ArtemisConnectionFactory") private ConnectionFactory connectionFactory; @Resource(lookup = "jms/ArtemisQueue") private Queue queue; public ConnectionFactory getConnectionFactory() { return connectionFactory; } public Queue getQueue() { return queue; } }
修改MessageProducer类
package com.demo.rest; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.jms.Connection; // 替换javax.jms为jakarta.jms import jakarta.jms.JMSException; import jakarta.jms.MessageProducer; import jakarta.jms.Session; import jakarta.jms.TextMessage; @ApplicationScoped public class MessageProducer { @Inject private JMSConfig jmsConfig; public MessageProducer() { } public void sendMessage(String text) throws JMSException { try (Connection connection = jmsConfig.getConnectionFactory().createConnection(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = session.createProducer(jmsConfig.getQueue())) { TextMessage message = session.createTextMessage(text); producer.send(message); } } }
修改MessageConsumerMDB类
注意要修改destinationType的属性值为jakarta.jms.Queue,同时替换JMS API包:
package com.demo.rest; import jakarta.ejb.ActivationConfigProperty; import jakarta.ejb.MessageDriven; import jakarta.jms.JMSException; import jakarta.jms.Message; import jakarta.jms.MessageListener; import jakarta.jms.TextMessage; import java.util.logging.Level; import java.util.logging.Logger; @MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "jakarta.jms.Queue"), // 替换javax.jms.Queue @ActivationConfigProperty(propertyName = "destination", propertyValue = "jms/ArtemisQueue"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge") }) public class MessageConsumerMDB implements MessageListener { private static final Logger LOGGER = Logger.getLogger(MessageConsumerMDB.class.getName()); @Override public void onMessage(Message message) { if (message instanceof TextMessage) { try { String content = ((TextMessage) message).getText(); LOGGER.log(Level.INFO, "Received message: " + content); } catch (JMSException e) { LOGGER.log(Level.SEVERE, "Error reading message", e); } } else { LOGGER.log(Level.WARNING, "Received non-text message"); } } }
2. 完善server.xml的特性配置
默认的jakartaee-9.1特性并不包含ActiveMQ Artemis的集成组件,需要添加messaging-activemq特性到featureManager中,确保服务器能识别Artemis的JMS配置:
<?xml version="1.0" encoding="UTF-8"?> <server description="new server"> <featureManager> <feature>jakartaee-9.1</feature> <feature>messaging-activemq</feature> <!-- 添加此特性 --> </featureManager> <jmsConnectionFactory jndiName="jms/ArtemisConnectionFactory"> <properties.activemq brokerURL="tcp://localhost:61616" userName="admin" password="admin"/> </jmsConnectionFactory> <jmsQueue id="jms/ArtemisQueue" jndiName="jms/ArtemisQueue"> <properties.activemq queueName="Test_Queue"/> </jmsQueue> <basicRegistry id="basic" realm="BasicRealm"/> <httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443" /> <applicationManager autoExpand="true"/> <ssl id="defaultSSLConfig" trustDefaultCerts="true" /> </server>
3. 额外检查点
- 确保ActiveMQ Artemis broker已在
tcp://localhost:61616运行,并且配置的admin/admin用户名密码有效。 - 验证应用部署时服务器日志中没有JNDI绑定失败的提示,确认
jms/ArtemisConnectionFactory和jms/ArtemisQueue已成功注册。 - 检查项目依赖是否使用了Jakarta EE 9.1版本的JMS API,避免混合引入
javax.jms和jakarta.jms的依赖。
内容的提问来源于stack exchange,提问作者Alex_Pap
相关产品推荐
相关产品推荐

