EJB's - when to use Remote and/or local interfaces?

I'm very new to Java EE and I'm trying to understand the concept of Local interfaces and Remote interfaces.

In the initial versions of the EJB specification, EJBs were "assumed" to be remote components and the only way to invoke them was to make a remote call, using RMI semantics and all the overhead it implies (a network call and object serialization for every method call). EJB clients had to pay this performance penalty even when collocated in the same virtual machine with the EJB container.

Later, Sun realized most business applications were actually not distributing EJBs on a different tier and they fixed the spec (in EJB 2.0) by introducing the concept of Local interfaces so that clients collocated in the same virtual machine with the EJB container can call EJBs using direct method invocation, totally bypassing RMI semantics (and the associated overhead).

I've been told that one of the big advantages of Java EE is that it is easy to scale (which I believe means you can deploy different components on different servers)

Java EE can scale, but this doesn't necessarily means distributing components. You can run a Web+EJB application on a cluster without separating the Web tier and the EJB tier.

Are you supposed to use Remote interfaces if you expect your application to have different components on different servers? And use Local interfaces if your application is only going to reside on one server?

I would phrase it like this: use remote interfaces if the client are not in the same JVM (this doesn't mean using only one server/JVM).

(...) Start off by using Local interfaces, and gradually upgrade to Remote interfaces where applicable?

I would probably start by using Local interfaces. And as already hinted, switching to remote interfaces is not always mandatory (you can cluster a collocated structure).

I suggest to check the resources mentioned below (the 2 first ones are quite old but still relevant, the 2 others are more recent).

Resources

  • Under the Hood of J2EE Clustering by Wang Yu
  • Scaling Your Java EE Applications by Wang Yu
  • Scaling Your Java EE Applications -- Part 2 by Wang Yu

While I agree with most of what is written above, I would like to refine the "how to start" ideas a bit.

My suggestion to you is to never ever program directly to EJB interfaces within your code. Always use a regular, business-oriented interface, program to it (meaning, have your code call methods on the business-oriented interface) and provide the EJB "glue" code as a pluggable implementation. Your program should be focused on business logic, and not on implementation details such as EJB.

That way, you can easily switch between remote and local implementations - and if you use an IoC container such as Spring, you can do it by means of configuration only.

A special note about switching from local to remote: note that there are a few semantic differences between the two. For example, calling an EJB method via its "remote interface" results in arguments being passed by-value, while calling through the "local interface" results in arguments being passed by-reference. This is a major difference; so if you "start with local", make sure that you design your system in a way that it takes "remote" semantics into consideration as well.

If your design relies on EJB methods changing passed-in objects, then it would be tricky for you to "switch to remote" later; perhaps even impossible.

Good luck.


According to EJB Spec 3.2 an EJB can be either be local or remote. A business interface cannot be both local and remote at the same time.

@Local annotated beans can only be accessed if they are in the same application.

@Remote annotated beans can be accessed across different applications, residing in different jvms or across application servers.

So the important things to keep in mind are:

  1. If a bean class contains the @Remote annotation, then all implemented interfaces are to be remote.
  2. If a bean class contains no annotation or if the @Local annotation is specified, then all implemented interface are assumed to be local.
  3. Any interfaces that is explicitly defined for a bean which contains no interface must be declared as @Local.
  4. The EJB 3.2 release tends to provide more granularity for situations where local and remote interfaces need to explicitly defined.