Monday, January 24, 2011

EJB3.0 ------- Remote or Local interface for same bean ?

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.
Do you have one bean implementation class that has the [b]same[/b] Java interface as local and remote interface, e.g.
@Local(Foo.class)
@Remote(Foo.class)
@Stateless public class MyEJB implements Foo {
...
}
[b]and[/b]
you are trying to use it from an ejb or a web app?
In this case, you [b]probably[/b] have to use deployment descritor (ejb-jar.xml) so that you can deploy the same implementation class twice each time using a separate ejb-name. Then you can use those names in @EJB(beanName="xxx") format in your client.
2. The other alternative is to have something like this:
public interface Foo {...
}
public interface LocalFoo extends Foo{}
public interface RemoteFoo extends Foo{}
@Remote(RemoteFoo.class)
@Local(LocalFoo.class)
@Stateless
public class FooBean implements Foo {
...
}
Then you can use
@EJB LocalFoo myBean;
or
@EJB RemoteFoo myBean;
in your client. Container can use the interface type to figure out which one to use.
3. There is another thing worth mentioning here: if you use [i]your ejb from an application client, then you can never use local interface. So container will always use the remote view[/i]. I actually don't know if this is a portable behavior or not. I can check and let you know. But I know GlassFish behaves this way.


No comments:

Post a Comment