Jboss 从portlet中的JSF托管bean调用远程EJB方法时出错

Jboss 从portlet中的JSF托管bean调用远程EJB方法时出错,jboss,ejb,portlet,ajp,Jboss,Ejb,Portlet,Ajp,我正在尝试将JSFPortlet部署到运行在JBossEAP6.4之上的Liferay portal 6.2中,使用OpenJDK8。portlet作为WAR文件部署,但通过远程接口调用EJB的某些方法。EJB作为EAR文件直接部署在JBoss上 在我的显影机上,它运转良好。但在一台测试机上,情况并非如此。WAR和EAR文件完全相同,两台机器的standalone.xml设置几乎相同,JBoss模块也相同 日志中打印的stacktrace如下所示: JBWEB000236: Servlet.se

我正在尝试将JSFPortlet部署到运行在JBossEAP6.4之上的Liferay portal 6.2中,使用OpenJDK8。portlet作为WAR文件部署,但通过远程接口调用EJB的某些方法。EJB作为EAR文件直接部署在JBoss上

在我的显影机上,它运转良好。但在一台测试机上,情况并非如此。WAR和EAR文件完全相同,两台机器的standalone.xml设置几乎相同,JBoss模块也相同

日志中打印的stacktrace如下所示:

JBWEB000236: Servlet.service() for servlet Adminis Servlet threw exception: javax.portlet.faces.BridgeException: javax.faces.FacesException
    at com.liferay.faces.bridge.BridgePhaseRenderImpl.execute(BridgePhaseRenderImpl.java:91) [liferay-faces-bridge-impl-3.2.4-ga5.jar:3.2.4-ga5 (Ephesus / Feb 15, 2014 AD)]
    at com.liferay.faces.bridge.BridgeImpl.doFacesRequest(BridgeImpl.java:112) [liferay-faces-bridge-impl-3.2.4-ga5.jar:3.2.4-ga5 (Ephesus / Feb 15, 2014 AD)]
    ...
    at java.lang.Thread.run(Thread.java:745) [rt.jar:1.8.0_121]
Caused by: javax.faces.FacesException
    at com.sun.faces.context.ExceptionHandlerImpl.handle(ExceptionHandlerImpl.java:139) [jsf-impl-2.1.28.redhat-8.jar:2.1.28.redhat-8]
    at org.icefaces.impl.application.ExtendedExceptionHandler.handle(ExtendedExceptionHandler.java:113) [icefaces-3.3.0.jar:]
    ... 194 more
Caused by: java.util.NoSuchElementException
    at java.util.HashMap$HashIterator.nextNode(HashMap.java:1439) [rt.jar:1.8.0_121]
    at java.util.HashMap$KeyIterator.next(HashMap.java:1461) [rt.jar:1.8.0_121]
    at org.jboss.ejb.client.EJBClientContext.getEJBReceiver(EJBClientContext.java:725) [jboss-ejb-client-1.0.30.Final-redhat-1.jar:1.0.30.Final-redhat-1]
    at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146) [jboss-ejb-client-1.0.30.Final-redhat-1.jar:1.0.30.Final-redhat-1]
    ...
    at com.sun.proxy.$Proxy459.obtenerUsuarioPorCodigo(Unknown Source)
    at com.sofis.adminis.delegates.PermisosDelegate.obtenerUsuarioPorCodigo(PermisosDelegate.java:450) [adminis-delegate-1.0.jar:]
    at com.sofis.security.web.UsuariosSessionBeanWeb.autenticar(UsuariosSessionBeanWeb.java:1927) [classes:]
    at com.sofis.security.web.listeners.SofisAutologinLiferayPhaseListener.afterPhase(SofisAutologinLiferayPhaseListener.java:54) [classes:]
    at com.sun.faces.lifecycle.Phase.handleAfterPhase(Phase.java:189) [jsf-impl-2.1.28.redhat-8.jar:2.1.28.redhat-8]
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:107) [jsf-impl-2.1.28.redhat-8.jar:2.1.28.redhat-8]
    ... 198 more
我将日志级别提升为“org.jboss.ejb.client”,现在在跟踪之前看到两条有趣的消息:

22:13:16,684 DEBUG [org.jboss.ejb.client.EJBClientContext] (ajp-/0.0.0.0:8009-5) org.jboss.as.ejb3.remote.LocalEJBReceiverPreferringDeploymentNodeSelector@4bc9113e deployment node selector selected  node for appname=SS-ADMINIS-ear-1.0,modulename=SS-ADMINIS-MAVEN-EJB-1.0,distinctname=
22:13:16,687 DEBUG [org.jboss.ejb.client.EJBClientContext] (ajp-/0.0.0.0:8009-5) Selected node  doesn't belong to eligible receivers. Continuing with a random eligible receiver
请注意,这两条消息中都没有节点名称(“节点”前有两个空格)

在我的开发机器中,第一条消息包含节点名,第二条消息不显示:

18:56:37,902 DEBUG [org.jboss.ejb.client.EJBClientContext] (http-/0.0.0.0:8080-2) org.jboss.as.ejb3.remote.LocalEJBReceiverPreferringDeploymentNodeSelector@6db73304 deployment node selector selected spio node for appname=SS-ADMINIS-ear-1.0,modulename=SS-ADMINIS-MAVEN-EJB-1.0,distinctname=
唯一的区别是,在我的机器中,我直接使用浏览器访问服务器([browser]--HTTP-->[JBoss]),而在测试机器中,我通过负载平衡器([browser]--HTTP-->[Apache]--AJP-->[JBoss])。这反映在消息中(ajp-/0.0.0与http-/0.0.0)

当我试图通过远程接口从EJB调用方法时,会引发异常。对本地存根的引用是通过查找获得的,结果不为null。部署时没有错误,查找也不会引发错误


可能会发生什么,或者我遗漏了什么?

我的一个朋友找到了解决办法

a没有说的是,测试机实际上是一个docker容器。而且,JBoss中似乎存在一个bug,docker使前者不读取主机名来选择节点名,因此在开始时de node name是空的。因此,将显示所选空名称节点上方的消息,然后显示错误


解决方法是使用JBoss的
-Djboss.node.name
参数指定节点名。我将该设置放在
standalone.conf
中,重新启动JBoss,它工作正常。现在,第一条消息显示了我指定的名称,第二条消息没有出现,也没有出现异常。

远程EJB部署在同一个JBoss EAP实例中还是另一个实例中?在同一个容器中。在这种情况下,您根本不应该使用EJB客户端机制;只需使用我正在做的普通JNDI查找(不带属性),普通JNDI查找(不引发异常也不返回null),然后对返回的对象调用方法。然后抛出异常。