Puckl
Puckl

Reputation: 741

Accessing Enterprise Beans through a Remote Interface with @EJB

I have an interface like this:

@Remote
public interface ClientDataAccessRemote

And the EJB implements it:

@Stateless
public class ClientDataAccess implements ClientDataAccessRemote 

And in the remote client I can access the EJB with this:

@EJB
private static ClientDataAccessRemote clientDataAccess;

This is everything I did and it works. The client and the EJB reside on the same server. Would it still work if they were separated? And how would the container find the EJB with that interface? I implemented this with Netbeans and I didn´t have to specify any locations or anything like that. How does this work?

Upvotes: 1

Views: 1559

Answers (1)

Paweł Wyrwiński
Paweł Wyrwiński

Reputation: 1443

Unfortunatelly @EJB annotation works for local (single JVM) injections only. For separate hosts you need to fallback to plain JNDI lookup.

AFAIK there are some proprietary non-portable solutions to perform remote dependency injections, like for WebLogic server (here), but I wouldn't go that way.

JNDI lookup works but is overly complicated and quite ugly:

  • you need to know server vendor and add its client libraries to your app's dependencies,
  • you pollute application with:
    • cryptic vendor-specific URI formats
    • vendor-specific naming service port numer (often defaults to 1099, but who knows for sure...)
    • vendor-specific jndi-name pattern

Here is example lookup for bean hosted on remote JBoss 4.x instance:

Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY,
    "org.jnp.interfaces.NamingContextFactory");
properties.put(Context.URL_PKG_PREFIXES,
    "org.jboss.naming:org.jnp.interfaces");
properties.setProperty(Context.PROVIDER_URL, "localhost:1099");
InitialContext context = null;
ClientDataAccessRemote cl = null;
try {
    context = new InitialContext(properties);
    cl = (ClientDataAccessRemote) context.lookup("ClientDataAccess/remote");
} catch (NamingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

Given your EJB is part of EAR you need to prefix name of EJBean with name of EAR:

cl = (ClientDataAccessRemote) context.lookup("MyEAR/ClientDataAccess/remote");

Above example is JBoss specific, I'm not even sure if it will work with JBoss 5.x series without modifications.

Apparently EJB 3.1 specification brings some unification to jndi naming, but I haven't got pleasure to work with it yet.

If this example scared you a little, maybe a better solution would be exposing your EJB as web services (SOAP or REST style). It brings problems of it's own, but is portable at least.

Upvotes: 1

Related Questions