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!
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.