Home > Articles

This chapter is from the book

This chapter is from the book

Developing a CMP Bean

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 23.2).

Listing 23.2 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 23.3. This finder method should return a collection of employees rather than a single instance.

Listing 23.3 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 23.4).

Listing 23.4 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 23.5.

Listing 23.5 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 23.2. 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 23.2Figure 23.2 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 23.3). 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 23.3Figure 23.3 Sequence diagram for a client removing an entity bean.

Finally, let's look at a finder method, shown in Figure 23.4. 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 23.4Figure 23.4 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 23.6).

Listing 23.6 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 23.7.

Listing 23.7 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 23.8.

Listing 23.8 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 23.9 is the session bean developed to test the bean, and Listing 23.10 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 23.9 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 23.10 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 23.5.

  5. Figure 23.5Figure 23.5 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 23.2).

  10. Table 23.2 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


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

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

  13. Listing 23.11 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();
      }
     }
  14. Choose Tools, Borland Enterprise Server Management Agent from the menu.

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

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

  17. Listing 23.12 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.

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020