Discussions

Web tier: servlets, JSP, Web frameworks: strategies for connecting servlet layer to ejb layer

  1. I was wondering how people are connecting their servlet layer, to their EJB layer.

       Specifically, inorder to give your servlets access to your EJB layer you need some way to store and re-use your home objects.

       Where are people storing their home objects? I can think of some alternatives:

    1) in static member variables (shared across all servlets)
       - this is possible since home objects are threadsafe
    2) as servlet member variables, with SingleThreadModel
       - for those who just want to be sure. :)
    3) In the ServletContext
       - This seems like a real nice "clean" way to do it. Is anyone doing this?
    4) Don't store them. Just lookup home objects all the time
       - jndi lookups are slow. I think this is a very bad practice.


        Thoughts?

    Floyd

    Threaded Messages (23)

  2. We are storing the EO factories in the session. Originally we were just doing JNDI lookups as needed. I do believe that the JNDI lookup could be more intensive.
  3. We are storing the EO factories in the session.


       I should have included that in my list. :) Chris, why are you storing them in your session? Doesn't that mean that there will be one set of Home objects for *every concurrent user* of your site? This could potentially be hundreds, or even thousands of home objects.

        Why did you choose to go the Session route, over the "one set for the whole app" alternatives I listed originally?

    Floyd
  4. Floyd,
    Now that I think about it, the ServletContext would be a nice way to go. As for the reasons as putting in the Session is that we wanted each user to have their own home. However as you have pointed out, that could be a hog. On another note, what do you think of caching the stub around for a stateless session? From reading the spec, it seems that the coupling of stub to the actual EJBObject is not too tight. So I should be able to hold onto the stub and use it repeatedly?

    Let me know what you think.
    Thanks.
  5. Caching stubs to stateless session beans may be dangerous. First of all, EJBObjects (unlike EJBHomes) are not thread safe. If you cache the EJBObjects in your Session then this won't be problem, but if you cache it application wide (say in the Servlet Context) you will run into problems, since only one client can use the EJBObject at a time.

        Now if you do store a stub per-client, then this should be ok, although I am not sure what the performance impact of having potentially MANY EJBObjects floating around compared to using the a Home to Create them as needed. Does anyone else have any input into this?

    Floyd
         
  6. I cache the Home objects into a HomeFactory class.
    This class supply static synchronized methods to get a synchronized smart proxy.

    The synchronize SP just delegate the call to the real proxy, but with synchronized methods.
    The smart proxy overhead is very low.

    The HomeFactory cache the JNDI context and store the Home proxy in a hashmap.
  7. That is an interesting strategy Thibault, and I have two questions about it:

    1) Why syncronize the proxy to the home objects, when they are supposed to be thread safe?

    2) What effect would holding your homes in a statics have on multiple VM Servlet enginges (load balanced, etc)? Some engine's may even swap in and out new VM's while they run.

    Floyd
  8. Hi,

    This thread is intersting. I'm a beginner to EJB programming. Right now in my code I'm looking up home
    objects all the time. Know that it's not so efficient,
    but schedule doesn't allow other thoughts.

    I like storing them in ServletContext.

    But I didn't quite understand the caching of Home objects
    in HomeFactory. Could one of you please elaborate on that?

    Thanks in advance,
    Kothapalli.
  9. Floyd,
    A home proxy is not multi-thread safe.

    I do not use load balancing, but it's possible to change the strategy in the cache to run a lookup for each request (no cache).

    The remote references must be managed by a single class in the system (i.e., RemoteRefManager), such as you centralize management rules to your system specific contraints. A consequence is to be able to change the management rules easily.

    This class may include a reference cache or not, a Context cache or not, may manage, or not the class re-loading.
    A kind of HomeHome !
  10. Hi

      ...This thread is quite interesting.Here I have my problem.I have deployed EJB's in winNT/Oracle8iR2 and my client servlets for this are in Redhat Linux6.2/Apache1.3.x/Tomcat3.1.My problme is when I invoke a EJB from JDeveloper IDE from a client machine,I am getting the result from EJB.But when I try the same from Tomcat,I am unable to intereact with the EJB.


        Just advice me what changes I have to make when I put my servlets in Tomcat.coz these are working from JDeveloper perfectly.

       I'll be thankful

    shyam
  11. Thibault,
      I am using an architecture very similar to yours. One problem i've discovered in caching these EJBHome references is that if a particular ejb is redeployed or undeployed after it is put in the HashMap you will get an exception(seems to be proprietary to a particular vendor) thrown. Since hot deployment is a pretty important tool what do you do to solve this problem? One option would be to catch the exceptions and try to refresh the HashMap. What are your thoughts?
  12. IBM Visual Age introduces a very interesting feature for the problem. Though introduced in VAJ it is simple in concept and can be easily reproduced on any App Server/IDE .

    Create ordinary Java Bean Wrappers for the each session Bean.
    The JNDI name is hardcoded into each wrapper bean.
    These Java Beans may use class inheritance to cache the EJBHomes and narrow them as required.
    The Beans expose the same methods as declared on the Remote Interface.Therefore you can call the methods on the session bean directly on this wrapper.
    Use Lazy instantiation to get the Remote reference.

    Im my case all my session beans expose a common interface and that allows me to treat all my wrapper beans as instances of that single type.
    Now add to this a factory to get the actual wrapper instance and your servlets can do magic.
    Any Servlet to any sesion bean thru the wrapper obtained thru the factory.


  13. Thibault,

        I like your reasoning for using a HomeFactory, very nice! However, I am still pretty sure that HomeObjects are threadsafe. After all, they are just factories! Here on TheServerSide I have one HomeObject that creates EJBObjects for every client, and there is no problem. Thibault, have you considered writing up your idea as a pattern here on TheServerSide? I would love to see some of that code. :)

    John, I like your pattern! Although it produces a whole new layer to this architecture, if using VAJ then obviously these are auto generated. I like the fact that they all inherit from a common interface, and can be produced from factories, very nice! I think this is worthy of being posted as a pattern as well.

    Floyd
  14. I've used java bean wrappers in the form of IBM VAJ
    Access Beans in a session EJB prototype. It all seems
    to work but I have not tested under any realistic loading. Finding documentation for VAJ Access Beans is hard.

    Incidentally, as a result of taking this approach
    when learning EJB I've never before had any idea
    that it could be necessary or desirable to store
    and re-use home objects!

    Thanks,

    Ken
  15. Floyd,

    A proxy to a Home, or on an EJB is the same: a RMI or CORBA proxy to a remote object. J2EE/RMI/CORBA do not specify that a proxy has to be multi-thread-safe.

    To check this point, I start a thread in the sun EJB mailing-list, and Chris Raber reply that you should never supose a proxy multi-thread safe.

    Ciao
    Tibo.
  16. I would be weary of having lots of garbage floating around if you create a new proxy every time you want to make a call on the EJBObject.

    Holding the proxy in the user session strikes me as a good idea, since it's well contextualized and is likely to stick around for as long as the user session does. Additionally, it does not pose multithreading problems (unless, of course, you pull up a new window with the same session ID.)

    Someone suggested that, in addition to this, the proxy is serializable, which makes it easy to failover to another servlet engine. Is the proxy serializable, or is the /handle/ to the proxy (obtained via EJBObject.getHandle()) serializable?

    Thanks,
  17. Here is the rule that I follow:
    EJBHome gets dumped by JNDI name in the ServletContext.
    EJBRemote gets dumped by JNDI name in the HTTPSession.

    That way I only lookup the home once, and the remote gets pinned to a user. Also with clustering, the remote is a serializable interface and will propogate around a web/app server farm if clustering is supported.

    Thoughts?

    bmatalus@fusionally.com
  18.   Actually I am glad to see that what I came up with on my own seems pretty close to what alot of people are doing.
    I basically store an ejbCreator into a servletcontext attribute. The ejbcreator has all ejbHome objects stored as instance variables. These objects are created in the constructor of the ejbcreator class. Ejbobjects are created on a as needed basis and stored in a users session.
    Jeff
  19. I'm fairly new to EJBs ... but if I correctly understand most of the suggestions in this thread, it is to look up the EJBHome just once, keep a reference to it (through the ServletContext), and create the EJBObjects per client request. My question is how do you propagate the user identity down to the EJB? Isn't the SECURITY_PRINCIPAL set in the initial context when the EJBHome is looked up? Doesn't that mean, then, that the user identity as far as the beans are concered would always be the same?

    Rino Ong
  20. No. The client-specific data (credentials, etc...) is saved in thread-local storage. An EJB can call InitialContext.getCallerPrincipal() anytime and get accurate results.
  21. Actually I think his point was how do you pass the EJB the client-specific data after you already have a reference to the HOME.

    For instance, when my servlet starts I connect and do a JNDI lookup using a logon for the servlet. Then I want to be able to execute the EJB as the users that login to my servlet. How do you change credentials without having to do a look up?

  22. That strategy introduces a subtle race condition, if clients open multiple browsing windows. Recall that all open windows in the same domain share the same session.

    I think access to shared remote objects must be synchronized.

    Comments?
  23. When you redeploy the beans, those remote interfaces might get broken. Just a thought...

  24. Hot-deployment, on Weblogic 5.1 anyway, requires that the remote interface does not change. A surprising limitation...