Skip Headers
Oracle® Application Server Application Developer's Guide
10g Release 2 (10.1.2)
Part No. B14000-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

10 Updating EJBs to Use EJB 2.0 Features

This chapter describes the implementation details of the second sample application. The first part of the chapter describes the business methods in the application. The second part describes how the EJBs in the application map to database tables.

Contents of this chapter:

10.1 Overview of the Second Sample Application

The second sample application provides business operations that clients can invoke through Web Services. The third sample application is an example of such a client.

The business operations involve accessing and updating data in the HR schema, which is the same schema used in the first sample application.

The application uses EJBs to implement the business operations. The EJBs use features such as container-managed persistence, EJB query language, local interfaces, and container-managed relationships.

Note that the second sample application does not contain any JSPs or servlets because it does not display any pages. The application simply contains EJBs and some supporting Java classes. Its operations are accessed by clients through Web Services, and it is the client applications that display the results.

10.1.1 Business Operations in the Second Sample Application

The second sample application implements these business operations:

  • List all benefits

  • Add new benefits

  • Count the number of employees

  • List the benefits an employee has

  • Count the number of employees enrolled in a specified benefit

To implement the operations, the application uses entity beans and a session bean:

Table 10-1 EJBs in the Second Sample Application

EJB Description
Employee (entity bean) The Employee entity bean contains fields for employee information such as employee ID, first name, last name, address, and benefits the employee has selected.
Benefit (entity bean) The Benefit entity bean contains fields for benefit information such as benefit ID, benefit name, benefit description, and employees who have that benefit.
EmployeeBenefitManager (session bean) The EmployeeBenefitManager EJB is a stateless session bean that provides the interface for the application's clients. Clients call methods in the EmployeeBenefitManager to access the application's business operations. These methods, in turn, invoke methods in the Employee and Benefit entity beans. Clients do not call the Employee and Benefit beans directly.

Later sections in this chapter describe each business operation in detail.

Entity beans provide a flexible model: they can create new tables and columns and populate them, or they can work with existing tables. In the sample application, they work with existing tables.

Figure 10-1 shows how the EJBs in the application work together. It shows:

  • business methods in the EmployeeBenefitManager session bean

  • some of the fields and methods in the Employee and Benefit entity beans

  • an employee can be associated with zero or more benefits, and a benefit can be associated with zero or more employees

Figure 10-1 UML Diagram for the EJBs

Description of uml-model.gif follows
Description of the illustration uml-model.gif

10.1.2 Design of the Second Application

The second sample application follows the "session facade" design pattern. This means that the methods in the entity beans are hidden from clients. Instead, clients call methods in the EmployeeBenefitManager session bean to invoke business operations. Methods in the session bean invoke other methods in the entity beans. Clients do not even know about the existence of the entity beans.

10.1.3 EJB 2.0 Features Used by the Entity Beans

The entity beans use features from the EJB 2.0 specification. In particular, they use these features:

  • container-managed persistence (CMP) instead of bean-managed persistence (BMP)

  • container-managed relationships between employees and their benefit items

  • local interfaces instead of remote interfaces

  • EJB Query Language (QL)

Note that these features do not apply to the EmployeeBenefitManager session bean. This session bean uses a remote interface (not local interface) so that remote clients can invoke it. Remote clients are clients that run in a different JVM or in a different application. If the session bean used a local interface, then only clients running in the same application can invoke it.

Persistent Fields in the Entity Beans

The entity beans contain fields for data that are stored in database tables. Examples of fields in the Employee entity bean are Employee ID, First Name, Last Name, and Hire Date. Examples of fields in the Benefit entity bean are Benefit ID, Benefit Name, and Description.

To enable the EmployeeBenefitManager session bean to access the fields in the entity beans, you do these tasks for each field:

  • Declare accessor methods (get and set methods) for each field in the local interface (EmployeeLocal.java and BenefitLocal.java).

    For example, for the First Name field, you would have the getFirstName and setFirstName methods.

  • Create abstract methods for the accessor methods in the bean implementation class (EmployeeBean.java and BenefitBean.java).

    The container takes the abstract methods and implements the code to perform the get or set operation. The container connects to the database to get or set the values.

  • Map the fields to table columns in the orion-ejb-jar.xml file. This is required because the field names do not match the names of the table columns in the database.

10.2 Details of employeeCount Method

To get the number of employees, a client calls the employeeCount method in the EmployeeBenefitManager session bean. This method calls the corresponding method in the Employee entity bean. The client does not invoke the method in the Employee entity bean directly.

// EmployeeBenefitManagerBean.java
public int employeeCount()
{
   try
   {
      return getEmployeeLocalHome().employeeCount();      
   }
   catch(Exception e)
   {
      e.printStackTrace();
      throw new EJBException(e);
   }
}

// The following method gets the local home object for the Employee bean.
private EmployeeLocalHome getEmployeeLocalHome() throws NamingException
{
   final InitialContext context = new InitialContext();
   return (EmployeeLocalHome)context.lookup("java:comp/env/ejb/EmployeeLocal"); 
}


In the EmployeeLocalHome interface, the employeeCount method executes the ejbHomeEmployeeCount method in the EmployeeBean class:

// EmployeeBean.java
public int ejbHomeEmployeeCount()
{
   try
   {
      return ejbSelectAllEmployees().size();
   }
   catch(FinderException fe)
   {
      return 0;
   }
}

public abstract Collection ejbSelectAllEmployees() throws FinderException;

The ejbSelectAllEmployees method uses EJB QL to get its results. The name of the method and its EJB QL statement are defined in the ejb-jar.xml file:

// ejb-jar.xml
<entity>
   <description>Entity Bean ( CMP )</description>
   <display-name>Employee</display-name>
   <ejb-name>Employee</ejb-name>
   ... lines omitted ...
   <abstract-schema-name>Employee</abstract-schema-name>
   ... lines omitted ...
   <query>
      <query-method>
         <method-name>ejbSelectAllEmployees</method-name>
         <method-params/>
      </query-method>
      <ejb-ql>select object(e) from Employee e</ejb-ql>
   </query>
   ... lines omitted ...
</entity>

The <method-name> element specifies the name of the method, and the <ejb-ql> element specifies the EJB QL statement to execute when the method is invoked. The <abstract-schema-name> element specifies the name to use in EJB QL statements to identify entity beans.

In the EJB QL statement, the Employee reference matches the name specified in the <abstract-schema-name> element. The statement selects all Employee entity beans and returns a Collection of Employee beans to the ejbHomeEmployeeCount method. The method uses the size method to determine the number of elements in the Collection.

10.3 Details of listBenefits Method

To get a list of all benefits, a client calls the listBenefits method in the EmployeeBenefitManager session bean. This method calls the findAll method in the Benefit bean.

// EmployeeBenefitManagerBean.java
public BenefitModel[] listBenefits()
{
   int count = 0;
   BenefitModel[] returnBenefits;
   Collection allBenefits = null;
   BenefitLocal benefitLocal = null;
   BenefitModel benefit = null;

   try
   {
      allBenefits = getBenefitLocalHome().findAll();
      returnBenefits = new BenefitModel[allBenefits.size()];
      Iterator iter = allBenefits.iterator();
      while(iter.hasNext())
      {
         benefitLocal = (BenefitLocal)iter.next();
         benefit = new BenefitModel(benefitLocal.getBenefitId(),
                                    benefitLocal.getName(),
                                    benefitLocal.getDescription());
         returnBenefits[count++]=benefit;
      }
      return returnBenefits;
   }
   catch(Exception e)
   {
      e.printStackTrace();
      throw new EJBException(e);
   }
}


The findAll method is a special method. You declare the method in the BenefitLocalHome interface, but do not implement it in the BenefitBean class. The container implements it for you. You do not have to define a query statement for the method in the ejb-jar.xml file (it gets generated automatically for you).

Example 10-1 BenefitLocalHome.java

// BenefitLocalHome.java
public interface BenefitLocalHome extends EJBLocalHome{
   BenefitLocal create() throws CreateException;
   BenefitLocal findByPrimaryKey(Long primaryKey) throws FinderException;
   Collection findAll() throws FinderException;
   BenefitLocal create(Long benefitId, String name) throws CreateException;
   BenefitLocal findByName(String name) throws FinderException;}

The findAll method returns a Collection of BenefitLocal instances. The listBenefits method iterates through the Collection and saves the members into an array. It then returns an array of BenefitModel instances to the client.

The BenefitModel class is a JavaBean that simply contains the fields for a Benefit object.

// BenefitModel.java
package empbft.component.model;
import java.io.Serializable;
public class BenefitModel implements Serializable {
   private Long _id;
   private String _name;
   private String _description;
   /**
    *  No-Arg constructor required to satisfy contract as a JavaBean. Do 
    *  <B>NOT</B> use this constructor.  It will throw a RuntimeException
    *  when used.
    *  
    *  @throws RuntimeException
    */
   public BenefitModel()
   {
      throw new RuntimeException(getClass().getName() +
                     ": This is not a valid constructor for this object.");
   }
   /** 
    * Constructs a new benefit model containing the details for the benefit.
    */
   public BenefitModel(Long id, String name, String description)
   {
      this._id = id;
      this._name = name;
      this._description = description;
   }

   public String getDescription()   {      return _description;   }
   public void  setDescription(String new_description)
   {
      _description = new_description;
   }

   public Long getId()  {      return _id;  }
   public void setId(Long new_id)   {      _id = new_id;   }

   public String getName()   {      return _name;  }
   public void setName(String new_name)   {    _name = new_name;  }
}

10.4 Details of addNewBenefit Method

To add a new benefit, a client calls the addNewBenefit method in the EmployeeBenefitManager session bean. This method calls the create method in the BenefitLocalHome interface.

// EmployeeBenefitManagerBean.java
public void addNewBenefit(Long benefitId, String benefitName,
                          String benefitDescription)
{
   try
   {
      BenefitLocal newBenefit =
                       getBenefitLocalHome().create(benefitId,benefitName);
      if(benefitDescription!=null)
         newBenefit.setDescription(benefitDescription);
   }
   catch(Exception e)
   {
      e.printStackTrace();
      throw new EJBException("Error adding new benefit item : " + e);
   }
}

The create method in the BenefitLocalHome interface executes the ejbCreate method in the BenefitBean class. In the ejbCreate method, you populate the benefit ID and name fields, and return null. The container does the actual work of creating the bean and returning the bean to the caller. The return value type for the ejbCreate method is the same as the primary key type for the entity bean.

// BenefitBean.java
public Long ejbCreate(Long benefitId, String name)
{
   setBenefitId(benefitId);
   setName(name);
   return null;
}

The addNewBenefit method then adds a description to the new benefit if the client provided a description.

10.5 Details of listBenefitsOfEmployee Method

To get a list of benefits for a specified employee, a client calls the listBenefitsOfEmployee method in the EmployeeBenefitManager session bean. This method calls the getBenefits method in the Employee bean, which returns a Collection of Benefit local interface objects for the specified employee.

// EmployeeBenefitManagerBean.java
public BenefitModel[] listBenefitsOfEmployee(long employeeId)
{
   EmployeeLocal employee = null;
   Collection allBenefits = null;
   BenefitModel benefits[];
   BenefitLocal benefit = null;
   BenefitModel benefitModel = null;

   try
   {
      // Find the employee, then get their benefits
      employee = getEmployeeLocalHome().findByPrimaryKey(new Long(employeeId));
      allBenefits = employee.getBenefits();
      benefits = new BenefitModel[allBenefits.size()];
      Iterator iter = allBenefits.iterator();

      int count = 0;
      while(iter.hasNext())
      {
         benefit = (BenefitLocal)iter.next();
         benefitModel = new BenefitModel(
                        (Long)benefit.getPrimaryKey(),
                        benefit.getName(),
                        benefit.getDescription());
         benefits[count++] = benefitModel;
      }
      return benefits;
   }
   catch(NamingException ne)
   {
      ne.printStackTrace();
      throw new EJBException("Could not find Employee " + employeeId);      
   }
   catch(FinderException fe)
   {
      fe.printStackTrace();
      throw new EJBException("Could not find Employee " + employeeId);
   }
}

The listBenefitsOfEmployee method takes an employee ID as an input parameter. It calls the findByPrimaryKey method in the Employee bean to get the desired Employee instance. It then calls the getBenefits method on that instance.

Like other get and set methods, the getBenefits method is an abstract method implemented by the EJB container.

The getBenefits method returns a Collection to the listBenefitsOfEmployee method (in EmployeeBenefitManager), which then extracts the contents of the Collection into an array of BenefitModel's to return to the client.

Note that the listBenefitsOfEmployee and countEnrollmentsForBenefit methods (described in the next section) use both the Employee and Benefit entity beans. This requires a relationship field.

10.6 Details for countEnrollmentsForBenefit Method

To get the number of employees enrolled in a specified benefit, a client calls the countEnrollmentsForBenefit method in the EmployeeBenefitManager session bean. This method calls the getEmployees method in the Benefit bean.

// EmployeeBenefitManagerBean.java
public int countEnrollmentsForBenefit(long benefitId)
{
   try
   {
      BenefitLocal benefit =
                  getBenefitLocalHome().findByPrimaryKey(new Long(benefitId));
      Collection employees = benefit.getEmployees();
      return employees.size();
   }
   catch(Exception e)
   {
      e.printStackTrace();
      throw new EJBException(e);
   }
}

The EmployeeBenefitManager session bean uses the findByPrimaryKey method to locate the Benefit bean instance that represents the benefit in question. The findByPrimaryKey method is implemented for you by the container. You declare it in the BenefitLocalHome interface (shown in Example 10-1), but do not define it in the BenefitBean class.

The countEnrollmentsForBenefit method calls the getEmployees method on the instance returned by findByPrimaryKey to get a list of employees, and then calls the size method to get the number of employees in the list.

Note that the countEnrollmentsForBenefit method and listBenefitsOfEmployee method (described in the previous section) use both the Employee and Benefit entity beans. This requires a relationship field.

10.7 Entity Beans and Database Tables

The Employee and Benefit entity beans use container-managed persistence (CMP), which means you have to map the persistent fields in the entity beans to table columns. (You can set the container to do automatic mapping.)

Most of the fields in the Employee and the Benefit entity beans map to columns in the EMPLOYEES and BENEFIT tables in the database. Because the beans have different names from the tables, and the names of the fields in the beans do not match the column names, you have to map the names manually in the ejb-jar.xml and orion-ejb-jar.xml files.

10.7.1 Persistent Fields in the ejb-jar.xml File

In the ejb-jar.xml file, the <cmp-field><field-name> elements define the persistent fields. For example:

// ejb-jar.xml
<entity>
  <description>Entity Bean ( CMP )</description>
  <display-name>Employee</display-name>
  <ejb-name>Employee</ejb-name>

  <local-home>empbft.component.employee.ejb20.EmployeeLocalHome</local-home>
  <local>empbft.component.employee.ejb20.EmployeeLocal</local>
  <ejb-class>empbft.component.employee.ejb20.EmployeeBean</ejb-class>
  <persistence-type>Container</persistence-type>
  ... lines omitted ...
  <cmp-field><field-name>employeeId</field-name></cmp-field>
  <cmp-field><field-name>firstName</field-name></cmp-field>
  <cmp-field><field-name>lastName</field-name></cmp-field>
  <cmp-field><field-name>emailAddress</field-name></cmp-field>
  <cmp-field><field-name>phoneNumber</field-name></cmp-field>
  <cmp-field><field-name>hireDate</field-name></cmp-field>
  ... lines omitted ...
</entity>

<entity>
   <description>Entity Bean ( CMP )</description>
   <display-name>Benefit</display-name>
   <ejb-name>Benefit</ejb-name>

   <local-home>empbft.component.benefit.ejb20.BenefitLocalHome</local-home>
   <local>empbft.component.benefit.ejb20.BenefitLocal</local>
   <ejb-class>empbft.component.benefit.ejb20.BenefitBean</ejb-class>
   <persistence-type>Container</persistence-type>
   <prim-key-class>java.lang.Long</prim-key-class>
   ... lines omitted ...
   <cmp-field><field-name>benefitId</field-name></cmp-field>
   <cmp-field><field-name>name</field-name></cmp-field>
   <cmp-field><field-name>description</field-name></cmp-field>
   ... lines omitted ...
</entity>

10.7.2 Persistent Fields in the Local Interface

In the local interfaces, EmployeeLocal and BenefitLocal, for each persistent field, you declare a pair of accessor methods (get and set methods).

// EmployeeLocal.java
package empbft.component.employee.ejb20;
import javax.ejb.EJBLocalObject;
import java.util.Collection;
import java.sql.Timestamp;
public interface EmployeeLocal extends EJBLocalObject {
   Long getEmployeeId();
   void setEmployeeId(Long newEmployeeId);
   String getFirstName();
   void setFirstName(String newFirstName);
   String getLastName();
   void setLastName(String newLastName);
   ... lines omitted ...
   Timestamp getHireDate();
   void setHireDate(Timestamp newHireDate);
   ... lines omitted ...
   Collection getBenefits();
   void setBenefits(Collection newBenefits);}

// BenefitLocal.java
package empbft.component.benefit.ejb20;
import javax.ejb.EJBLocalObject;
import java.util.Collection;
public interface BenefitLocal extends EJBLocalObject {
   Long getBenefitId();
   void setBenefitId(Long newBenefitId);
   String getName();
   void setName(String newName);
   String getDescription();
   void setDescription(String newDescription);
   Collection getEmployees();
   void setEmployees(Collection newEmployees);}

10.7.3 Persistent Fields in the orion-ejb-jar.xml File

You map the persistent fields in the entity beans to table columns using the orion-ejb-jar.xml file. The following lines from the orion-ejb-jar.xml file show the mappings of some fields in the Employee entity bean.


Tip:

If you do not want to create the orion-ejb-jar.xml file from scratch, let OC4J generate a version of the file. You can then edit the generated file and enter the correct values. To do this:
  1. Deploy the application without the orion-ejb-jar.xml file. OC4J generates the orion-ejb-jar.xml file.

  2. Edit the generated orion-ejb-jar.xml file, which is located in the ORACLE_HOME/j2ee/home/application-deployments/<app-name>/<ejb-module-name> directory.

  3. Place the edited file in the same directory as the ejb-jar.xml file, and redeploy the application.


// orion-ejb-jar.xml
<entity-deployment name="Employee" copy-by-value="false"
                   data-source="jdbc/OracleDS"
                   exclusive-write-access="false" location="Employee"
                   table="EMPLOYEES">
   <primkey-mapping>
      <cmp-field-mapping name="employeeId" persistence-name="EMPLOYEE_ID"
                                           persistence-type="number(6)"/>
   </primkey-mapping>
   <cmp-field-mapping name="firstName" persistence-name="FIRST_NAME"
                                       persistence-type="VARCHAR2(20)"/>
   <cmp-field-mapping name="lastName"  persistence-name="LAST_NAME"
                                       persistence-type="VARCHAR2(25)"/>
   <cmp-field-mapping name="hireDate"  persistence-name="HIRE_DATE"
                                       persistence-type="DATE"/>
   ... lines omitted ...
</entity-deployment>

Table 10-2 describes some attributes in the <entity-deployment> element.

Table 10-2 Description of Some Attributes in the <entity-deployment> Element

Attribute Description
name Identifies the entity bean. This value matches the name specified in the <ejb-name> element in the ejb-jar.xml file.
table Identifies the table in the database.
location Specifies the JNDI name of the entity bean.
data-source Identifies the database. This value refers to the database pointed to in the data-sources.xml file.

The <cmp-field-mapping> element maps fields to columns. The name attribute specifies the field name, and persistence-name specifies the column name.

10.8 Relationship Fields in the Entity Beans

Most of the persistent fields in the Employee and Benefit entity beans map cleanly to corresponding columns in the EMPLOYEES and BENEFITS tables in the database. Also, the countEmployees method accesses the Employee bean only, and the listBenefits and the addNewBenefit methods access the Benefit bean only.

However, the listBenefitsOfEmployee and the countEnrollmentsForBenefit methods use both beans each.

For these two methods to work, you need to set up a many-to-many relationship between the Employee and Benefit entity beans. The relationship type is many-to-many so that you can look up benefits if you know an employee ID, and you can look up employees if you know a benefit ID.

To determine which employees have which benefits, the many-to-many relationship needs to access the EMPLOYEE_BENEFIT_ITEMS table in the database. This is an association table that enables an employee to have more than one benefit, and a benefit to be associated with more than one employee.

Table 10-3 shows some sample rows in the EMPLOYEE_BENEFIT_ITEMS table. The sample rows show that employee ID 101 has two benefits, and benefit ID 1 has two enrollees.

Table 10-3 Sample Data in EMPLOYEE_BENEFIT_ITEMS Table

EMPLOYEE_ID BENEFIT_ID ELECTION_DATE
101 1 1/5/2003
101 2 1/5/2003
102 1 1/6/2003

You set up relationships in the ejb-jar.xml file using the <relationships> element. Under this parent element, the <ejb-relation> element defines each relationship.

Relationships work with fields. The names of the relationship fields are defined in the <cmr-field-name> element. In this case, the names of the relationship fields are "benefits" and "employees".

// ejb-jar.xml
<relationships>
   <ejb-relation>
      <ejb-relation-name>Employee-Has-Benefits</ejb-relation-name>

      <ejb-relationship-role>
         <ejb-relationship-role-name>Employee-Has-Benefits
                                   </ejb-relationship-role-name>
         <multiplicity>Many</multiplicity>
         <relationship-role-source>
            <ejb-name>Employee</ejb-name>
         </relationship-role-source>
         <cmr-field>
            <cmr-field-name>benefits</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
         </cmr-field>
      </ejb-relationship-role>

      <ejb-relationship-role>
         <ejb-relationship-role-name>Benefits-Are-For-Employees
                                   </ejb-relationship-role-name>
         <multiplicity>Many</multiplicity>
         <relationship-role-source>
            <ejb-name>Benefit</ejb-name>
         </relationship-role-source>
         <cmr-field>
            <cmr-field-name>employees</cmr-field-name>
            <cmr-field-type>java.util.Collection</cmr-field-type>
         </cmr-field>
      </ejb-relationship-role>
   </ejb-relation>
</relationships>

Relationship fields have these features in common with persistent fields:

Example 10-2 <entity-deployment> Section for Employee Entity Bean

// orion-ejb-jar.xml
<entity-deployment name="Employee" copy-by-value="false"
                       data-source="jdbc/OracleDS"
                       exclusive-write-access="false" location="Employee"
                       table="EMPLOYEES">
   ... other cmp-field-mapping elements omitted ...
   <cmp-field-mapping name="benefits">
      <collection-mapping table="EMPLOYEE_BENEFIT_ITEMS">

         <primkey-mapping>
            <cmp-field-mapping name="employeeId">
               <entity-ref>
                  <cmp-field-mapping name="employeeId"
                                     persistence-name="EMPLOYEE_ID"
                                     persistence-type="NUMBER(6)"/>
               </entity-ref>
            </cmp-field-mapping>
         </primkey-mapping>

         <value-mapping type="empbft.component.benefit.ejb20.BenefitLocal">
            <cmp-field-mapping name="benefitId">
               <entity-ref>
                  <cmp-field-mapping name="benefitId"
                                     persistence-name="BENEFIT_ID"
                                     persistence-type="NUMBER(6)"/>
               </entity-ref>
            </cmp-field-mapping>
         </value-mapping>
      </collection-mapping>
   </cmp-field-mapping>
</entity-deployment>

Note the following:

Example 10-3 shows the contents of the <entity-deployment> element for the Benefit entity bean. Its contents are similar to that of the Employee bean.

Note that the values in the <primkey-mapping> and the <value-mapping> elements are reversed from the Employee beans. The <primkey-mapping> element for the Benefit bean specifies the BENEFIT_ID column, and the <value-mapping> element specifies the EMPLOYEE_ID column.

Example 10-3 <entity-deployment> Section for the Benefit Entity Bean

// orion-ejb-jar.xml
<entity-deployment name="Benefit" copy-by-value="false"
                       data-source="jdbc/OracleDS"
                       exclusive-write-access="false" location="Benefit"
                       table="BENEFITS">
   <primkey-mapping>
      <cmp-field-mapping name="benefitId"
                         persistence-name="BENEFIT_ID"
                         persistence-type="number(6)"/>
   </primkey-mapping>
   <cmp-field-mapping name="name"
                      persistence-name="BENEFIT_NAME"
                      persistence-type="varchar2(50)"/>
   <cmp-field-mapping name="description"
                      persistence-name="BENEFIT_DESCRIPTION"
                      persistence-type="varchar2(255)"/>

   <cmp-field-mapping name="employees">
      <collection-mapping table="EMPLOYEE_BENEFIT_ITEMS">

         <primkey-mapping>
            <cmp-field-mapping name="benefitId">
               <entity-ref home="Benefit">
                  <cmp-field-mapping name="benefitId"
                                     persistence-name="BENEFIT_ID" />
               </entity-ref>
            </cmp-field-mapping>
         </primkey-mapping>

         <value-mapping type="empbft.component.employee.ejb20.EmployeeLocal">
            <cmp-field-mapping name="employeeId">
               <entity-ref home="Employee">
                  <cmp-field-mapping name="employeeId"
                                     persistence-name="EMPLOYEE_ID" />
               </entity-ref>
            </cmp-field-mapping>
         </value-mapping>
      </collection-mapping>
   </cmp-field-mapping>
</entity-deployment>