Developing a CMP Bean

Thursday Jul 24th 2003 by Saleem Siddiqui, Michael Landy, & Jeff Swisher
Share:

Discover how to build, deploy, and use CMP (container managed persistence) beans to split the work between the component developer and the container within your Java application.


This material is from the book JBuilder Developer's Guide.

© Copyright Sams Publishing. All rights reserved.


It is now time to look at the process of building an entity bean. We will develop a simple CMP bean, but spend most of our time investigating and perfecting the process.

The process has some similarities to creating session beans. The following is the process we are going to use to investigate and build an entity bean:

  • Implement the home interface.

  • Define the appropriate finder methods.

  • Implement the component interface.

  • Define the bean implementation class.

  • Build the deployment descriptor.

  • Deploy the bean.

  • Test the bean.

Defining the Home Interface

The home interface for an entity bean is similar to the home interface of a session bean. To review, its purpose is to create an instance, find existing instances, or remove an instance; the same rules apply to an entity bean (see Listing 1).

Listing 1 Home Interface for Our Employee Entity Bean

import javax.ejb.*;
import java.util.*;

public interface EmployeeHome extends javax.ejb.EJBLocalHome {
 public Employee create(Short empNo) throws CreateException;
 public Employee findByPrimaryKey(Short empNo) throws FinderException;
}

The create() method is used to create an instance of a class based on this primary key. For our employee table, the empNo is the primary key, thus we will also use empNo as the primary key of our entity bean. The second method type is called a finder method. With entity beans, to create an instance we use the create() method, but finding an existing instance is just as important if not more important. With that requirement, we need finder methods to provide the capability to locate a specific instance or collection of instances of data.

The findByPrimaryKey() is a method that has an argument representing the primary key; in our case, it is empNo. This searches for an employee with the given primary key either returning a remote interface to the instance or through an exception.


Note

The findByPrimaryKey() method is required by all entity beans; any other finders are optional.


Finder methods do not just return a single instance, but they can also return a collection of instances. These types of finder methods are typically used when the primary key or an alternative unique key is not used. For example, we might want to be able to find employees who have a certain salary range, as shown in Listing 2. This finder method should return a collection of employees rather than a single instance.

Listing 2 Home Interface for Our Employee Entity Bean with the Addition of New Finder Methods

import javax.ejb.*;
import java.util.*;
import java.math.*;

public interface EmployeeHome extends javax.ejb.EJBLocalHome {
 public Employee create(Short empNo) throws CreateException;
 public Collection findSalaryRange(BigDecimal low, BigDecimal high) throws FinderException;
 public Employee findByPrimaryKey(Short empNo) throws FinderException;
}

Notice that the findSalaryRange() does not return a single instance like the findByPrimaryKey() but a java.lang.Collection. This collection contains instances of the primary key, not the entire instance; the container then translates for you this instance into the remote interface. This method might return a huge collection of records, so it is important to make sure that you design the beans appropriately.

Defining the Component Interface

Our Employee interface defines all the methods required for us to access and mutate the data within the bean. For example, setFirstName() and getFirstName() methods are required to get access to the instance variables (see Listing 3).

Listing 3 Component Interface for the Employee Bean

import javax.ejb.*;
import java.util.*;
import java.sql.*;
import java.math.*;

public interface Employee extends javax.ejb.EJBLocalObject {
 public Short getEmpNo();
 public void setFirstName(String firstName);
 public String getFirstName();
 public void setLastName(String lastName);
 public String getLastName();
 public void setPhoneExt(String phoneExt);
 public String getPhoneExt();
 public void setHireDate(Timestamp hireDate);
 public Timestamp getHireDate();
 public void setDeptNo(String deptNo);
 public String getDeptNo();
 public void setJobCode(String jobCode);
 public String getJobCode();
 public void setJobGrade(Short jobGrade);
 public Short getJobGrade();
 public void setJobCountry(String jobCountry);
 public String getJobCountry();
 public void setSalary(BigDecimal salary);
 public BigDecimal getSalary();
 public void setFullName(String fullName);
 public String getFullName();
}

Implementing the Bean

One misconception about CMP beans is that you do not have to have a bean implementation class. This class supplies the necessary implementations required for the container to manage the persistence, as shown in Listing 4.

Listing 4 EmployeeBean Implementation Class

import javax.ejb.*;

abstract public class EmployeeBean implements EntityBean {
 EntityContext entityContext;
 public java.lang.Short ejbCreate(java.lang.Short empNo) throws CreateException {
  setEmpNo(empNo);
  return null;
 }
 public void ejbPostCreate(java.lang.Short empNo) throws CreateException {
  /**@todo Complete this method*/
 }
 public void ejbRemove() throws RemoveException {
  /**@todo Complete this method*/
 }
 public abstract void setEmpNo(java.lang.Short empNo);
 public abstract void setFirstName(java.lang.String firstName);
 public abstract void setLastName(java.lang.String lastName);
 public abstract void setPhoneExt(java.lang.String phoneExt);
 public abstract void setHireDate(java.sql.Timestamp hireDate);
 public abstract void setDeptNo(java.lang.String deptNo);
 public abstract void setJobCode(java.lang.String jobCode);
 public abstract void setJobGrade(java.lang.Short jobGrade);
 public abstract void setJobCountry(java.lang.String jobCountry);
 public abstract void setSalary(java.math.BigDecimal salary);
 public abstract void setFullName(java.lang.String fullName);
 public abstract java.lang.Short getEmpNo();
 public abstract java.lang.String getFirstName();
 public abstract java.lang.String getLastName();
 public abstract java.lang.String getPhoneExt();
 public abstract java.sql.Timestamp getHireDate();
 public abstract java.lang.String getDeptNo();
 public abstract java.lang.String getJobCode();
 public abstract java.lang.Short getJobGrade();
 public abstract java.lang.String getJobCountry();
 public abstract java.math.BigDecimal getSalary();
 public abstract java.lang.String getFullName();
 public void ejbLoad() {
  /**@todo Complete this method*/
 }
 public void ejbStore() {
  /**@todo Complete this method*/
 }
 public void ejbActivate() {
  /**@todo Complete this method*/
 }
 public void ejbPassivate() {
  /**@todo Complete this method*/
 }
 public void unsetEntityContext() {
  this.entityContext = null;
 }
 public void setEntityContext(EntityContext entityContext) {
  this.entityContext = entityContext;
 }
}

The client first calls the create() method of the entity bean's home interface. Remember that this is the client of the bean, not necessarily an end-user client. This then translates through the container to the implementation bean. These methods are called by the container for the persistence to take place properly. Let's take a look in detail at how the bean actually works. The best method to view the operation is to use a sequence diagram.

First, let's look at the creation of a new instance of an entity bean, as shown in Figure 1. The create() method tags arguments, which is typically a signature containing the primary key of an instance. After that, the container takes complete control going forward.


Figure 1
Sequence diagram for a client creating an entity bean.

Second, we might need to remove a bean. The remove() method is called by the client, allowing for the instance to be removed from the data source (see Figure 2). Again, the only call the client needs to make is remove(); the container then manages the rest of the interaction to remove the instance.


Figure 2
Sequence diagram for a client removing an entity bean.

Finally, let's look at a finder method, shown in Figure 3. When the client makes a call to one of the finder methods on the home interface, the home interface uses the data source to return the matching elements either singularly using the remote interface or by a list using a java.lang.Collection.


Figure 3
Sequence diagram for a client using one of the finder methods.

Deployment Descriptor

The role of the deployment descriptor is to ultimately provide information about each EJB that is to be bundled and deployed within a particular JAR file. Its intent is to inform the consumer, in this case the container, what the JAR file contains and how it is to be implemented. If you are developing your bean, it is typically your responsibility to create the deployment descriptor. The deployment descriptor keeps the following information:

  • Defines the types, or names, of the classes for the home/local home and remote/local interfaces and the bean class.

  • JNDI names, which define the name of the interface advertised to the naming service.

  • Fields to enable container managed persistence.

  • Transactional policies for the bean's transactional behavior.

  • Security attributes for the enterprise beans.

  • Deployment-specific information; these include special information for the deployed container brand.

To alleviate the confusion between vendor-specific deployment descriptors and general deployment descriptors, they are divided into two different descriptors. The first of which is the deployment descriptor, which contains the configuration information for our Employee CMP bean (see Listing 5).

Listing 5 Deployment Descriptor Containing Our Employee CMP Bean (ejb-JAR.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-JAR PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-JAR_2_0.dtd">
<ejb-JAR>
  <enterprise-beans>
    <entity>
      <display-name>Employee</display-name>
      <ejb-name>Employee</ejb-name>
      <local-home>com.sams.samples.entity.EmployeeHome</local-home>
      <local>com.sams.samples.entity.Employee</local>
      <ejb-class>com.sams.samples.entity.EmployeeBean</ejb-class>
      <persistence-type>Container</persistence-type>
      <prim-key-class>java.lang.Short</prim-key-class>
      <reentrant>False</reentrant>
      <cmp-version>2.x</cmp-version>
      <abstract-schema-name>Employee</abstract-schema-name>
      <cmp-field>
        <field-name>empNo</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>phoneExt</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>hireDate</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>deptNo</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>jobCode</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>jobGrade</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>jobCountry</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>salary</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>fullName</field-name>
      </cmp-field>
      <primkey-field>empNo</primkey-field>
      <query>
        <query-method>
          <method-name>findBySalaryRange</method-name>
          <method-params>
            <method-param>java.math.BigDecimal</method-param>
            <method-param>java.math.BigDecimal</method-param>
          </method-params>
        </query-method>
        <ejb-ql>select OBJECT(e) from employee e where e.salary between (low,high)</ejb-ql>
      </query>
    </entity>
  </enterprise-beans>
  <assembly-descriptor>
    <container-transaction>
      <method>
        <ejb-name>Employee</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Required</trans-attribute>
    </container-transaction>
  </assembly-descriptor>
</ejb-JAR>

As you look at this descriptor, you will notice that all the information regarding our bean is contained within the deployment descriptor. This descriptor will be deployed in the JAR with the bean. Now let's look at the deployment descriptor specific to an enterprise application server container—specifically, in this case, Borland's Enterprise Server, shown in Listing 6.

Listing 6 Application-Specific Deployment Descriptor for Borland's Enterprise Server (ejb-borland.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-JAR PUBLIC "-//Borland Software Corporation//DTD Enterprise JavaBeans 2.0//EN" 
"http://www.borland.com/devsupport/appserver/dtds/ejb-JAR_2_0-borland.dtd">
<ejb-JAR>
  <enterprise-beans>
    <entity>
      <ejb-name>Employee</ejb-name>
      <bean-local-home-name>Employee</bean-local-home-name>
      <cmp2-info>
        <cmp-field>
          <field-name>empNo</field-name>
          <column-name>EMP_NO</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>firstName</field-name>
          <column-name>FIRST_NAME</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>lastName</field-name>
          <column-name>LAST_NAME</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>phoneExt</field-name>
          <column-name>PHONE_EXT</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>hireDate</field-name>
          <column-name>HIRE_DATE</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>deptNo</field-name>
          <column-name>DEPT_NO</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>jobCode</field-name>
          <column-name>JOB_CODE</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>jobGrade</field-name>
          <column-name>JOB_GRADE</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>jobCountry</field-name>
          <column-name>JOB_COUNTRY</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>salary</field-name>
          <column-name>SALARY</column-name>
        </cmp-field>
        <cmp-field>
          <field-name>fullName</field-name>
          <column-name>FULL_NAME</column-name>
        </cmp-field>
        <table-name>EMPLOYEE</table-name>
      </cmp2-info>
      <property>
        <prop-name>ejb-designer-id</prop-name>
        <prop-type>String</prop-type>
        <prop-value>Employee</prop-value>
      </property>
    </entity>
  </enterprise-beans>
  <table-properties>
    <table-name>EMPLOYEE</table-name>
    <column-properties>
      <column-name>EMP_NO</column-name>
    </column-properties>
    <column-properties>
      <column-name>FIRST_NAME</column-name>
    </column-properties>
    <column-properties>
      <column-name>LAST_NAME</column-name>
    </column-properties>
    <column-properties>
      <column-name>PHONE_EXT</column-name>
    </column-properties>
    <column-properties>
      <column-name>HIRE_DATE</column-name>
    </column-properties>
    <column-properties>
      <column-name>DEPT_NO</column-name>
    </column-properties>
    <column-properties>
      <column-name>JOB_CODE</column-name>
    </column-properties>
    <column-properties>
      <column-name>JOB_GRADE</column-name>
    </column-properties>
    <column-properties>
      <column-name>JOB_COUNTRY</column-name>
    </column-properties>
    <column-properties>
      <column-name>SALARY</column-name>
    </column-properties>
    <column-properties>
      <column-name>FULL_NAME</column-name>
    </column-properties>
    <property>
      <prop-name>datasource</prop-name>
      <prop-type>String</prop-type>
      <prop-value>serial://datasources/DataSource</prop-value>
    </property>
  </table-properties>
  <assembly-descriptor />
</ejb-JAR>

Deploying Your Entity Bean

Deploying the bean is exactly the same as deploying the bean with a session bean. The entity bean we just created must be deployed on an application server before any client can access the bean. The process varies slightly depending on the version or brand of your application server. JBuilder insulates you from most of the differences, but nonetheless you have to know a little bit about your deployment environment. The process for deploying our bean is accomplished in two steps:

  1. Create an EAR node.

  2. Deploy it to the application server.

The topmost archive used for deployment is an Enterprise Archive File (EAR). The EAR file contains all the JAR and WAR files required for deployment and execution of our enterprise application. It also contains an application.xml file describing the manifest to the entire archive. In other words, it allows you to completely package your application into one deliverable, self-contained entity.

Let's now create an EAR file for our application, containing at this point only our session bean:

  1. Choose File, New from the menu and select the Enterprise tab.

  2. Select the EAR node to add to the project.

  3. Specify the name of the EAR file and node name. In this case, keep the name similar to the sample project SampleBeans.

  4. Right-click on the new node SampleBean.EARgrp and select Make. This creates a SampleBean.EAR, and contained within this is an application.xml descriptor.

  5. Right-click on the SampleBean.EARgrp and choose Deploy Your Bean. Note: Make sure that your application server is running; if it is not, start your application server and deploy the bean again.

Using Your Entity Bean

It is easiest to test any bean using the remote interface. If you want to test your local interface, you must communicate to that local interface with another object that encapsulates that call with a remote interface. For example, we will test our local interface using a session bean. But first let's test our entity bean's remote interface. The test client in this case only tests the finder method, as shown in Listing 7.

Listing 7 Test Client for Verifying the Operation of Our Employee Entity Bean (EmployeeTestClient.java)

package testclient;

import javax.naming.*;
import javax.rmi.*;

import com.sams.samples.entity.*;

/**
 * <p>Title: Empoyee Entity Test Client</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2002</p>
 * <p>Company: SAMS Publishing</p>
 * @author SAMS Publishing
 * @version 1.0
 */

public class EmployeeTestClient {
 private EmployeeRemoteHome employeeRemoteHome = null;

 //Construct the EJB test client
 public EmployeeTestClient() {
  try {
   //get naming context
   Context ctx = new InitialContext();

   //look up jndi name
   Object ref = ctx.lookup("EmployeeRemote");

   //cast to Home interface
   employeeRemoteHome = (EmployeeRemoteHome) PortableRemoteObject.narrow(ref,EmployeeRemoteHome.class);

   Short empNo = new Short("5");

   EmployeeRemote employee = employeeRemoteHome.findByPrimaryKey(empNo);

   System.out.println(employee.getFirstName());
   System.out.println(employee.getLastName());
  }
  catch(Exception e) {
   e.printStackTrace();
  }
 }

 
 //-----------------------------------------------------------------------
 // Utility Methods
 //-----------------------------------------------------------------------

 public EmployeeRemoteHome getHome() {
  return employeeRemoteHome;
 }
 //Main method

 public static void main(String[] args) {
  EmployeeTestClient client = new EmployeeTestClient();
  // Use the getHome() method of the client object to call Home interface
  // methods that will return a Remote interface reference. Then
  // use that Remote interface reference to access the EJB.
 }
} 

The other option for our entity bean, or for that matter even a session bean, is a local interface. This local interface is available only to another bean running inside the same JVM. Listing 8 is the session bean developed to test the bean, and Listing 9 is the client used to exercise the session bean.


Note

The purpose of the local interface is simple—performance. This performance gain is accomplished primarily in passing data. With a remote interface, the data is passed by value. In other words, the data is copied and serialized to another object on the client. The local interface passes by reference, giving a huge performance increase.


Listing 8 Session Façade to Access the Employee Entity Bean (EmployeeFacadeBean.java)

package com.sams.samples.ejb;

import javax.ejb.*;
import javax.naming.*;
import javax.rmi.*;


public class EmployeeFacadeBean implements SessionBean {
 SessionContext sessionContext;
 public void ejbCreate() throws CreateException {
  /**@todo Complete this method*/
 }
 public void ejbRemove() {
  /**@todo Complete this method*/
 }
 public void ejbActivate() {
  /**@todo Complete this method*/
 }
 public void ejbPassivate() {
  /**@todo Complete this method*/
 }
 public void setSessionContext(SessionContext sessionContext) {
  this.sessionContext = sessionContext;
 }
 public java.lang.String getEmployeeFirstName(java.lang.Short empNo) {
  try {
   //get naming context
   Context ctx = new InitialContext();

   //look up jndi name
   Object ref = ctx.lookup("java:comp/env/ejb/employee");

   //cast to Home interface
   EmployeeHome employeeHome = (EmployeeHome) PortableRemoteObject.narrow(ref, EmployeeHome.class);

   Employee employee = employeeHome.findByPrimaryKey(empNo);

   return employee.getLastName();
  }
  catch(Exception e) {
   e.printStackTrace();
  }
  return null;
 }
}

Listing 9 Client Testing the Session Façade, Which in Turn Accesses the Employee Entity Bean (EmployeeFacadeTestClient.java)

package testclient;

import com.sams.samples.ejb.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;

/**
 * <p>Title: Session Facade Test Client</p>
 * <p>Description: Testing the entity beans local interface via the session</p>
 * <p>Copyright: Copyright (c) 2002</p>
 * <p>Company: SAMS Publishing</p>
 * @author unascribed
 * @version 1.0
 */

public class EmployeeFacadeTestClient {
 static final private String ERROR_NULL_REMOTE = "Remote interface reference is null. It must be created by calling one of the Home interface methods first.";
 static final private int MAX_OUTPUT_LINE_LENGTH = 100;
 private boolean logging = true;
 private EmployeeFacadeHome employeeFacadeHome = null;
 private EmployeeFacade employeeFacade = null;

 //Construct the EJB test client
 public EmployeeFacadeTestClient() {
  long startTime = 0;
  if (logging) {
   log("Initializing bean access.");
   startTime = System.currentTimeMillis();
  }

  try {
   //get naming context
   Context ctx = new InitialContext();

   //look up jndi name
   Object ref = ctx.lookup("EmployeeFacade");

   //cast to Home interface
   employeeFacadeHome = (EmployeeFacadeHome) PortableRemoteObject.narrow(ref, EmployeeFacadeHome.class);
   if (logging) {
    long endTime = System.currentTimeMillis();
    log("Succeeded initializing bean access.");
    log("Execution time: " + (endTime - startTime) + " ms.");
   }

   java.lang.Short empNo = new java.lang.Short("5");
   EmployeeFacade employeeFacade = this.create();
   System.out.println(employeeFacade.getEmployeeFirstName(empNo));
  }
  catch(Exception e) {
   if (logging) {
    log("Failed initializing bean access.");
   }
   e.printStackTrace();
  }
 }

 //-----------------------------------------------------------------------
 // Methods that use Home interface methods to generate a Remote interface
 // reference
 //-----------------------------------------------------------------------

 public EmployeeFacade create() {
  long startTime = 0;
  if (logging) {
   log("Calling create()");
   startTime = System.currentTimeMillis();
  }
  try {
   employeeFacade = employeeFacadeHome.create();
   if (logging) {
    long endTime = System.currentTimeMillis();
    log("Succeeded: create()");
    log("Execution time: " + (endTime - startTime) + " ms.");
   }
  }
  catch(Exception e) {
   if (logging) {
    log("Failed: create()");
   }
   e.printStackTrace();
  }

  if (logging) {
   log("Return value from create(): " + employeeFacade + ".");
  }
  return employeeFacade;
 }

 //-----------------------------------------------------------------------
 // Methods that use Remote interface methods to access data through the bean
 //-----------------------------------------------------------------------

 public String getEmployeeFirstName(Short empNo) {
  String returnValue = "";
  if (employeeFacade == null) {
   System.out.println("Error in getEmployeeFirstName(): " + ERROR_NULL_REMOTE);
   return returnValue;
  }
  long startTime = 0;
  if (logging) {
   log("Calling getEmployeeFirstName(" + empNo + ")");
   startTime = System.currentTimeMillis();
  }

  try {
   returnValue = employeeFacade.getEmployeeFirstName(empNo);
   if (logging) {
    long endTime = System.currentTimeMillis();
    log("Succeeded: getEmployeeFirstName(" + empNo + ")");
    log("Execution time: " + (endTime - startTime) + " ms.");
   }
  }
  catch(Exception e) {
   if (logging) {
    log("Failed: getEmployeeFirstName(" + empNo + ")");
   }
   e.printStackTrace();
  }

  if (logging) {
   log("Return value from getEmployeeFirstName(" + empNo + "): " + returnValue + ".");
  }
  return returnValue;
 }

 public void testRemoteCallsWithDefaultArguments() {
  if (employeeFacade == null) {
   System.out.println("Error in testRemoteCallsWithDefaultArguments(): " + ERROR_NULL_REMOTE);
   return ;
  }
  getEmployeeFirstName(null);
 }

 //-----------------------------------------------------------------------
 // Utility Methods
 //-----------------------------------------------------------------------

 private void log(String message) {
  if (message == null) {
   System.out.println("-- null");
   return ;
  }
  if (message.length() > MAX_OUTPUT_LINE_LENGTH) {
   System.out.println("-- " + message.substring(0, MAX_OUTPUT_LINE_LENGTH) + " ...");
  }
  else {
   System.out.println("-- " + message);
  }
 }
 //Main method

 public static void main(String[] args) {
  EmployeeFacadeTestClient client = new EmployeeFacadeTestClient();
  // Use the client object to call one of the Home interface wrappers
  // above, to create a Remote interface reference to the bean.
  // If the return value is of the Remote interface type, you can use it
  // to access the remote interface methods. You can also just use the
  // client object to call the Remote interface wrappers.
 }
}

Building Entity Beans with JBuilder

You may look at the amount of code you need to accomplish a simple task, but JBuilder offers a number of time-saving features to make this process efficient. These features offer a number of capabilities regardless of the EJB vendor you are using. The following are some of those features:

  • EJB Designer to build session and entity beans graphically

  • Component packaging for deployment

  • Deployment Descriptor Editors

  • Wizards to automatically produce container managed persistence

  • Test client generators

Many of these features were discussed in Chapter 22, "Developing Session Beans." We will concentrate on the ones that specialize in entity beans. We will build the same example we built earlier to access our Employee entity and wrap the access with a session façade.

  1. Create a project by choosing File, New Project from the menu. Call the project EntityBeanSample. After you create the project, make sure that the enterprise server is selected using the Project Properties Editor. If you set it as the default for all projects, it will not need to be set.

  2. Create a new EJB module called EntityBean. Make sure the version property is set to EJB 2.0 compliant.

  3. Double-click on the new EJB module node. This loads the EJB Designer.

  4. Right-click on the data sources in the button on the left pane of the IDE and select Import Schema from Database. This process loads all the information from an existing data structure, as shown in Figure 4.


  5. Figure 4

    Import data source definition from external database.

  6. Fill in the connection information to your data source. In this case, use the employee jDatastore database that ships with JBuilder. This process loads the entire schema from the specified database. This is accomplished by clicking on the Choose Existing Connection button.

  7. Right-click on the table Employee and create a CMP 2.0 Entity Bean. This creates an entity bean configured to manage the persistence of the entity to the Employee table.

  8. Now place both a local and remote interface on the new entity bean. This is accomplished by selecting the bean in the Designer, and then changing the interface's property to local/remote.

  9. Let's look at what was generated by JBuilder and make sure that you understand the purpose of each generated file (see Table 1).

    Table 1 Files Generated when Creating a CMP Entity Bean

    Filename

    Scope

    Description

    Employee.java

    Local

    Interface for providing the accessors and mutators to the attributes

    EmployeeHome.java

    Local

    Home interface for creating, finding, and removing an entity

    EmployeeBean.java

    Local/remote

    Implementation class for CMP beans

    EmployeeRemote.java

    Remote

    Interface for providing the accessors and mutators to the attributes for remote usage

    EmployeeRemoteHome.java

    Remote

    Home interface for creating, finding, and removing an entity for remote usage


  10. Compile your application to create a JAR for your EJB entity beans.

  11. Add to the project a test client generated for our new Employee entity bean, or write your own client as seen in Listing 10.

  12. Listing 10 Test Client to Verify Your Entity Bean Operations

     public EmployeeTestClient() {
      long startTime = 0;
      if (logging) {
       log("Initializing bean access.");
       startTime = System.currentTimeMillis();
      }
    
      try {
       //get naming context
       Context ctx = new InitialContext();
    
       //look up jndi name
       Object ref = ctx.lookup("EmployeeRemote");
    
       //cast to Home interface
       employeeRemoteHome = (EmployeeRemoteHome) PortableRemoteObject.narrow(ref, EmployeeRemoteHome.class);
       if (logging) {
        long endTime = System.currentTimeMillis();
        log("Succeeded initializing bean access.");
        log("Execution time: " + (endTime - startTime) + " ms.");
       }
       
       /* Test your component Interface */
       this.findByPrimaryKey(new java.lang.Short("5"));
       this.getEmpNo();
    
      }
      catch(Exception e) {
       if (logging) {
        log("Failed initializing bean access.");
       }
       e.printStackTrace();
      }
     }
  13. Choose Tools, Borland Enterprise Server Management Agent from the menu.

  14. Right-click and run either your JAR file or your EAR. This launches a version of the enterprise server inside JBuilder.

  15. Run your test application and verify the exercising of the entity bean (see Listing 11).

  16. Listing 11 Results of the Test Client Exercising Your Beans Methods

    -- Initializing bean access.
    -- Succeeded initializing bean access.
    -- Execution time: 2944 ms.
    -- Calling findByPrimaryKey(5)
    -- Succeeded: findByPrimaryKey(5)
    -- Execution time: 1452 ms.
    -- Return value from findByPrimaryKey(5): Stub[repository_id=RMI:entitybeansample.EmployeeRemote:000000 ...
    -- Calling getEmpNo()
    -- Succeeded: getEmpNo()
    -- Execution time: 40 ms.
    -- Return value from getEmpNo(): 5.

About the Authors

Saleem Siddiqui is a technical architect and trainer with Dunn Solutions Group. He is also a Sun Certified Developer and a Borland Certified JBuilder Instructor. At Dunn, he provides consulting services and business application development.

Michael Landy is Director of Business Applications for Dunn Solutions Group directing the strategic solutions for clients.

Jeff Swisher is a technical manager for the Dunn Solutions Group business applications. He works as a programmer, trainer, architect, and instructional designer. He is a Sun Certified Java Developer and a Borland Certified Instructor in JBuilder.

Source of this material

This material is from Chapter 23: Developing Entity Beans from the book JBuilder Developer's Guide (ISBN: 0-672-32427-X) written by Saleem Siddiqui, Michael Landy, and Jeff Swisher, published by Sams Publishing.

To access the full Table of Contents for the book.


Other Chapters from Sams Publishing:

Web Services and Flows (WSFL)
Overview of JXTA
Introduction to EJBs
Processing Speech with Java
The Java Database Control in BEA Weblogic
Databases and Tomcat
Working with JAX-RPC
Understanding Servlets


Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved