无法让远程 EJB 与 Wildfly 上的 EJB 客户端 API 一起工作

Can't get Remote EJB to work with EJB Client API on Wildfly

我目前正在努力让远程 EJB 调用在 wildfly 上工作(8.x 和 9.x)。

详细来说,它是关于使用 EJB 客户端 API 方法从独立客户端应用程序(而不是从另一个应用程序服务器)进行远程调用。远程命名方法适用于我,但不适用于我的场景,因为我需要使用客户端拦截器将上下文数据传递给服务器端拦截器以进行远程调用。

但现在我尝试使用客户端进行远程调用 API 来作为一个简单的示例。因此,我尝试了 github (wildfly/quickstart/ejb-remote) 上可用的远程 ejb 调用快速入门。关键是这个快速入门引发了与我的简单示例应用程序相同的错误。以下是我的申请的一些细节:

我的远程接口:

package test.ejb;

public interface HelloRemote {
  String greet(String name);
}

我的 Bean 实现:

package test.ejb;
import javax.ejb.Remote;
import javax.ejb.Stateless;

@Stateless(name = "Hello")
@Remote(HelloRemote.class)
public class HelloBean implements HelloRemote {

  public String greet(String name) {
    return "Hello " + name;
  }
}

bean 的远程视图已在服务器上正确注册(在导出命名空间中):

java:jboss/exported/ejb-test-backend.jar/Hello!de.coryx.HelloRemote

这里是客户端:

我的主class:

import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.jboss.ejb.client.EJBClientContext;
import test.ejb.HelloRemote;

public class Main {
  public static void main(String[] args) throws Exception {
    Properties props = new Properties();
    props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
    Context context = new InitialContext(props);

    String jndiLookup = "ejb:/ejb-test-backend.jar/Hello!" + HelloRemote.class.getName();
    HelloRemote hello = (HelloRemote) context.lookup(jndiLookup);
    System.out.println(hello.greet("World"));
  }
}

jboss-ejb-client.properties(打包在jar/META_INF):

endpoint.name=client-endpoint
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false

remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port=8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

当我执行主要方法时,我收到以下错误消息(尝试我上面提到的 wildfly quickstart 时发生同样的事情):

Exception in thread "main" java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:, moduleName:ejb-test-backend.jar, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@497470ed
    at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:774)
    at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:116)
    at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)
    at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255)
    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200)
    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)
    at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)
    at com.sun.proxy.$Proxy0.greet(Unknown Source)
    at Main.main(Main.java:16)

当我使用远程命名方法时一切正常:

Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
props.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");
props.put("jboss.naming.client.ejb.context", true);
props.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
props.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
Context context = new InitialContext(props);

String jndiLookup = "/ejb-test-backend.jar/Hello!" + HelloRemote.class.getName();
HelloRemote hello = (HelloRemote) context.lookup(jndiLookup);
System.out.println(hello.greet("World"));

这里的输出是(如预期的那样):

Hello World

那么,有没有人知道这里或更好的地方可能出了什么问题,谁有使用 EJB 客户端 API 在 Wildfly 上进行远程 EJB 调用的工作示例? 提前致谢!

像往常一样,我在写下问题并讨论后不久就偶然发现了解决方案。

此设置的问题是 jboss-ejb-client.properties 文件尚未由客户端 API 加载,然后缺少连接 url , ...

我不知道是否对必须放置这些属性的所需位置进行了更改,或者我是否太笨而无法正确阅读它,或者我是否只是改编了一个损坏的教程。没关系 ;)

解决方案是将属性文件 toplevel 放在类路径中,而不是放在 JAR 的 META-INF 目录中!

它现在按预期工作,我可以注册客户端拦截器。