Switch Local/Remote EJBinterface usage without code change

Discussions

J2EE patterns: Switch Local/Remote EJBinterface usage without code change

  1. Solution Detail - We can have a common parent home interface (CommonHome) for the LocalHome and EJBHome interfaces. Similarly, another interface (CommonObject) be subclassed by EJBObject and EJBLocalObject. All business methods reside in these Common interface and they would throw java.lang.Exception. The Remote interfaces can override the methods by throwing a RemoteException.

    The client retrieves the JNDI name (local or remote) from the property file, performs a lookup and typecasts to the common parent home. When invoking CommonHome.create, the returned type is CommonObject and that is used by the client to interact with the EJB.

    To elucidate, the interfaces would be as follows:

    **** HOME Interfaces ****
    interface CommonHome{
    CommonObject create() throws Exception;
    }

    interface RemoteHome extends EJBHome, CommonHome{
    CommonObject create() throws RemoteException;
    }

    interface LocalHome extends EJBLocalHome, CommonHome{
    CommonObject create() throws Exception;
    }

    **** Object Interfaces ****
    interface CommonObject{
    int service() throws Exception;
    }

    interface RemoteObject extends EJBObject,CommonObject{
    int service() throws RemoteException;
    {

    interface LocalObject extends EJBLocalObject,CommonObject{
    int service() throws Exception;
    }

    **** Client ****
    Object homeObject = context.lookup("CommonBean");
    home = (CommonHome)PortableRemoteObject.narrow(homeObject, CommonHome.class);
    CommonObject object = home.create();
    object.service();

    Threaded Messages (21)

  2. <p>First, local and remote interfaces are not interchangeable. The client code has to be implemented differently for each as the remote passes by value and the local passes by reference.

    <p>Second, in your example, the local interfaces can throw "EJBException" rather than "Exception".
  3. How can this approach be made to work[ Go to top ]

    I tried out the above mentioned approach as we needed both local and remote interface for a ejb and we wanted this switch from local --> remote and vice versa a configurable option.
    However both in websphere 5.1 and weblogic 8.1 the ejb deployment fails and the following error is thrown.
    The RemoteHome class returns an instance of CommonObject which is not a valid remote object.
    If some body has successfully implemented the following approach please tell as to how to get around this problem. My email-id is shamsur_r@rediffmail.com
  4. By doing what you suggest you simply loose exception type information and blur the distinction between remote interfaces and local ones. This distinction is intended. IMO You shouldn't be making patterns to go around it. RMI and EJB have taken many design decisions to make that distinction clear. IMO breaking the distinction by creating a typeless interface (let it be exceptions, parameters, or whatever) is an anti-pattern.

    Gal
  5. Local vs remote semantics[ Go to top ]


    There's a timeless seminal paper published back in 1994 by Sun Research that is still wholly relevant to today's distributed computing problems. See "A Note on Distributed Computing" by Kendall, Waldo, Wollrath, Wyant at http://research.sun.com/technical-reports/1994/abstract-29.html. I strongly urge any serious EJB developer to read it.

    To quote from the abstract:

    We look at a number of distributed systems that have attempted to paper over the distinction between local and remote objects, and show that such systems fail to support basic requirements of robustness and reliability. These failures have been masked in the past by the small size of the distributed systems that have been built. In the enterprise-wide distributed systems foreseen in the near future, however, such a masking will be impossible.


  6. Local vs remote semantics[ Go to top ]

    There is a pattern (something service) which is basically a cache of home objects - stored against the jndi name.

    ie decouple code from lookup via the services factory. First time the jndi name is requested a lookup is performed, and from then on a cached copy is used. With the normal time-outs, water marks and so on that a cache provides.

    This could provide an abstraction of local and remote but not via your bespoke API, simply through a layer that does the jndi lookup differently, plus exceptions etc.

    BUT.

    I also agree that local and remote are fundamental to system design. If your system is small enough to always use local then ditch EJB and JNDI as totally irrelevant. And if its large enough then go with remote session facade, local entity.

    Jonathan
    ps LowRoad 4.10 code generator out later this week at
    http://www.tallsoftware.com/
    With build in referential integrity checks being the new feature...
  7. Local vs remote semantics[ Go to top ]

    Next time I should read the pattern more, ignore the first part of my post. But the 2nd part is still true.

    Jonathan
  8. Local vs remote semantics[ Go to top ]

    http://research.sun.com/technical-reports/1994/smli_tr-94-29.pdf

    It's a good read. It also makes the observation that distributed systems are more of a desire than a necessity (a Point Jonathan Gibbons makes in the next thread).

    "Every ten years (approximately), members of the language camp notice that the number of distributed applications is relatively small. They look at the programming interfaces and decide that the problem is that the programming model is not close enough to whatever programming model is currently in vogue ([messages, functions, objects]). A furious bout of language and protocol design takes place and a new distributed computing paradigm is announced that is compliant with the latest programming model. After several years, the percentage of distributed applications is discovered not to have increased significantly, and the cycle begins anew."

    Marc Fleury made the point that the 'Object Poets' wanting objects every where didn't work, in his interview with The Server Side.

    I think the penultimate sentence of Moby Dick sums it up (ironically cried by Starbuck).

    "Oh! Ahab," cried Starbuck, "not too late is it, even now, the third day, to desist. See! Moby Dick seeks thee not. It is thou, thou, that madly seekest him!"




  9. * Is this really working??
    * which home and Remote object did you specify in your descriptor file? (CommonHome ?? but this doesn't extend EjbHome??)
    * Where is the intelligence to decide which object type(Remote/Local) to create embedded within the appserver??

  10. According to this pattern i have to make

    (1)LocalHomeInterface
    (2)LocalRemoteInterface

    (3)HomeInterface
    (4)RemoteInterface

    (5)CommonHome
    (6)CommonObject(CommonRemote)

    (7)Bean class
    (8)and May be Primary Key class.

    Can anybody please tell me how i have to deploy my bean.

    Normally in client code (which call Bean) , after look up we call PortableRemote.narrow method to convert LookUp object to 'Home Object' . Is it require in case of use of Local Interfaces ?


    Does call to any other method( Like create() , Business methods) will be affected in case of Local Interfaces ?

    -viren
  11. First, don't try this. It's a bad idea.

    Second, if you were to try this, the point was to be able to swap the local and remote interfaces, not use them simultaneously. Client code would work against the "common" interface to facilitate this. Lastly, using narrow() to cast the local interfaces is not necessary, but it won't hurt anything.
  12. What is the advantage of not having to change your code between switching local and remote interfaces. For local interfaces you're passing objects by reference, where for remote interfaces you're passing them by value. If your clients make calls using pass-by-referrence, switching to remote interfaces will certainly require some code changes.If on the other hand, the clients are making only pass-by-value calls( RMI calls), then the need for local interfaces is defeated, hence the need to switch between intefaces.

     At the same time this code is making RMI calls only, which also defeats the purpose of local interfaces.
  13. Note :
    * This design can be utilised only by clients in the same JVM as the EJB.
    * As the background suggests, this idea was used only to determine whether there is a benefit to switching to LocalInterfaces without all the code changes. It also allowed our application to run on EJB1.1 as well as EJB 2.0 servers for some intermediate time, which was real useful to us.
    * You have to be aware that the pass-by-reference/value semantics should not affect your application functionality. In our case, it did not.

    Sri
  14. WHat's the point of this pattern if the client has to be in the same JVM as the EJBs. Isn't that why Local interfaces was introduced in EJB2.0. So why do I have to go through the pain of writing a few more interfaces just to switch between Local and Remote.Am I missing something here?
  15.         The fact that LocalInterfaces can be used implies that the client is in the same JVM. So that is not a limitation of the pattern as such. That is what LocalInterfaces are designed for.
           As per the EJB spec, if you ever have to switch Local/Remote ( the reasons could be app server differences, EJB 1.x/2 upgrade etc )you will have change all your client code. This design would make it a deploy-time config. However, that's assuming the pass-by reference/value criteria in my previous post is met.
           This need not be extra work. The Business Interface pattern (i.e. common parent to Remote to Bean ) can be extended to the Local interfaces. So it is something you may already have been doing.
  16. I see the utility of this in the circumstance where you actually have multiple clients that might be accessing the same business logic (EJB). Not so much in the situation where you want to 'switch' the implementation for a (read one) client.

    Say, for example, you have a web tier as the client that may be deployed on different JVM's and accessing the EJB remotely. At the same time, you have a service that can access the same EJB locally, improving performance. The semantics of the different clients are understood and intended. All is well.

    My primary objection to this approach is that which is outlined in a previous post. Namely, we *have* to obscure the business contract / interface by throwing some type of exception, e.g. Exception, EJBException just so the container can be happy - the effects of needing RemoteException. I would like to use a Business Delegate to encapsulate the selection of the remote or local interface - I might also like that delegate to handle the potential RemoteException. I can't though, because I must declare some type of exception that doesn't really need to be there.

    I like the basic idea so long as it *is* understood which semantics are in place. It's unfortunate that it seems difficult to use a Business Delegate here.
  17. I've attempted to use a similar pattern for by Home interfaces, however I've not been able to successfully deploy this on WebLogic 6.1.

    Even though the LocalHome create method does not throw a RemoteException, I get an error message saying that the LocalHome cannot throw a RemoteException.

    Has anyone been able to get this successfully deployed on WebLogic?
  18. Packaging your application into an ear file will acommplish the same result in Weblogic 6+.
  19. Hi Shriganesh,

    This Pattern looks very good. It enables you that , you can call same IMPLEMENTATION as localEJB as well as RemoteEJB.

    I have not tried it.
    I have some confusion about it.

    (1)When we deploy ejb with 5 interfaces, how deployment desccriptor will be generated?

    One change client has to make is URL Proiveder. It will be 'local-host' for Local.

    (2)Without your pattern if i want that my bean should be called Locally as well as Remotely, WHAT code changes i will need in client code as well as Bean code....Please tell me in as much detail as possible?

    Or Should i have to deploy it twice FIRST with Local Interfaces and SECOND with Reomote Interfaces with DIFFERENT JNDI NAME?


    Thanks,
    Viren Jasani.
  20. my thoughts...>>
    This seems to be OK for SessionBean implemention . What about an Entity Bean??. What would the method signatures in CommonHome interface be and what return types (esp for the finder methods be)?? . Does'nt seem to be possible because the finder methods of the EJB have to return a Remote/Local Bean [ calling a find on a Local Home returns a Local Bean(EJBObject0) and calling finder on a Remote Home returns a Remote Bean(EJBObject).... ]
    what i tried to do ...>>
    The code i did was on a proxy class that references the EJB and hides the JNDI call and lookup from the client. The client gets an instance of the proxy (something like this) and calls methods on proxy that is translated to an EJB call... he proxy has to make a local call first and if it faoils tries a remote call + in this way clients from outside the JVM can make calls via the proxy without knowing the details of implementation....

    In short ... doesnt seem to work for an Entity Bean
  21. This is a great idea.[ Go to top ]

    I had the same idea and implemented for session. It works for me. I did not have the pass-by-valye vs pass-by-refferance problem as long long the business methods take the passing object as argument and passed it back as the return
  22. very useful pattern[ Go to top ]

    ..this is a superb pattern which i've used over and over for many projects for stateless session beans. Deplyoment semantics very often change as a large project develops, some beans moved here other beans moved over there, this ear and that ear. Its great that the exception api stays the same no matter what type of a client i'm in ( eg a servlet or another session bean ), and no matter what the topology of the deployment is.