Java SE 17客户端无法查找Payara中部署的无状态EJB求助
使用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

