Discussions

J2EE patterns: Lazy Load Entity Bean References

  1. Lazy Load Entity Bean References (9 messages)

    In most typical scenarios, entity beans need to hold references to other entity beans, be it one to one, one to many, etc. So how to we deal with this when we are using Bean Managed Persistence (BMP)? The most straight forward way is to initialize all your references in ejbLoad(). That way your entity bean will be ready to use with all references intact, once activated. Now consider the effects of instantiating all your references in ejbLoad. The loading of one entity bean would cause the loading of potentially hundreds of other entity beans! If all you wanted to do was something simple like getting its Details Object, this is a tremendous waste of resources.

    The solution is to lazy load your entity beans. This is a flashy term that basically means don't instantiate and save a reference to another entity bean until you need to.

    For example, consider a forum messaging system. A Message entity bean should have a reference to its containing thread, the User that posted it, and its parent Message (if it is a reply). To lazy load your beans, you would have the following code in your "getThread" or your "getUser" methods:

    public Thread getThread() throws EJBException {

       if ( this.myThread != null )
       {
          return this.myThread;
       }

       try //to lazy initialize the thread this Message is in
       {
          this.myThread = (Thread) this.aThreadHome.findByPrimaryKey( new ThreadPK(this.threadPK) );
          return this.myThread;
       }
       catch( Exception e )
       {
          //log error here
          throw new EJBException( e );
       }
    }


    public User getUser() throws EJBException {

       if ( this.myUser != null )
       {
          return this.myUser;
       }

       try //to lazy initialize
       {
          this.myUser = (User) this.aUserHome.findByPrimaryKey( new UserPK(this.userPK) );
          return this.myUser;
       }
       catch( Exception e )
       {
          //log error here
          throw new EJBException( e );
       }
    }

    Where this.myThread, this.myUser are references to a Thread and User Entity bean. Now don't forget to clear out all your references in ejbPassivate, since these references are specific to this particular entity bean instance:

    /**
     * Called by Container. Releases held resources for
     * passivation.
     */
    public void ejbPassivate() {

       //nullify our other entity bean references since they may reflect
       //reflect bean refernces of a different entity bean
       this.myThread = null;
       this.myUser = null;

    }

    Using this strategy will result in more memory efficient, faster Enterprise Java Bean applications!



    Threaded Messages (9)

  2. This strategy can be combined with the ValueObject pattern to pretty effectively minimize resource utilization at runtime.

    The ValueObject would contain other uninstantiated ValueObjects. At the time they are first used, they would be fully realized and initialized. We introduce some latecy here, but by intelligently selecting the granularity of our ValueObjects... we can make this latency negligable.

    Also by introducing a "projection" metaphor to the ValueObject, we can control during the request for data the amount(number of fields) of data that we will get back at any one time.

    Thoughts?

    bmatalus@fusionally.com
  3. Brian,
     
      What do you mean by a "projection metaphor"?

      Also, how would a ValueObject (or Details Object, as we call them here on TheServerSide), know to lazy initialize its references to other value objects? This would require access to the EJB API's, which would defeat the purpose of the data encapsulation provided by the Details Object.

      Am I misunderstanding your architecture?

    Floyd
  4. Lazy Load Entity Bean References[ Go to top ]

    Floyd,
      This sound like a great pattern and I intend to use it in my BMP for a project I'm on but I have a question. I'm fairly new to EJB and I beleive I know them failry well but I'm having trouble with these 2 lines:

    this.myThread = (Thread) this.aThreadHome.findByPrimaryKey( new ThreadPK(this.threadPK) );


    this.myUser = (User) this.aUserHome.findByPrimaryKey( new UserPK(this.userPK) );
          
    I understand that this.myUser/myThread are member variables of the Message object, I just don't understand the last bit...are you casting the Message object to be a Thread/User object and accessing an EJBHome Interface reference stored with in that object for the findbyPrimaryKey();

    Perhaps a complete example with source code would explain this better.

    Mike

  5. Lazy Load Entity Bean References[ Go to top ]

    Mike

    this.myThread = (Thread) this.aThreadHome.findByPrimaryKey( new ThreadPK(this.threadPK) );

    This is not casting Message object to Thread object. I thing you are right this.myThread is member variables of the Message object. this.aThreadHome is member variable of Message object too and here is stored reference to EJBhome object of Thread EJB. Then findByPrimaryKey method of this member variables (EJBhome object for Thread EJB) is called and the result is casted to Thread.

    Vlastik
  6. Lazy Load Entity Bean References[ Go to top ]

    hello,
      can u show me how myThread variable is initialized or declared in your entity bean.
    I want to know what would be best framwork or way to maintain relations among my BMP entity beans.If i have ejb-ref in my DD , and use home references in my ejbload()for lazy reference.Is this mechanism works potentially to save from loading long hierarchical relations.
     Then what is the differece calling other entity beans by looking up the entity beans that directly referred in DD and looking up entity beans that are in other containers.

    Please can u explain me how is this ejb-ref helps me for managing my BMP entity bean internal relations.

    Appaji.
  7. Lazy Load Entity Bean References[ Go to top ]

    Also I want to know is this a performance issue to store home reference in other entity beans and use it for lazy reference since this becomes a remote call to other entity bean. Can i make this possible in a session bean wrapping entity beans and mentioning all referred entity beans references ejb-ref in session bean DD.

    Can anyone comment on this.

    Appaji.
  8. Hi appaji
    We are showing in the DD about the referred Bean is beacuse the container will lookup for u and keep the connection to that bean always.
    Also,We can't make Socket connections to the outside world from the EJB.But when u make the lookup,u have to make a Scoket connection.To avoid this,the container will do all for u if u just give in ejb-ref in DD.
    by
    idhaya
  9. I understand that you should only obtain an EJB object when you need it. This is the main concept in lazy loading, if I understand things.

    But what about home interfaces? Where should you do the JNDI lookup to establish the home interface? Often times, I establish the home interface just before I find the EJB object that I need. Is this OK? What are other good alternatives? How expensive is it to create a home interface?

    More specifically, let's say I have a Session bean that calls other EJBs. One method in my session bean needs to find a User EJB. Should I establish the UserHome reference in the method right before I need it? If not, what are good alternatives?

    Beyond Session beans, I often ask myself the same questions when writing client applications. You could make the home interface a class variable accessible to all methods. Or you could create the home interface right before you need it within individual methods.

    Anyone have some thoughts? Thanks for any insight!
  10. Read about Service Locator pattern.

    Willow