Search code examples
javajakarta-eeejbwildflywildfly-8

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


I'm currently struggling with getting remote EJB invocation to work on wildfly (8.x and 9.x).

In detail it's about remote invocation from a standalone client application (not from another app server) using the EJB Client API approach. The remote naming approach works for me but isn't applicable in my scenario because I need to use client-side interceptors for passing context data to a server-side interceptor for the remote invocations.

But for now I try to get remote invocations with the client API to work for a simple example. Therefore I tried the quickstart for remote ejb invocation which is available on github (wildfly/quickstart/ejb-remote). The point is that this quickstart raises the same error as my on simple sample app. Here are some details of my application:

My remote interface:

package test.ejb;

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

My Bean implementation:

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;
  }
}

The remote view of the bean is correctly registered at the server (in export namespace):

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

Here now the client side:

My Main 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"));
  }
}

The jboss-ejb-client.properties (packaged in 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

When I execute the main Method I get the following error message (same thing occurs when trying the wildfly quickstart that I mentioned above):

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)

When I use the remote naming approach everything is fine:

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"));

Output here is (as expected):

Hello World

So is there anyone who knows what could be wrong here or better, who has a working example for remote EJB invocation on Wildfly using the EJB client API? Thanks in advance!


Solution

  • As so often, I stumbled over the solution shortly after writing down the question and talking about it.

    The problem with this setup was that the jboss-ejb-client.properties file has not been loaded by the client API which was then missing the connection url, ...

    I don't know whether there where changes to the required location where these properties have to be placed or whether I was too dumb to read it correctly or whether I just adapted a tutorial that was corrupted. It doesn't even matter ;)

    The solution is to place the properties file toplevel on the classpath and not in the META-INF directory of the JAR!

    It works now as expected and I can register client-side interceptors.