关于从独立应用程序远程访问 JBoss EJB 有大量令人沮丧的错误信息(更好的描述 - “关闭但没有雪茄”)。一天多来,我一直在用头撞墙,但没有成功。
我正在尝试将 EJB 从 WebLogic 移植到 JBoss,它由运行在另一台服务器上的独立应用程序调用。
我一直在这里、这里和其他几个地方寻找各种“解决方案”来解决我的问题,但没有成功。我已经尝试阅读官方文档,它希望我安装一个基于 Maven 的“快速入门”,它可能适合我的情况,也可能不适合我的情况,到目前为止我决定不去追求。(我的项目不是用 Maven 构建的,它使用 Gradle,但我有理由确定我已经成功部署了所有正确的依赖项)。
我有一个有状态的 EJB 部署在 EAR 内的 WAR 中(以前将其简单地部署在 WAR 中的实现没有帮助)。
我这样配置客户端:
public InitialContext createInitialContext() throws NamingException {
Properties prop = new Properties();
prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
prop.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jboss.naming.remote.client.InitialContextFactory");
prop.put(Context.PROVIDER_URL, purl);
prop.put(Context.SECURITY_PRINCIPAL, "myusername");
prop.put(Context.SECURITY_CREDENTIALS, "mypassword");
prop.put("jboss.naming.client.ejb.context", false);
return new InitialContext(prop);
}
public void closeContext(Context context) throws NamingException {
if (context != null) {
context.close();
}
}
private String getJndiName(
String prefix,
String appName,
String moduleName,
String distinctName,
String beanName,
Class viewClass,
boolean stateful)
{
StringBuilder builder = new StringBuilder();
if (prefix != null && prefix.length() > 0) {
builder.append(prefix).append(':');
}
builder.append(appName)
.append('/')
.append(moduleName)
.append('/')
.append(distinctName)
.append('/')
.append(beanName).append('!')
.append(viewClass.getName());
if (stateful) {
builder.append("?stateful");
}
return builder.toString();
}
public Object lookup(Context context) throws NamingException {
final String prefix = "ejb";
final String appName = "myearname";
final String moduleName = "mywarname";
final String distinctName = "";
final String beanName = "MyBean";
final Class viewClass = MyBeanInterface.class;
String jndi = getJndiName(prefix, appName, moduleName, distinctName, beanName, viewClass, true);
return context.lookup(jndi);
}
请注意,没有提供任何“不同的名称”,因为不需要。“distinct name”应该是可选的:所有这些都被调用:
MyBeanInterface sstatus = null;
try {
ctx = createInitialContext();
sstatus = (MyBeanInterface) lookup(ctx);
} catch (Exception ex) {
...
}
调用此代码时,会产生以下错误消息:
Caused by: java.lang.IllegalStateException: EJBCLIENT000024: No EJB receiver available for handling [appName:SockTransport, moduleName:SockTransport, distinctName:] combination
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:873) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBClient.createSessionWithPossibleRetries(EJBClient.java:222) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBClient.createSession(EJBClient.java:202) ~[ttjd.jar:?]
at org.jboss.ejb.client.naming.ejb.EjbNamingContext.doCreateProxy(EjbNamingContext.java:227) ~[ttjd.jar:?]
at org.jboss.ejb.client.naming.ejb.EjbNamingContext.createEjbProxy(EjbNamingContext.java:204) ~[ttjd.jar:?]
使用上面的代码,我提供的 JNDI 名称是
ejb:myearname/mywarname//MyBean!com.whatever.my.package.MyBeanInterface
. 请注意由缺少 distinctName 引起的双斜杠。我可以并且已经重新调整了此代码以代替生成ejb:myearname/mywarname/MyBean!com.whatever.my.package.MyBeanInterface
,这没有什么区别。
坦率地说,我认为这个错误信息是一个红鲱鱼。 我怀疑我的设置还有一些其他问题没有在这个界面上被捕获和破坏。我不认为独特的名称或缺乏与问题有任何关系。我认为这只是他们记录无法查找的对象的方式。
在我想出如何添加一个无用的“独特名称”以使 JBOSS 高兴之前可能是徒劳的,有人可以大胆猜测一下真正的问题可能是什么吗?
更新:
@Steve_C 的建议很有启发性,但我仍然没有让它们发挥作用。他在最初的上下文创建中留下了几点:
- Context.URL_PKG_PREFIXES
- Context.INITIAL_CONTEXT_FACTORY
- “jboss.naming.client.ejb.context”
但他引用的资源中提到了这些——顺便说一句,非常方便。
所以我添加了这些,我的 createInitialContext 方法现在看起来像这样:
public InitialContext createInitialContext() throws NamingException {
Properties prop = new Properties();
prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
prop.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jboss.naming.remote.client.InitialContextFactory");
prop.put(Context.PROVIDER_URL, "http-remoting://{server-ip}:{server-port});
prop.put("jboss.naming.client.ejb.context", true);
return new InitialContext(prop);
}
为什么当我已经在 jboss-ejb-client.properties 文件中提供了 server-ip 和 server-port 时需要 PROVIDER_URL 仍然是神秘的,但它有所作为。
将这三个项目添加到我的初始上下文环境中,现在我收到一条不同的错误消息(EJBCLIENT000025 而不是 EJBCLIENT000024):
java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:SockTransport, moduleName:SockTransport, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@67f639d3
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:798) ~[ttjd.jar:?]
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:128) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146) ~[ttjd.jar:?]
at com.sun.proxy.$Proxy20.create(Unknown Source) ~[?:?]
我想这算是进步,但我发现这比它需要的更困难。我想知道这些新属性是否需要在属性文件中,但官方文档很清楚地说它们不需要。