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

Java SE 17客户端无法查找Payara中部署的无状态EJB求助

问题:Java SE 17客户端查找Payara 6中无状态EJB失败,抛出NullPointerException

使用NetBeans 24 + Payara 6.2024-5开发Java SE 17客户端,尝试查找Payara中已部署的无状态EJB时,始终抛出异常,无法成功查找。

客户端代码

package client;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class Client {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
        Object o = new Object();
        try {
            InitialContext context = new InitialContext(props);
            o = context.lookup("java:global/USer/User-ejb/UserService");
        } catch (NamingException e) {
            e.printStackTrace();
        }
    }
}

依赖库说明

客户端依赖的Jar包均来自Payara 6的modules和lib目录:

appserv-rt.jar
config-api.jar
gf-client.jar
glassfish-api.jar
glassfish-naming.jar
hk2-api.jar
hk2-config.jar
hk2-core.jar
hk2-locator.jar
hk2-utils.jar
internal-api.jar

此外,NetBeans中使用了jakarta.jakartaeeapi-10.0.0.jar库。

报错信息

java.lang.NullPointerException: Cannot invoke "org.glassfish.internal.api.ORBLocator.getORB()" because "orbHelper" is null
    at com.sun.enterprise.naming.impl.SerialContext.getORB(SerialContext.java:351)
    at com.sun.enterprise.naming.impl.SerialContext.getProviderCacheKey(SerialContext.java:358)
    at com.sun.enterprise.naming.impl.SerialContext.getRemoteProvider(SerialContext.java:388)
    at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:333)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:482)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442)
    at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
    at client.Client.main(Client.java:12)
javax.naming.NamingException: Lookup failed for 'java:global/USer/User-ejb/UserService' in SerialContext[myEnv={java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext[myEnv={java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is java.lang.NullPointerException: Cannot invoke "org.glassfish.internal.api.ORBLocator.getORB()" because "orbHelper" is null]]
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:496)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442)
    at java.naming/javax.naming.InitialContext.lookup(InitialContext.java:409)
    at client.Client.main(Client.java:12)
Caused by: javax.naming.NamingException: Unable to acquire SerialContextProvider for SerialContext[myEnv={java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is java.lang.NullPointerException: Cannot invoke "org.glassfish.internal.api.ORBLocator.getORB()" because "orbHelper" is null]
    at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:338)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:482)
... 3 more
Caused by: java.lang.NullPointerException: Cannot invoke "org.glassfish.internal.api.ORBLocator.getORB()" because "orbHelper" is null
    at com.sun.enterprise.naming.impl.SerialContext.getORB(SerialContext.java:351)
    at com.sun.enterprise.naming.impl.SerialContext.getProviderCacheKey(SerialContext.java:358)
    at com.sun.enterprise.naming.impl.SerialContext.getRemoteProvider(SerialContext.java:388)
    at com.sun.enterprise.naming.impl.SerialContext.getProvider(SerialContext.java:333)

已尝试提高Payara日志级别,但日志中无相关报错记录。


解决思路

1. 简化依赖,仅使用gf-client.jar

Payara的gf-client.jar是专门为远程客户端设计的fat jar,包含了所有EJB远程调用所需的依赖。手动添加多个零散Jar包容易出现依赖缺失或版本冲突,直接替换为gf-client.jar(位于Payara安装目录的glassfish/lib下),移除其他所有手动添加的Payara相关Jar包,避免依赖混乱。

2. 补充完整的JNDI配置属性

当前客户端仅配置了初始上下文工厂,缺少远程连接必需的属性,导致无法正确初始化ORB(对象请求代理)。需要添加以下属性:

props.setProperty("java.naming.provider.url", "iiop://localhost:3700"); // Payara默认IIOP端口
props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");

注意:如果Payara的IIOP端口被修改,需要对应调整java.naming.provider.url中的端口号。

3. 验证JNDI名称的正确性

检查EJB部署后的JNDI名称是否与客户端使用的java:global/USer/User-ejb/UserService一致:

  • 登录Payara管理控制台(默认http://localhost:4848),进入Applications -> 部署的EJB模块 -> JNDI Names,查看无状态EJB的全局JNDI名称。
  • 注意名称的大小写:代码中的USer可能是拼写错误,实际部署的模块名称可能是User,需严格匹配。

4. 确保EJB已正确暴露远程接口

无状态EJB需要实现一个远程接口(标注@Remote),并且EJB类上标注@Stateless,否则无法被远程客户端查找。示例:

// 远程接口
@Remote
public interface UserService {
    // 业务方法
}

// EJB实现类
@Stateless
public class UserServiceImpl implements UserService {
    // 方法实现
}

部署后,Payara会为该EJB生成对应的全局JNDI名称。

5. 检查客户端JDK版本兼容性

确保客户端使用的Java SE 17与Payara 6.2024-5兼容(Payara 6支持Java 11-17),避免因JDK版本差异导致的类加载问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 16:27:01