How to pass extra parameters when EJB client invokes EJB in JBoss EAP 6
Environment
- JBoss Enterprise Application Platform (EAP)
- 6.0
Issue
- We need to be able to pass few extra parameters when invoking EJBs (local and remote). These parameters can not be a part of method signature. We tried ejbContext, TransactionSynchronizationRegistry and those do not work. We also tried https://issues.jboss.org/browse/AS7-5021 but it does not work in JBoss EAP 6.0.0
Resolution
Update to JBoss EAP 6.0.1 or later.
Create an EJBClientInterceptor that adds custom data to the context data, see the example below. Note the EJB 3.1 specification does not define client side EJB interceptors which is why the client interceptor is implementing the JBoss class EJBClientInterceptor.
import org.jboss.ejb.client.EJBClientInterceptor;
import org.jboss.ejb.client.EJBClientInvocationContext;
public class HelloClientInterceptor implements EJBClientInterceptor
{
@Override
public void handleInvocation(EJBClientInvocationContext context)throws Exception {
context.getContextData().put("test_data", "it_works");
// Must make this call
context.sendRequest();
}
@Override
public Object handleInvocationResult(EJBClientInvocationContext context)
throws Exception {
// Must make this call
return context.getResult();
}
}
Create a EJB Server Interceptor that pulls the data out, see the example below. Note this is an EJB 3.1 interceptor as which is defined in the EJB specification.
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import java.security.Principal;
public class HelloServerInterceptor
{
@Resource
private SessionContext context;
@AroundInvoke
public Object log(InvocationContext invocationContext) throws Exception {
String test_data = (String) invocationContext.getContextData().get("test_data");
System.out.println("test_data:" + test_data);
return invocationContext.proceed();
}
}
Add the client interceptor in your client when setting up the EJB call, for example:
import java.util.Hashtable;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.security.auth.login.LoginContext;
import javax.security.auth.callback.CallbackHandler;
import org.jboss.security.auth.callback.SecurityAssociationHandler;
import org.jboss.security.SimplePrincipal;
import org.jboss.ejb.client.EJBClientConfiguration;
import org.jboss.ejb.client.ContextSelector;
import org.jboss.ejb.client.PropertiesBasedEJBClientConfiguration;
import org.jboss.ejb.client.EJBClientContext;
import org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector;
// This is setting up the connection properties to call the remote ejb
Properties p = new Properties();
p.put("remote.connections", "default");
p.put("remote.connection.default.host", "localhost");
p.put("remote.connection.default.port", "4447");
p.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
p.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");
// The following setting is required when deferring to JAAS
p.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
p.put("remote.connection.default.username", "admin");
p.put("remote.connection.default.password", "redhat");
EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(p);
ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(cc);
EJBClientContext.setSelector(selector);
// registering the client interceptor (JBoss specific since the EJB 3.1 spec does not cover client side interceptors)
EJBClientContext.getCurrent().registerInterceptor(0, new HelloClientInterceptor());
// Create the initial context to look up the ejb
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
Context ctx = new InitialContext(env);
// look up and invoke the ejb
Hello ejbObject = (Hello) ctx.lookup("ejb:/example-ejb//Hello!jboss.example.ejb.Hello");
System.out.println(ejbObject.sayHello());
Note the JBoss private private attachments are stored under the key: org.jboss.ejb.client.EJBClientInvocationContext.PRIVATE_ATTACHMENTS_KEY key
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.