Sun Java logo     Previous      Contents      Index      Next     

Sun logo
Sun Java System Application Server Standard and Enterprise Edition 7 2004Q2 Developer's Guide to Enterprise JavaBeans Technology 

Chapter 3
Using Entity Beans

This section describes entity beans and explains the requirements for creating them in the Sun Java System Application Server environment.


Note

If you are unfamiliar with entity beans or the EJB technology, refer to the Java Software tutorials:

http://java.sun.com/j2ee/docs.html

Extensive information on entity beans is contained in chapters 9, 10, 12, 13, and 14 of the Enterprise JavaBeans Specification, v2.0.

Overview material on the Sun Java System Application Server is contained in Sun Java System Application Server and Enterprise JavaBeans Technology and the Sun Java System Application Server Product Introduction.


This section addresses the following topics:


About Entity Beans

An entity bean implements an object view of an entity stored in an underlying database, or an entity implemented by an existing enterprise application (for example, by a mainframe program or by an ERP application). Some examples of business objects are customers, orders, and products. The data access protocol for transferring the state of the entity between the entity bean instances and the underlying database is referred to as object persistence.

The following topics are discussed in this section:

Entity Bean Characteristics

Entity beans differ from session beans in several ways. Entity beans are persistent, can be accessed simultaneously by multiple clients, have primary keys, and may participate in relationships with other entity beans.

Entity beans have the following characteristics:

A good situation for using entity beans includes a well encapsulated, transactional, and persistent interaction with databases, documents, and other business objects.

The Container

Entity beans rely on the enterprise bean container to manage security, concurrency, transactions, and other container-specific services for the entity objects it manages. Multiple clients can access an entity object at the same time, while the container transparently handles simultaneous accesses through transactions.

Each entity has a unique object identifier. A customer entity bean, for example, might be identified by a customer number. This unique identifier, or primary key, enables the client to locate a particular entity bean.

Like a session bean, an entity bean can access a database through JDBC calls inside methods whose transaction attributes can be set using deployment descriptors.The container supports both bean-managed and container-managed persistence as described in the following section.

Persistence

Because the state of an entity bean is saved in a some durable storage, it is persistent. Persistence means that the entity bean's state exists beyond the lifetime of the application or the server process.

Persistence of entity beans may done explicitly by the bean and programmed by the bean developer. This is known as bean-managed persistence (BMP).

Persistence management can also be delegated to the container, leveraging the Sun Java System Application Server and the persistence management APIs of the enterprise beans. This approach is called container-managed persistence (CMP). In the CMP mechanism, a persistence manager, integrated with the Sun Java System Application Server, is required to ensure reliable persistence. Refer to Using Container-Managed Persistence for Entity Beans for additional information on container-managed persistence.

The following figure illustrates how persistence works in the Sun Java System Application Server environment.

Figure shows persistence flow for entity beans, including persistence manager, transaction manager, BMP/CMP beans, and database.

Guidelines for selecting the most appropriate persistence method for your applications are contained in Determining Entity Bean Usage.

The following topics are addressed in this section:

Bean-Managed Persistence

In bean-managed persistence, the bean is responsible for its own persistence. The entity bean code that you write contains the calls that access the database.

You code a bean-managed entity bean by providing database access calls—through JDBC and SQL—directly in the bean class methods. Database access calls must be in the ejbCreate, ejbRemove, ejbFindXXX, ejbLoad, and ejbStore methods. The advantage of this approach is that these beans can be deployed to the application server without requiring much effort. The disadvantage is that database access is expensive and, in some cases, the application server can do a better job of optimizing database access than the application programmer can. Also, bean-managed persistence requires the developer to write JDBC code.

For details about using JDBC to work with data, see the Sun Java System Application Server Developer’s Guide to J2EE Services and APIs.

Container-Managed Persistence

In container-managed persistence, the enterprise bean container handles all database access required by the entity bean by interacting through the persistence manager. The bean's code contains no database access (JCBC) calls. As a result, the bean's code is not tied to a specific persistent storage mechanism (database). Because of this flexibility, even if you redeploy the same entity bean on a different database, you won't need to modify the bean's code. In short, your entity beans are more portable.

The bean developer provides abstract bean classes. Typically, the container-managed persistence runtime generates concrete implementation classes that know how to load and save the bean state (in the ejbLoad and ejbStore methods).

To generate the data access calls, the container needs information that you provide in the entity bean's abstract schema. Additional information on the abstract schema is contained in Abstract Schema.

Read-Only Beans

A read-only bean is an entity bean that is never modified by an EJB client. The data that a read-only bean represents may be updated externally by other enterprise beans, or by other means, such as direct database updates.


Note

For this release of the Sun Java System Application Server, only entity beans that use bean-managed persistence can be designated as read-only.


Read-only beans are best suited for situations where the underlying data never changes, or changes infrequently. Instructions for creating read-only beans are contained in Using Read-Only Beans.


Developing Entity Beans

When creating an entity bean, you must provide a number of class files. The tasks required are discussed in the following topics:

Determining Entity Bean Usage

You should probably use an entity bean when the bean represents a business entity, not a procedure, and/or the bean’s state must be persistent (the bean’s state still exists in the database if the server is shut down).

Unlike session beans, entity bean instances can be accessed simultaneously by multiple clients. The container is responsible for synchronizing the instance state using transactions. Because this responsibility is delegated to the container, you do not need to consider concurrent access methods from multiple transactions.

Your choice of persistence method also has an impact:

Responsibilities of the Bean Developer

This section describes what you need to do to ensure that an entity bean with bean-managed persistence can be deployed on the Sun Java System Application Server.

The entity bean developer is responsible for providing the following class files:

Defining the Primary Key Class

The EJB architecture allows a primary key class to be any class that is a legal Value Type in RMI/IIOP. The class must provide suitable implementation of the hashCode and equals (Object other) methods. The primary key class may be specific to an entity bean class, that is, each entity bean class may define a different class for its primary key, but it is possible for multiple entity beans to use the same primary key class.

You must specify a primary key class in the deployment descriptor.

Defining Remote Interfaces

This section discusses the following topics:

Creating the Remote Home Interface

As a bean developer, you must provide the bean's remote home interface (if it is applicable). The home interface defines the methods that enable a client accessing an application to create, find, and remove entity objects. You must create a remote home interface that meets the following requirements:

Remote Create Methods
Remote Find Methods

findByPrimaryKey Method

Remote Remove Methods

All home interfaces automatically (by extending javax.ejb.EJBHome) define two remove methods for destroying an enterprise bean when it is no longer needed:

public void remove(java.lang.Object primaryKey)
throws java.rmi.RemoteException, RemoveException

public void remove(Handle handle)
throws java.rmi.RemoteException, RemoveException


Note

Do not override these remove methods.


Example of a Remote Home interface


import javax.ejb.*;
import java.rmi.*;

public interface MyEntityBeanLocalHome
  extends EJBHome
{
  /**
    * Create an Employee
    * @param empName Employee name
    * @exception CreateException If the employee cannot be
      created
      * @return The remote interface of the bean
    */
  public MyEntity create(String empName)
    throws CreateException;
  /**
    * Find an Employee
    * @param empName Employee name
    * @exception FinderException if the empName is not found
    * @return The remote interface of the bean
    */
  public MyEntity findByPrimaryKey(String empName)
    throws FinderException;
}

Defining Local Interfaces

To build an enterprise bean that allows local access, you must code the local interface and the local home interface. The local interface defines the bean’s business methods; the local home interface defines its life cycle (create/remove) and finder methods.

This section addresses the following topics:

Creating the Local Home Interface

The home interface defines the methods that enable a client using the application to create and remove entity beans. A bean’s local home interface defines the methods that allow local clients to create, find, and remove EJB objects, as well as home business methods that are not specific to a bean instance (session beans do not have finders and home business methods). The local home interface is defined by you and implemented by the container. A client locates a bean’s home using JNDI.

The local home interface allows a local client to:

A local home interface always extends javax.ejb.EJBLocalHome. For example:

  import javax.ejb.*;
  public interface MyEntityLocalBeanHome extends EJBLocalHome {
    MyEntityLocalBean create() throws CreateException;
  }

Creating a Local Interface

If an entity bean is the target of a container-managed relationship, it must have local interfaces. The direction of the relationship determines whether or not a bean is a target. Because they require local access, entity beans that participate in a container-managed relationship must reside in the same EJB JAR file. The primary benefit of this locality is improved performance—local calls are faster than remote calls.

Since local interfaces follow pass by reference semantics, you must be aware of the potential sharing of objects passed through the local interface. In particular, be careful that the state of one enterprise bean is not assigned as the state of another. You must also exercise caution in determining which objects to pass across the local interface, particularly in the case where there is a change in transaction or security content.

(Local) Create Methods
(Local) Find Methods
findByPrimaryKey Method
(Local) home Methods

Creating a Remote Interface

Besides the business methods you define in the remote interface, the EJBObject interface defines several abstract methods that enable you to:

For more information about these built-in methods and how they are used, see the Enterprise JavaBeans Specification, v2.0.


Note

The Enterprise JavaBeans Specification, v2.0 permits the bean class to implement the remote interface's methods, but you should be careful not to inadvertently pass a direct reference (through this) to a client in violation of the client-container-EJB protocol intended by the Enterprise JavaBeans Specification, v2.0.


Example of a Remote Interface

The following fragment is an example of a remote interface

import javax.ejb.*;
import java.rmi.*;

public interface MyEntity
  extends EJBObject
  {
  public String getAddress() throws RemoteException;
  public void setAddress(String addr) throws RemoteException;
}

Creating the Bean Class Definition (for Bean-Managed Persistence)

For an entity bean that uses bean-managed persistence, the bean class must be defined as public and cannot be abstract. The bean class must implement the javax.ejb.EntityBean interface. For example:

import java.rmi.*;
import java.util.*;
import javax.ejb.*;
public class MyEntityBean implements EntityBean {
  //   Entity Bean implementation. These methods must always be
  included.
  public void ejbActivate() {
  }
  public void ejbLoad() {
  }
  public void ejbPassivate() {
  }
  public void ejbRemove() {
  }
  public void ejbStore() t{
  }
  public void setEntityContext(EntityContext ctx) {
  }
  public void unsetEntityContext() {
  }
  // other code omitted here....
  }

In addition to these methods, the entity bean class must also define one or more ejbCreate methods and the ejbFindByPrimaryKey finder method. Optionally, it may define one ejbPostCreate method for each ejbCreate method. It may provide additional, developer-defined finder methods that take the form ejbFindXXX, where XXX represents a unique method name continuation (for example, ejbFindApplesAndOranges) that does not duplicate any other method names.

Entity beans typically implement one or more business methods. These methods are usually unique to each bean and represent its particular functionality. Business method names can be anything, but must not conflict with the method names used in the EJB architecture. Business methods must be declared as public. Method arguments and return value types must be Java RMI legal. The throws clause may define application-specific exceptions and may include java.rmi.RemoteException.

There are two business method types to implement in an entity bean:

The following sections address the various methods in an entity bean’s class definition:

Using ejbCreate

The entity bean must implement one or more ejbCreate methods. There must be one method for each way a client is allowed to invoke the bean. For example:

public String ejbCreate(String orderId, String customerId,
  String status, double totalPrice)
  throws CreateException {
    try {
    InitialContext ic = new InitialContext();
    DataSource ds = (DataSource) ic.lookup(dbName);
    con = ds.getConnection();
    String insertStatement =
      "insert into orders values ( ? , ? , ? , ? )";
    PreparedStatement prepStmt =
      con.prepareStatement(insertStatement);
    prepStmt.setString(1, orderId);
    prepStmt.setString(2, customerId);
    prepStmt.setDouble(3, totalPrice);
    prepStmt.setString(4, status);
    prepStmt.executeUpdate();
    prepStmt.close();
  } catch (Exception ex) {
    throw new CreateException("ejbCreate: "
      +ex.getMessage());
  }
}

public String ejbPostCreate(String orderId, String customerId,String
status, double totalPrice)
  throws CreateException

{
......
......
}

Each ejbCreate method must be declared as public, return the primary key type, and be named ejbCreate. The return type can be any legal Java RMI type that converts to a number for key purposes. All arguments must be legal Java RMI types. The throws clause may define application-specific exceptions, and may include java.ejb.CreateException.

This is the method in which relationships are established. For each ejbCreate method, the entity bean class may define a corresponding ejbPostCreate method to handle entity services immediately following creation. Each ejbPostCreate method must be declared as public, must return void, and be named ejbPostCreate. The method arguments, if any, must match in number and argument type its corresponding ejbCreate method. The throws clause may define application-specific exceptions, and may include java.ejb.CreateException.

Using ejbActivate and ejbPassivate

When an entity bean instance is needed by a server application, the bean’s container invokes ejbActivate to ready a bean instance for use. Similarly, when an instance is no longer needed, the bean’s container invokes ejbPassivate to disassociate the bean from the application.

If specific application tasks need to be performed when a bean is first made ready for an application, or when a bean is no longer needed, you should program those operations within the ejbActivate and ejbPassivate methods. For example, you may release references to database and backend resources during ejbPassivate and regain them during ejbActivate.

Using ejbLoad and ejbStore

An entity bean can collaborate with the container to store the bean state information in a database, for synchronization purposes. In the case of bean-managed persistence, you are responsible for coding ejbLoad and ejbStore. The container ensures that the state of the bean is synchronized with the database by calling ejbLoad at the beginning of a transaction and calling ejbStore when the transaction completes successfully.

Use your implementation of ejbStore to store state information in the database, and use your implementation of ejbLoad to retrieve state information from the database.

The following example shows ejbLoad and ejbStore method definitions that store and retrieve active data.

public void ejbLoad()
    throws java.rmi.RemoteException
{
  String itemId;
  javax.sql.Connection dc = null;
  java.sql.Statement stmt = null;
  java.sql.ResultSet rs = null;

  itemId = (String) m_ctx.getPrimaryKey();

  System.out.println("myBean: Loading state for item " + itemId);

  String query =
    "SELECT s.totalSold, s.quantity " +
    " FROM Item s " +
    " WHERE s.item_id = " + itemId;

  dc = new DatabaseConnection();
  dc.createConnection(DatabaseConnection.GLOBALTX);
  stmt = dc.createStatement();
  rs = stmt.executeQuery(query);

  if (rs != null) {
    rs.next();
    m_totalSold = rs.getInt(1);
    m_quantity = rs.getInt(2);
  }
}

public void ejbStore()
    throws java.rmi.RemoteException
{
  String itemId;
  itemId = (String) m_ctx.getPrimaryKey();
  DatabaseConnection dc = null;
  java.sql.Statement stmt1 = null;
  java.sql.Statement stmt2 = null;

  System.out.println("myBean: Saving state for item = " + itemId);

  String upd1 =
    "UPDATE Item " +
    " SET quantity = " + m_quantity +
    " WHERE item_id = " + itemId;

  String upd2 =
    "UPDATE Item " +
    " SET totalSold = " + m_totalSold +
    " WHERE item_id = " + itemId;

  dc = new DatabaseConnection();
  dc.createConnection(DatabaseConnection.GLOBALTX);
  stmt1 = dc.createStatement();
  stmt1.executeUpdate(upd1);
  stmt1.close();
  stmt2 = dc.createStatement();

  stmt2.executeUpdate(upd2);
  stmt2.close();
}

For more information about bean isolation levels that access transactions concurrently with other beans, see Handling Synchronization of Concurrent Access.

Using setEntityContext and unsetEntityContext

A container calls setEntityContext after it creates an entity bean instance to provide the bean with an interface to the container. Implement this method to store the entity context passed by the container. You can later use this reference to get the primary key of the instance, and so on.

  public void setEntityContext(javax.ejb.EntityContext ctx)
  {
  m_ctx = ctx;
  }

Similarly, a container calls unsetEntityContext to remove the container reference from the instance. This is the last bean class method a container calls before the bean instance becomes a candidate for removal. After this call, the Java garbage collection mechanism eventually calls finalize on the instance to clean it up and dispose of it.

  public void unsetEntityContext()
  {
  m_ctx = null;
  }

Using ejbRemove

The client can invoke the remove methods on the entity bean's home or component interface to remove the associated record from the database. The container invokes the ejbRemove method on an entity bean instance in response to a client invocation on the entity bean's home or component interface, or as the result of a cascade-delete operation.

Using Finder Methods

Because entity beans are persistent, shared among clients, and may have more than one instance instantiated at the same time, an entity bean must implement at least one ejbFindByPrimaryKey method. This enables the client and the container to locate a specific bean instance. All entity beans must provide a unique primary key as an identifying signature. Implement the ejbFindByPrimaryKey method in the bean’s class to enable a bean to return its primary key to the container.

The following example shows a definition for FindByPrimaryKey:

public String ejbFindByPrimaryKey(String key)
    throws java.rmi.RemoteException,
      javax.ejb.FinderException

In some cases, you find a specific entity bean instance based on what the enterprise bean does, on certain values the instance is working with, or on other criteria. These implementation-specific finder method names take the form ejbFindXXX, where XXX represents a unique continuation of a method name (for example, ejbFindApplesAndOranges) that does not duplicate any other method names.

Finder methods must be declared as public, and their arguments, and return values must be legal Java RMI types. Each finder method return type must be the entity bean’s primary key type or a collection of objects of the same primary key type. If the return type is a collection, the return type must be one of the following:

The throws clause of a finder method is an application-specific exception, and may include java.rmi.RemoteException and/or java.ejb.FinderException.


Using Read-Only Beans

A read-only bean is an entity bean that is never modified by an EJB client. The data that a read-only bean represents may be updated externally by other enterprise beans, or by other means, such as direct database updates.


Note

For this release of Sun Java System Application Server, only entity beans that use bean-managed persistence can be designated as read-only.

Read-only beans are specific to Sun Java System application server and are not part of the Enterprise JavaBeans Specification, v2.0.


The following topics are addressed in this section:

Read-Only Bean Characteristics and Life Cycle

Read-only beans are best suited for situations where the underlying data never changes, or changes infrequently. For example, a read-only bean can be used to represent a stock quote for a particular company, which is updated externally. In such a case, using a regular entity bean may incur the burden of calling ejbStore, which can be avoided by using a read-only bean.

Read-only beans have the following characteristics:

A read-only bean comes into existence using the appropriate find methods.

Read-only beans are cached and have the same cache properties as entity beans. When a read-only bean is selected as a victim to make room in the cache, ejbPassivate is called and the bean is returned to the free pool. When in the free pool, the bean has no identity and will be used only to serve any finder requests.

Read-only beans are bound to the naming service like regular read-write entity beans, and clients can look up read-only beans the same way read-write entity beans are looked up.

Read-Only Bean Good Practices

Refreshing Read-Only Beans

There are several ways of refreshing read-only beans as addressed in the following sections:

Invoking a Transactional Method

Invoking any transactional method will invoke ejbLoad.

Refreshing Periodically

Read-only beans can be refreshed periodically by specifying the refresh-period-in-seconds element in the Sun Java System Application Server-specific XML file.

Refreshing Programmatically

Typically, beans that update any data that is cached by read-only beans need to notify the read-only beans to refresh their state. You can use ReadOnlyBeanNotifier to force the refresh of read-only beans. To do this, invoke the following methods on the ReadOnlyBeanNotifier bean:

  public interface ReadOnlyBeanNotifier
    extends java.rmi.Remote
  {
    refresh(Object PrimaryKey)
      throws RemoteException;
  }

The implementation of the ReadOnlyBeanNotifier interface is provided by the container. The user can look up ReadOnlyBeanNotifier using the following fragment of code:

com.sun.ejb.ReadOnlyBeanNotifier notifier = com.sun.ejb.containers.ReadOnlyBeanHelper.getReadOnlyBeanNotifier
  (<ejb-name-of -the-target>);
  notifier.refresh(<PrimaryKey>);

Beans that update any data that is cached by read-only beans need to call the refresh methods. The next (non-transactional) call to the read-only bean will invoke ejbLoad.

Deploying Read Only Beans

Read-only beans are deployed in the same manner as other entity beans. However, in the entry for the bean in the Sun Java System Application Server-specific XML file, the is-read-only-bean element must be set to true. That is:

Also, the refresh-period-in-seconds element may be set to some value that specifies the rate at which the bean is refreshed. If this element is missing, a default of 600 (seconds) is assumed.

All requests with the same transaction context are routed to the same read-only bean instance. The deployer can specify if such multiple requests have to be serialized by setting the allow-concurrent-access element to either true (to allow concurrent accesses) or false (to serialize concurrent access to the same read-only bean). The default is false.

For further information on these elements, refer to the Sun Java System Application Server Administrator’s Configuration File Reference.


Handling Synchronization of Concurrent Access

As an entity bean developer, you generally do not have to be concerned about concurrent access to an entity bean from multiple transactions. The bean’s container automatically provides synchronization in these cases. In the Sun Java System Application Server, the container activates one entity bean instance for each simultaneously occurring transaction that uses the bean.

Transaction synchronization is performed automatically by the underlying database during database access calls. You typically perform this synchronization in conjunction with the underlying database or resource. One approach would be to acquire the corresponding database locks in the ejbLoad method, for example by choosing an appropriate isolation level or by using a select for update clause. The specifics vary depending on the database being used.

For more information, see the Enterprise JavaBeans Specification, v2.0 as it relates to concurrent access.



Previous      Contents      Index      Next     


Copyright 2004 Sun Microsystems, Inc. All rights reserved.