Thursday, March 09, 2006

Remote or Local interface?

EJB 3.0 takes away much of the pain associated with maintaining the Local and Remote interfaces for Session Beans. However, there are still some issues that you need to be aware of.

By design, the EJB specification disallows the same Business interface to be marked as @Local as well as @Remote (this restriction has been added in a revision to the PFD). The reason for this is that remote interfaces have different semantics to local interfaces, and it is usually inappropriate for the same method to be exposed as a remote interface as well as local interface. The problems are two-fold:

1. Remote interfaces must typically be designed to be coarse-grained.
2. Remote interfaces do not support the pass-by-reference semantics of parameter passing as in local interfaces.

Having separate Remote and Local interfaces forces designers to think about how the interfaces will be used and ensure that the design is optimised for the use case. It also reduces the chances of errors caused by incorrect semantics, such as clients relying upon ability to pass parameters by reference.

A drawback to this approach is that it does not allow transparent redeployment of an EJB from a co-located environment to a distributed environment or vice-versa. While such re-deployment has its dangers, there are times when it can prove useful to have such a facility.

Ideally, you should define your Session beans to have either remote or local interface. This will keep the design simple and allow you to implement Business Logic as POJOs.

If you do want to endow the same Session Bean with both remote and local interfaces, then, I suggest that you use the following example as a model:
public interface CustomerService {

void createCustomer(District d, Customer c);
void removeCustomer(Long id);
List findByDistrict(District d);

@Remote
public interface IRemote extends CustomerService {
}

@Local
public interface ILocal extends CustomerService {
}
}
Note that the local and remote interfaces extend a common business interface. Also note that the local and remote interfaces are nested within the business interface. I like this model because it reduces the clutter, keeps related interfaces together, and eases understanding.

When using dependency injection, you can specify explicitly whether you want the remote or local interface. For example:
@EJB(beanInterface=services.DistrictService.IRemote.class)
public final void setDistrictService(DistrictService districtService) {
this.districtService = districtService;
}

I also suggest that when specifying dependency injection, always annotate your setters rather than instance variables. This will allow you to use your beans outside the J2EE container, for example in a Spring Framework environment.

1 comment:

david said...

Have you tried it in JBoss? in 4.0.4GA using EJB3 RC9 it si not working