Discussions

EJB design: Newbie : How to communicate between Session EJB and Entity EJB

  1. Hello All,

    In the past few days I have been struggling to understand how exactly Session EJB's (remote interfaces) and Entity EJB's (local interfaces) communicate. I have read up on JNDI which seems to be the way to go, but I there is still a few things unclear to me.

    I have created a simple session bean Catalogue. Now I have created a method in Catalogue to lookup my Entity Beans so that I can use them for my business logic. The following method provides, what I think, could be used to obtain a reference to a Entity Bean. I am using CMP, so if that makes any difference in terms of lookup code I would be glad to hear about it.

    // Lookup my entity beans
    public void lookupEntityBeans () throws NamingException {
       Context ctx = new InitialContext();
       Account accountEntity = (Account)ctx.lookup("Account");
       Part partEntity = (Part)ctx.lookup("Part");
     }

    Now from my Catalogue Session Bean, I wish to a get the discount which is associated with a particular customer, which is stored in the Account Entity Bean. Upon retrieving that value I would store it in a local variable. Then get the price of a particular part from a Part Entity Bean and store it in a local variable as well. Then perform my business logic using the values I have extracted from the 2 entity beans.

    // Business Method
    public double computeNewPartPrice (double oldPartPrice) {
       // getPartPrice is an abstract method defined in
       // the local interface
       oldPartPrice = partEntity.getPartPrice();
       tempAccountDiscount = accountEntity.getAccountDiscount();
       newPartPrice = oldPartPrice - tempAccountDiscount;
    }

    Question 1

    Basically, is the above code listings enough to get the necessary information that I need from the entity beans?
    Do I need to declare any JNDI context code in my entity beans or is that done by the container?

    Question 2

    If I want to find say a customer discount value, which is located in the Account Entity Bean, should I use the findByCustomerID(String custID) method OR is it taken care of for me as suggested by Mastering EJB?

    Question 3

    If I use CMP Entity Beans, do I still need a AccountPK class OR is that taken care of by the container as well?

    Thanks
  2. One unrelated question, Is there a way to manage your threads?

    i.e. - delete a thread
         - move a thread to the correct board :p
         - etc?
  3. Hi Izak,

    Please see inline comments

    > Question 1
    >
    > Basically, is the above code listings enough to get the necessary information that I need from the entity beans?
    > Do I need to declare any JNDI context code in my entity beans or is that done by the container?
    >

    The initial context that is used inside the bean is initialized by the container when you do a new InitialContext with proper naming settings. As far as lookup names are concerned there are two approaches:

    1) Spec compliant, standard approach: Declare an ejb reference in the ejb-jar.xml in the source bean to lookup a target bean. This ejb reference is typically defined as "ejb/Account" and "ejb/Part" in the Catalogue session bean. This ejb-reference name can then be mapped to corresponding jndi names of Account and Part bean respectively.

    2) Most of the conatiner vendors allow local jndi names for local entities. IN that case you lookup code above is absolutely correct. In such a case, "Account" and "Part" will become local jndi names.

    > Question 2
    >
    > If I want to find say a customer discount value, which is located in the Account Entity Bean, should I use the findByCustomerID(String custID) method OR is it taken care of for me as suggested by Mastering EJB?
    >
    When you are working on AccountEntity, if there is implicit association of this account with cistomer via pk, then you dont need a finder.
    > Question 3
    >
    > If I use CMP Entity Beans, do I still need a AccountPK class OR is that taken care of by the container as well?
    >
    If you are marking only one of the cmp-fields as primary key you dont need an AccountPK class. However, it is a good practice to have a pk class, in cases where you want to add more cmp-fields to your pk class. In such cases you need not change your code.

    Hemant
    www.pramati.com
  4. Just a few more questions[ Go to top ]

    Hello Hermant,

    > The initial context that is used inside the bean is initialized by the container when you do a new InitialContext with proper naming settings. As far as lookup names are concerned there are two approaches:
    >
    > 1) Spec compliant, standard approach: Declare an ejb reference in the ejb-jar.xml in the source bean to lookup a target bean. This ejb reference is typically defined as "ejb/Account" and "ejb/Part" in the Catalogue session bean. This ejb-reference name can then be mapped to corresponding jndi names of Account and Part bean respectively.
    >

    Do I use the Spec Compliant if I am working with remote interfaces? (i.e. session beans)

    I forgot, but I have already made an entry into my ejb-jar.xml to declare my entity beans inside my session bean, (see code below), although I thought that was necessary if my entity beans and session beans have relationships with each other... which we are trying to do I guess, just never realized it :)

    <pre>
    <session>
     <ejb-ref>
      <ejb-ref-name>ejb/AccountHome</ejb-ref-name>
      <ejb-ref-type>Entity</ejb-ref-type>
      <home>AccountHome</home>
     </ejb-ref>
    </session>
    </pre>

    If I have the following code in my Session Bean Home Interface ..
    <pre>
    Context ctx = new InitialContext();
    Object result = ctx.lookup("java:comp/env/ejb/CatalogHome");
    CatalogHome home = (CatalogHome)PortableRemoteObject.narrow(result,CatalogHome.class);
    </pre>

    How would I programatically use the reference to my EntityBeans defined in ejb-jar.xml? (call the session / entity beans if I used the spec compliant approach)

     
    > > Question 2
    > >
    > > If I want to find say a customer discount value, which is located in the Account Entity Bean, should I use the findByCustomerID(String custID) method OR is it taken care of for me as suggested by Mastering EJB?
    > >
    > When you are working on AccountEntity, if there is implicit association of this account with cistomer via pk, then you dont need a finder.

    Right so just to clarify for myself, I have a PK in Customer called custID, and a PK in Account called accountID. Account also has a field custID which is a FK. So I don't need to a finder method because there is an implicit association, correct?

    Thanks for the response
  5. Just a few more questions[ Go to top ]

    Just to clarify what I meant by spec compliant:

    For each type of bean, you can have local or remote set of interfaces.

    1. You can lookup and get both local or remote home interfaces using ejb references. This is a preferred approach.

    2. You can lookup on remote home using jndi names without declaring ejb references. Again like 1, it is spec compliant but tie your code to jndi name literals.

    3. Most vendors allow local jndi names lookup for local home interfaces. Preferred way should be to use ejb references. This is what I meant as non spec compliant. Since you are using ejb references you are ok in this regard.

    >Right so just to clarify for myself, I have a PK in Customer called custID, >and a PK in Account called accountID. Account also has a field custID which is >a FK. So I don't need to a finder method because there is an implicit >association, correct?

    No, unless you have inform the container about this implicit association in some way (for example by using a cmr-field or relationship field between Customer and Account) or by declaring custID as a cmp field in the account bean and using on your own.

    Based on what I have understood so far, you can work out the following:

    AccountBean{
      //cmp-fields
      public abstract String getAccountID();
      public abstract void setAccountID(String accountID);
      ...
    }

    CustomerBean{
      //cmp-fields
      public abstract String getCustID();
      public abstract void setCustID(String custID);
      ...

      //cmr-field account which is 1:1 between Customer and Account
      //This will establist an implict association when you map cmr
      //cmr during or-mapping. You typically specify
      //CustTable.custID = AccountTable.custID
      public abstract Account getAccount();
      public abstract void setAccount(Account account);
    }


    snippet in ejb-jar.xml
    <pre>
    <session>
     <ejb-ref>
      <ejb-ref-name>ejb/CustomerHome</ejb-ref-name>
      <ejb-ref-type>Entity</ejb-ref-type>
      <home>CustomerHome</home>
     </ejb-ref>
     <ejb-ref>
      <ejb-ref-name>ejb/PartHome</ejb-ref-name>
      <ejb-ref-type>Entity</ejb-ref-type>
      <home>PartHome</home>
     </ejb-ref>
    </session>
    </pre>

    public CatalogueSessionBean extends javax.ejb.SessionBean{
    ...
    // Lookup my entity beans
    public double computeNewPartPrice (String custId, String partId) {
       Context ctx = new InitialContext();
       CustomerHome custHome = (CustomerHome)ctx.lookup("java:comp/env/ejb/CustomerHome");
       Customer cust = custHome.findByPrimaryKey(custId);
       PartHome partHome = (PartHome)ctx.lookup("java:comp/env/ejb/PartHome");
       Part partEntity = partHome.findByPrimaryKey(custId);

       // getPartPrice is an abstract method defined in
       // the local interface
       double oldPartPrice = partEntity.getPartPrice();
       //Use cmr-fields
       Account accountEntity = cust.getAccount();
       tempAccountDiscount = accountEntity.getAccountDiscount();
       newPartPrice = oldPartPrice - tempAccountDiscount;
       //Can set it on part
       //partEntity.setPartPrice(newPartPrice);
       return newPartPrice;
     }

    Hemant
    www.pramati.com

    <vendor>
    If you are using any other IDE please check out the options to do the same. If not, you can try our Pramati Studio (an IDE for J2EE applications) which can really help you quickly write beans with relationships etc. It automatically creates ejb-jar.xml with references and other xmls behind the scene.
    <vendor>
  6. Just a few more questions[ Go to top ]

    Thanks alot Hemant, it's all much clearer now.