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

Spring Boot3下通过JNDI访问嵌入式ActiveMQ Artemis连接失败求助

问题描述

生产环境基于Spring Boot 3.0.5对接无官方starter支持的商用JMS Broker,通过JNDI方式获取ConnectionFactory;测试环境计划替换为嵌入式内存ActiveMQ Artemis,但配置后访问抛出ActiveMQNotConnectedException,提示无法连接服务器。此前在Spring Boot 2 + ActiveMQ Classic环境下使用vm://localhost可正常工作,现在切换Artemis后同样报错。


现有配置代码

主类配置

@EnableJms
@SpringBootApplication
public class Main {

  @Bean
  public ConnectionFactory connectionFactory(
      @Value("${jms.jndi-context-factory}") String jndiContextFactory,
      @Value("${jms.broker-url}") String brokerUrl) throws NamingException {
    Properties props = new Properties();
    props.put(Context.INITIAL_CONTEXT_FACTORY, jndiContextFactory);
    props.put(Context.PROVIDER_URL, brokerUrl);
    InitialContext ctx = new InitialContext(props);
    return (ConnectionFactory) ctx.lookup("ConnectionFactory");
  }

  public static void main(String[] args) {
    SpringApplication.run(Main.class, args);
  }
}

Receiver组件

@Component
public class Receiver {

  private final BlockingDeque<String> receivedMessages = new LinkedBlockingDeque<>(100);

  @JmsListener(destination = "testtopic")
  public void receive(Message<String> message) {
    receivedMessages.add(message.getPayload());
  }

  public String getNextReceivedMessage() {
    try {
      return receivedMessages.poll(1_000L, MILLISECONDS);
    } catch (InterruptedException e) {
      throw new AssertionError(e);
    }
  }
}

测试环境application.yml

jms:
  jndi-context-factory: 'org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory'
  broker-url: 'vm://0'

Maven测试依赖

<dependency>
  <groupId>org.apache.activemq</groupId>
  <artifactId>artemis-jakarta-server</artifactId>
  <scope>test</scope>      
</dependency>

异常信息

org.springframework.jms.UncategorizedJmsException: Uncategorized exception occurred during JMS processing; nested exception is ActiveMQNotConnectedException[errorType=NOT_CONNECTED message=AMQ219007: Cannot connect to server(s). Tried with all available servers.]
    at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:311)
    ...(省略中间栈信息)
Caused by: ActiveMQNotConnectedException[errorType=NOT_CONNECTED message=AMQ219007: Cannot connect to server(s). Tried with all available servers.]
    at org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.createSessionFactory(ServerLocatorImpl.java:703)
    ... 77 more

解决方案

问题根源

  1. 嵌入式Broker未启动:ActiveMQ Artemis的VM连接模式要求Broker实例已显式启动,当前仅配置JNDI连接工厂,未初始化并启动嵌入式Artemis Broker。
  2. JNDI配置缺失:Artemis的JNDI初始上下文工厂需要额外配置映射关系,仅指定provider-url无法让JNDI找到ConnectionFactory实例。

具体修复方案

方案1:保留JNDI逻辑,启动嵌入式Broker

步骤1:添加测试专用Broker配置Bean

创建测试配置类,手动启动嵌入式Artemis Broker:

@TestConfiguration
public class EmbeddedArtemisConfig {

    @Bean(destroyMethod = "stop")
    public EmbeddedActiveMQ startEmbeddedBroker() throws Exception {
        EmbeddedActiveMQ embeddedBroker = new EmbeddedActiveMQ();
        embeddedBroker.start();
        return embeddedBroker;
    }
}

在测试类中引入该配置:

@SpringBootTest
@Import(EmbeddedArtemisConfig.class)
public class ReceiverTest {
    // 原有测试代码不变
}

步骤2:补充JNDI配置属性

修改测试环境application.yml,添加JNDI连接工厂映射:

jms:
  jndi-context-factory: 'org.apache.activemq.artemis.jndi.ActiveMQInitialContextFactory'
  broker-url: 'vm://0'
  jndi-additional-props:
    connectionFactory.ConnectionFactory: vm://0

同时修改主类的connectionFactory Bean,加载额外JNDI属性:

@Bean
public ConnectionFactory connectionFactory(
    @Value("${jms.jndi-context-factory}") String jndiContextFactory,
    @Value("${jms.broker-url}") String brokerUrl,
    @Value("#{${jms.jndi-additional-props:{}}}") Map<String, String> additionalJndiProps) throws NamingException {
  Properties props = new Properties();
  props.put(Context.INITIAL_CONTEXT_FACTORY, jndiContextFactory);
  props.put(Context.PROVIDER_URL, brokerUrl);
  props.putAll(additionalJndiProps); // 注入额外属性
  InitialContext ctx = new InitialContext(props);
  return (ConnectionFactory) ctx.lookup("ConnectionFactory");
}

方案2:绕过JNDI,直接创建Artemis连接工厂

如果测试环境无需沿用JNDI逻辑,可直接替换ConnectionFactory Bean简化配置:

@TestConfiguration
public class TestJmsConfig {

    @Bean
    public ConnectionFactory connectionFactory() {
        return new ActiveMQConnectionFactory("vm://0");
    }
}

在测试类中引入该配置,覆盖生产环境的JNDI连接工厂:

@SpringBootTest
@Import(TestJmsConfig.class)
public class ReceiverTest {
    // 原有测试代码不变
}

关键说明

  • ActiveMQ Artemis与ActiveMQ Classic的VM连接逻辑不同:Classic会自动创建VM Broker,而Artemis必须显式启动嵌入式实例。
  • 若坚持使用JNDI,必须确保Broker已启动,且JNDI属性包含connectionFactory.ConnectionFactory映射,让Artemis JNDI工厂能识别对应的连接工厂。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 06:52:57