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

添加JMS资源时遭遇javax.naming.NamingException问题求助

问题:Spring Boot迁移中通过JNDI配置JMS ConnectionFactory遇到NamingException

我正将遗留功能迁移至独立Spring Boot应用,通过编程方式添加DataSource资源已成功,但以类似方式添加JMS资源时,持续遭遇javax.naming.NamingException: Could not create resource instance错误。

我的代码如下:

TomcatConfig.java
[...]
public TomcatServletWebServerFactory servletContainer() {
        return new TomcatServletWebServerFactory() {
            @Override
            protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
                tomcat.enableNaming();
                return super.getTomcatWebServer(tomcat);
            }
            @Override
            protected void postProcessContext(Context context) {
                // JMS ConnectionFactory
                ContextResource jmsConnection = new ContextResource();
                jmsConnection.setName("jms/jmsConnection");
                jmsConnection.setType("javax.jms.ConnectionFactory");
                jmsConnection.setProperty("resourceAdapter", "openejb/Resource/JmsResourceAdapter");

                context.getNamingResources().addResource(jmsConnection);
            }
        };
    }

@Bean(destroyMethod="")
    public ConnectionFactory jndiConnectionFactory() throws IllegalArgumentException, NamingException {
        JndiObjectFactoryBean bean = new JndiObjectFactoryBean();
        bean.setJndiName("java:comp/env/jms/jmsConnection");
        bean.setProxyInterface(ConnectionFactory.class);
        bean.setLookupOnStartup(true);
        bean.afterPropertiesSet();                   // NamingException here!!
        return (ConnectionFactory) bean.getObject();
    }

我是现代化改造领域的新手,恳请各位指导。是否是因为Tomcat不支持EJB导致的?

我尝试通过编程方式创建ContextResource,但无法成功绑定/查找,无法实例化jndiConnectionFactory Bean,堆栈信息参考如下:

NamingException during context initialization: javax.naming.NamingException: Could not create resource instance
javax.naming.NamingException: Could not create resource instance
    at org.apache.naming.factory.FactoryBase.getObjectInstance(FactoryBase.java:98)
    at javax.naming.spi.NamingManager.getObjectInstance(NamingManager.java:321)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:864)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:158)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:850)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:172)
    at com......CustomContextListener.contextInitialized(CustomContextListener.java:25)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4462)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:4914)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1322)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:866)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:794)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1332)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1322)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:866)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:248)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:433)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:921)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:171)
    at org.apache.catalina.startup.Tomcat.start(Tomcat.java:489)
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123)
    at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104)
    at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:481)
    at com.............configuration.TomcatConfiguration$1.getTomcatWebServer(TomcatConfiguration.java:31)
    at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:211)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:184)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:162)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:585)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289)
解决方案

你的问题核心是Tomcat本身不自带JMS资源适配器(Resource Adapter),你配置的openejb/Resource/JmsResourceAdapter是OpenEJB的组件,而Tomcat作为轻量级Servlet容器,没有集成EJB/JMS相关的容器支持,所以无法实例化这个资源。以下是几种可行的解决方式:

1. 改用Spring Boot原生JMS配置(推荐)

放弃通过JNDI绑定OpenEJB的JMS资源,直接使用Spring Boot集成主流JMS Broker(如ActiveMQ、Artemis)的方式,代码更简洁且适配Spring生态:

首先添加对应依赖(以ActiveMQ为例):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-activemq</artifactId>
</dependency>

然后直接配置ConnectionFactory Bean:

@Bean
public ConnectionFactory connectionFactory() {
    ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
    factory.setBrokerURL("tcp://localhost:61616");
    factory.setUserName("admin");
    factory.setPassword("admin");
    return factory;
}

2. 保留JNDI方式适配遗留代码

如果必须通过JNDI查找来兼容遗留代码,可通过以下两种方式实现:

方式一:使用Spring的JNDI模拟上下文

通过SimpleNamingContextBuilder在Spring启动时手动绑定JMS资源到JNDI上下文,无需依赖Tomcat的JNDI:

@PostConstruct
public void initJndi() throws Exception {
    SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
    ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
    builder.bind("java:comp/env/jms/jmsConnection", factory);
    builder.activate();
}

方式二:配置Tomcat兼容的JNDI资源

如果一定要用Tomcat的原生JNDI,需要:

  • 引入对应JMS Broker的资源适配器(如ActiveMQ的activemq-rar包)到项目依赖中
  • 修改编程式配置,使用Tomcat能识别的JMS工厂类:
@Override
protected void postProcessContext(Context context) {
    ContextResource jmsConnection = new ContextResource();
    jmsConnection.setName("jms/jmsConnection");
    jmsConnection.setType("javax.jms.ConnectionFactory");
    // 使用ActiveMQ的JNDI工厂类
    jmsConnection.setProperty("factory", "org.apache.activemq.jndi.ActiveMQInitialContextFactory");
    jmsConnection.setProperty("brokerURL", "tcp://localhost:61616");
    context.getNamingResources().addResource(jmsConnection);
}

3. 关键排查要点

  • 确保项目已引入对应JMS Broker的依赖,避免缺失核心类
  • Tomcat不支持EJB容器,不要混用OpenEJB、WildFly等EJB容器的资源配置
  • 调整JNDI查找时机:将JndiObjectFactoryBean的setLookupOnStartup(false)改为延迟查找,或通过@DependsOn注解确保Tomcat上下文初始化完成后再执行查找

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 08:14:56