Inject a parameter from client to ejb bean in the context

1.6k views Asked by At

How to inject a parameter in the client of an Ejb? Something like that:

final Hashtable<String, String> jndiProperties = new Hashtable<String, String>();
jndiProperties.put("java.naming.factory.initial", "org.ow2.carol.jndi.spi.MultiOrbInitialContextFactory");
jndiProperties.put("java.naming.factory.url.pkgs", "org.ow2.jonas.naming");
jndiProperties.put("java.naming.provider.url", "rmi://localhost:1099");

final Context context = new InitialContext(jndiProperties);
Object obj = context.lookup("MyEjbTest");

context.addToEnvironment("user", new Object());

In the server side, using an Interceptor get the parameter injected by the client:

public Object intercept(InvocationContext ctx) throws Exception {

    Object o = ctx.getContextData().get("user");
    if (o != null) {
        LOG.info("Exists " + o.toString());
        return ctx.proceed();
    } else {
        return null;
    }
}

The parameter user is never injected in the context and in the server side o is always null. Is there any way to handle that?

1

There are 1 answers

2
Brett Kail On BEST ANSWER

No, there is no standard way to implicitly pass data to an EJB from a client. You must explicitly pass data to the EJB via a method argument.

If you're using RMI-IIOP, then you could write your own interceptor to transfer context data to the server and then store it in a thread local. If you're using WebSphere Application Server, you could use application context work areas (this was attempted to be standardized by JSR 149, but it was not deemed portable enough). These options are likely too niche or too cumbersome, so you're likely better off just explicitly passing the data via a method argument.

A complete example for sending additional context data using RMI-IIOP is quite extensive, but the general steps are:

  1. Start by registering an ORBInitializer. See the javadoc therein, but since ORB configuration is usually tightly controlled by the application server, you should read your application server documentation, particularly for how (or if it's even supported at all) you can add an ORB interceptor and how the class loading works.
  2. In the client, your ORBInitializer should call ORBInitInfo.add_client_request_interceptor. In your implementation of the send_request method, call ClientRequestInfo.add_request_service_context.
    1. Normally, you would reserve a vendor prefix with the OMG for the service context ID, but if it's local to your environment (i.e., you're not providing your application to third parties), then you can probably pick one that doesn't conflict with any other products in your environment.
    2. The bytes you send are your choosing. Your client would probably set some data in a thread local, and then your implementation of the send_request method would serialize the data to a byte[] to be added to the ServiceContext.
  3. In the server, your ORBInitializer should call add_server_request_interceptor. Your implementation of this interceptor would decode the service context sent by the client and probably set a thread local variable for the duration of the request and remove it at the end.