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

Tomcat通过HTTP调用Payara远程EJB抛出NameNotFoundException问题

Payara 5.2022.2 远程EJB HTTP调用NameNotFoundException排查解决

问题场景

在Payara Server 5.2022.2中部署打包在JULY.ear内的TestMC EJB应用,EJB代码定义如下:

@Remote 
public interface City { 
  public Integer getVisits();
}
@Stateless(name = "City")
public class CityEJB implements City, Serializable {
}

启用ejb-invoker组件执行命令:

asadmin > set-ejb-invoker-configuration --enabled=true

部署后控制台输出可移植JNDI名称:

Portable JNDI names for EJB City: [java:global/JULY/TestMC/City, java:global/JULY/TestMC/City!cityall.City]

Tomcat 9侧客户端使用ejb-http-client依赖编写InitialContext查找逻辑,依赖配置:

<dependency>
    <groupId>fish.payara.extras</groupId>
    <artifactId>ejb-http-client</artifactId>
    <version>5.2022.2</version>
</dependency>

InitialContext配置:

public class InitialContextUtil {
    protected static InitialContext ic;
    public static InitialContext getInstance() {
        if (ic == null) {
            final Properties initialContextProperties = new Properties();
            initialContextProperties.put(Context.INITIAL_CONTEXT_FACTORY,
                    "fish.payara.ejb.rest.client.RemoteEJBContextFactory");
            initialContextProperties.put(Context.PROVIDER_URL, "http://localhost:8080/ejb-invoker");
            
            try {
                ic = new InitialContext(initialContextProperties);
            } catch (NamingException e) {
                e.printStackTrace();
            }
        }
        return ic;
    }
}

查找逻辑:

public void getUserServices() {
    try {
        cityRemote = (City) InitialContextUtil.getInstance().lookup(
                "java:global/JULY/TestMC/City"); 
    } catch (NamingException e) {
        e.printStackTrace();
    }
}

执行时抛出异常:

javax.naming.NameNotFoundException: Name [global/JULY/TestMC/City] is not bound in this context.

环境为Eclipse 2022-06、JDK 11,脱离IDE直接启动服务仍复现问题。

解决步骤

按优先级依次排查修复:

  • 修正ejb-invoker访问路径
    当前配置的PROVIDER_URL路径错误,Payara的ejb-invoker组件部署后的默认上下文根为/__ejb-invoker(注意前缀是两个下划线,和管理控制台中显示的应用名__ejb-invoker一致),将配置修改为:
    initialContextProperties.put(Context.PROVIDER_URL, "http://localhost:8080/__ejb-invoker");
    
    修改后可以先直接在浏览器访问http://localhost:8080/__ejb-invoker,确认返回ejb-invoker服务响应而非404,再进行代码调试。
  • 优先使用带接口全限定名的JNDI路径查找
    不带接口全限定名的JNDI写法在EJB实现多接口时容易出现绑定匹配失败问题,将lookup的名称替换为带接口全路径的格式,不需要额外加java:前缀:
    cityRemote = (City) InitialContextUtil.getInstance().lookup(
            "global/JULY/TestMC/City!cityall.City");
    
  • 补全JDK 11环境缺失的JAXB依赖
    JDK 11移除了默认内置的JAXB API,ejb-http-client在序列化/反序列化EJB代理对象时依赖JAXB组件,缺失时会出现隐性的上下文加载失败,最终表现为JNDI名称找不到。在Tomcat侧Web应用的pom.xml中补充以下依赖:
    <dependency>
        <groupId>jakarta.xml.bind</groupId>
        <artifactId>jakarta.xml.bind-api</artifactId>
        <version>2.3.3</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jaxb</groupId>
        <artifactId>jaxb-runtime</artifactId>
        <version>2.3.9</version>
    </dependency>
    
  • 校验接口一致性
    确认Tomcat侧Web应用中引用的City远程接口,和Payara服务端部署的City接口的全限定名(包名+类名)、方法签名完全一致,不要出现类版本、包名不匹配的问题。
  • 配置生效检查
    执行set-ejb-invoker-configuration命令后需要重启Payara对应域或实例,配置才会完全生效,若以上修改后仍报错,重启Payara服务后重试。

该问题和Eclipse版本、JDK大版本无直接关联,不需要降级到JDK 8或旧版Eclipse即可在JDK 11环境下正常运行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 14:09:18