# Developing Entity Beans

## Target Audience and Content

The target audience for this guide is the Enterprise Bean provider, i.e. the person in charge of developing the software components on the server side, and more especially the Entity Beans.

The content of this guide is the following:

1. Target Audience and content
2. Introduction
3. The Home Interface
4. The Component Interface
5. The Primary Key Class
6. The Enterprise Bean Class
7. Writing Database Access Operations (bean-managed persistence)
8. Configuring Database Access for Container-managed Persistence
9. Tuning Container for Entity Bean Optimizations

## Introduction

An Entity Bean is composed of the following parts, that are to be developed by the Enterprise Bean Provider:

- The Component Interface is the client view of the bean. It contains all the "business methods" of the bean.
- The Home Interface contains all the methods for the bean life cycle (creation, suppression) and for instance retrieval (finding one or several bean objects) used by the client application.
- The Primary Key class (for entity beans only) contains a subset of the bean's fields that identifies a particular instance of an entity bean. This class is optional since the bean programmer can choose a standard class instead (for example java.lang.String)
- The bean implementation class, which implements the business methods, and all the methods (described in the EJB specification) allowing the bean to be managed in the container.
- The deployment descriptor, containing the bean properties that may be edited at assembly or deployment time.

Note that, according to the EJB 2.0 specification, the couple "Component Interface and Home Interface" may be either local or remote. Local Interfaces (Home and Component) are to be used by a client running in the same JVM as the EJB component. Create and finder methods of a local (resp. remote) home interface return local (resp. remote) component interfaces. An EJB component may have both remote and local interfaces, even if typically only one kind of interfaces is provided. If an entity bean is the target of a container-managed relationship (Cf. EJB 2.0 persistence), then it must have local interfaces.

The description of these elements is provided in the following sections.

Note: in this documentation, the term "Bean" always means "Enterprise Bean".

An entity bean represents persistent data. It is an object view of an entity stored in a relational database. The persistence of an entity bean may be handled in two ways:

- Container-Managed Persistence: the persistence is implicitly managed by the container, no code for data access is to be provided by the bean provider. The bean's state will be stored in a relational database according to a mapping description delivered within the deployment descriptor.
- Bean-Managed Persistence: the bean provider writes the database access operations (JDBC code) in the methods of the enterprise bean that are specified for data creation, load, store, retrieval, and remove operations (ejbCreate, ejbLoad, ejbStore, ejbFind..., ejbRemove).

Currently, the platform handles persistence in relational storage systems through the JDBC interface. For both container-managed or bean-managed persistence, JDBC connections are obtained from an object provided at the EJB server level, the DataSource. The DataSource interface is defined in the JDBC 2.0 standard extensions. A DataSource object identifies a database and a means to access it via JDBC (a JDBC driver). An EJB server may propose access to several databases and thus provides the corresponding DataSource objects. DataSources are described in more details in the section "Configuring JDBC DataSources".

## The Home Interface

The Home interface is used by any client application to create and retrieve instances of the entity bean. The bean provider only needs to provide the desired interface, the container will automatically provide the implementation. The interface must extend the `javax.ejb.EJBHome` interface if it is remote or the `javax.ejb.EJBLocalHome` interface if it is local. The methods of a remote home interface must follow the rules for java RMI. The signatures of the "create" and "find..." methods should match the signatures of the "ejbCreate" and "ejbFind..." methods that will be provided later in the enterprise bean implementation class (same number and types of arguments, but different return types).

create methods:

- the return type is the enterprise bean's component interface
- the exceptions defined in the throws clause must include the exceptions defined for the ejbCreate and ejbPostCreate methods, and must include `javax.ejb.CreateException` and `java.rmi.RemoteException` (this last only in case of a remote interface).

finder methods:

Finder methods are used to search for an EJB object or a collection of EJB objects. The arguments of the method are used by the entity bean implementation to locate the requested entity objects. In case of bean-managed persistence, the bean provider is responsible for developing the corresponding ejbFinder methods in the bean implementation. In case of container-managed persistence, the bean provider does not write these methods, they are generated at deployment time by the platform tools; the description of the method is provided in the deployment descriptor, as defined in section "Configuring database access for container-managed persistence". In the Home interface, the finder methods must follow the rules below:

- they must be named "find<method>" (e.g. `findLargeAccounts`)
- the return type must be the enterprise bean's component interface, or a collection thereof
- the exceptions defined in the throws clause must include the exceptions defined for the matching ejbFind method, and must include `javax.ejb.FinderException` and `java.rmi.RemoteException` (this last only in case of a remote interface).

At least one of these methods is mandatory, findByPrimaryKey, which takes as argument a primary key value and returns the corresponding EJB object.

### Example

The Account bean example, provided with the platform examples will be used to illustrate these concepts. The state of an entity bean instance is stored into a relational database where the following table should exist :

`create table ACCOUNT (ACCNO integer primary key, CUSTOMER varchar(30), BALANCE number(15,4));`

`public interface` `AccountHome` `extends EJBHome {`

`public Account` `create``(int accno, String customer, double balance)`
`throws RemoteException, CreateException;`

`public Account` `findByPrimaryKey``(Integer pk)`
`throws RemoteException, FinderException;`

`public Account` `findByNumber``(int accno)`
`throws RemoteException, FinderException;`

`public Enumeration` `findLargeAccounts``(double val)`
`throws RemoteException, FinderException;`
`}`

## The Component Interface

Business methods:

The Component Interface is the client's view of an instance of the entity bean. It is what is returned to the client by the Home interface after creating or finding an entity bean instance. This interface contains the business methods of the enterprise bean. The interface must extend the `javax.ejb.EJBObject` interface if it is remote or the `javax.ejb.EJBLocalObject` if it is local. The methods of a remote component interface must follow the rules for java RMI. For each method defined in this component interface, there must be a matching method of the bean implementation class (same arguments number and types, same return type, same exceptions except for RemoteException).

### Example

`public interface` `Account` `extends EJBObject {`
`public double` `getBalance``() throws RemoteException;`
`public void` `setBalance``(double d) throws RemoteException;`
`public String` `getCustomer``() throws RemoteException;`
`public void` `setCustomer``(String c) throws RemoteException;`
`public int` `getNumber``() throws RemoteException;`
`}`

## The Primary Key Class

The Primary Key class is necessary for entity beans only. It encapsulates the fields representing the primary key of an entity bean in a single object. If the primary key in the database table is composed of a single column with a basic data type, the simplest way to define the primary key in the bean is to use a standard java class like `java.lang.Integer` or `java.lang.String` for example. This must be the type of a field in the bean class. It is not possible to define it as a primitive field (like int, float or boolean for example). Then, the single thing to do is to specify in the deployment descriptor the type of the primary key :

          <prim-key-class>java.lang.Integer</prim-key-class>

And in case of container-managed persistence, the field which represents the primary key

          <primkey-field>accno</primkey-field>

The other way is to define its own Primary Key class, as defined here after:

The class must be serializable, and must provide suitable implementation of the `hashcode()` and `equals(Object)` methods.

For container-managed persistence, the following rules must be followed:

- the fields of the primary key class must be declared as public.
- the primary key class must have a public default constructor.
- the names of the fields in the primary key class must be a subset of the names of the container-managed fields of the enterprise bean.

### Example

`public class` `AccountBeanPK` `implements java.io.Serializable {`

> `public int accno;`

> `public AccountBeanPK(int accno) { this.accno = accno; }`

> `public AccountBeanPK() { }`

> `public int hashcode() { return accno; }`

> `public boolean equals(Object other) {`

> > `...`

> `}`

`}`

## The Enterprise Bean Class

The EJB implementation class implements the bean's business methods of the component interface, and the methods dedicated to the EJB environment, the interface of which are explicitely defined in the EJB specification. The class must implement the `javax.ejb.EntityBean` interface, must be defined as public, and may not be abstract. The EJB environment dedicated methods that the EJB provider must develop are listed below.

The first set of methods are those corresponding to the create and find methods of the Home interface:

- public PrimaryKeyClass ejbCreate(...);

  This method is invoked by the container when a client invokes the corresponding create operation on the enterprise Bean's home interface. The method should initialize instance's variables from the input arguments. The returned object should be the primary key of the created instance. In case of bean managed persistence, the bean provider should develop here the JDBC code to create the corresponding data in the database. In case of container-managed persistence, the container will perform the database insert after the ejbCreate method completes and the return value should be null.

- public void ejbPostCreate(...);

  There is a matching ejbPostCreate method (same input parameters) for each ejbCreate method. The container invokes this method after the execution of the matching ejbCreate(...) method. During the ejbPostCreate method, the object identity is available.

- public <PrimaryKeyClass or Collection> ejbFind<method> (...); // bean-managed persistence only

  The container invokes this method on a bean instance that is not associated to any particular object identity (some kind of class method ...) when the client invokes the corresponding method on the Home interface. The implementation uses the arguments to locate the requested object(s) in the database and returns a primary key (or a collection thereof). Currently, collections will be represented as `java.util.Enumeration objects` or `java.util.Collection`. The mandatory FindByPrimaryKey method takes as argument a primary key type value and returns a primary key object (it checks that the corresponding entity exists in the database).

  In case of container-managed persistence, the bean provider does not have to write these finder methods, they are generated at deployment time by the EJB platform tools. The information needed by the EJB platform for automatically generating these finder methods should be provided by the bean programmer; the EJB specification does not specify the format of this finder method description. For JOnAS, the finder methods description should be provided in the JOnAS specific deployment descriptor of the Entity Bean, see section "Configuring database access for container-managed persistence".

Then, the methods of the `javax.ejb.EntityBean` interface must be implemented:

- public void setEntityContext(EntityContext ic);

  Used by the container to pass a reference to the EntityContext to the bean instance. The container invokes this method on an instance after the instance has been created. Generally this method is used to store this reference in an instance variable.

- public void unSetEntityContext();

  Unset the associated entity context. The container calls this method before removing the instance. This is the last method that the container invokes on the instance.

- public void ejbActivate();

  The container invokes this method when the instance is taken out of the pool of available instances to become associated with a specific EJB object. This method transitions the instance to the ready state.

- public void ejbPassivate();

  The container invokes this method on an instance before the instance becomes dissociated with a specific EJB object. After this method completes, the container will place the instance into the pool of available instances.

- public void ejbRemove();

  This method is invoked by the container when a client invokes a remove operation on the enterprise bean. For entity beans with bean-managed persistence, this method should contain the JDBC code to remove the corresponding data in the database. In case of container-managed persistence, this method is called before the container removes the entity representation in the database.

- public void ejbLoad();

  The container invokes this method to instruct the instance to synchronize its state by loading it from the underlying database. In case of bean-managed persistence, the EJB provider should code at this place the JDBC statements for reading the data in the database. For container-managed persistence, loading the data from the database will be done automatically by the container just before ejbLoad is called, and the ejbLoad method should only contain some "after loading calculation statements".

- public void ejbStore();

  The container invokes this method to instruct the instance to synchronize its state by storing it to the underlying database. In case of bean-managed persistence, the EJB provider should code at this place the JDBC statements for writing the data in the database. For entity beans with container-managed persistence, this method should only contain some "pre-store statements", since the container will extract the container-managed fields and write them to the database just after the ejbStore method call.

### Example

This is the example for container-managed persistence. For bean-managed persistence you may refer to the examples delivered with the platform.

    package eb;

    import java.rmi.RemoteException;
    import javax.ejb.EntityBean;
    import javax.ejb.EntityContext;
    import javax.ejb.ObjectNotFoundException;
    import javax.ejb.RemoveException;
    import javax.ejb.EJBException;

    public class AccountImplBean implements EntityBean {

        // Keep the reference on the EntityContext
        protected EntityContext entityContext;

        // Object state
        public Integer accno;
        public String customer;
        public double balance;

        public Integer ejbCreate(int val_accno, String val_customer, double val_balance) {

    	// Init object state
    	accno = new Integer(val_accno);
    	customer = val_customer;
    	balance = val_balance;
    	return null;
        }

        public void ejbPostCreate(int val_accno, String val_customer, double val_balance) {
    	// Nothing to be done for this simple example.
        }

        public void ejbActivate() {
    	// Nothing to be done for this simple example.
        }

        public void ejbLoad() {
    	// Nothing to be done for this simple example, in implicit persistance.
        }

        public void ejbPassivate() {
    	// Nothing to be done for this simple example.
        }

        public void ejbRemove() {
    	// Nothing to be done for this simple example, in implicit persistance.
        }

        public void ejbStore() {
    	// Nothing to be done for this simple example, in implicit persistance.
        }

        public void setEntityContext(EntityContext ctx) {
    	// Keep the entity context in object
    	entityContext = ctx;
        }

        public void unsetEntityContext() {
    	entityContext = null;
        }

        public double getBalance() {
    	return balance;
        }

        public void setBalance(double d) {
    	balance = balance + d;
        }

        public String  getCustomer() {
    	return customer;
        }

        public void setCustomer(String c) {
    	customer = c;
        }

        public int getNumber()  {
    	return accno.intValue();
        }
    }

## Writing Database Access Operations (bean-managed persistence)

In the case of bean-managed persistence, data access operations are developed by the bean provider using the JDBC interface. However, getting database connections should be done through the javax.sql.DataSource interface on a datasource object provided by the EJB platform. This is mandatory since the EJB platform is responsible for managing the connection pool and for transaction management. So, in order to get a JDBC connection, in each method performing database operations, the bean provider should

- call the getConnection(...) method of the DataSource object, in order to obtain a connection to perform the JDBC operations in the current transactional context (if there is some),
- call the close() method on this connection after the database access operations, so that the connection may be returned to the connection pool (and dissociated from the potential current transaction).

A method that performs database access should always contain the getConnection and close statements, as follows:

    public void doSomethingInDB (...) {
        conn = dataSource.getConnection();
        ... // Database access operations
        conn.close();
    }

A DataSource object associates a JDBC driver and a database (as an ODBC datasource); it is created and registered in JNDI by the EJB server at launch time (see also the section about JDBC DataSources configuration).

A DataSource object is a resource manager connection factory for `java.sql.Connection` objects, which implements connections to a database management system. The enterprise bean code refers to resource factories using logical names called "Resource manager connection factory references". The resource manager connection factory references are special entries in the enterprise bean environment. The bean provider must use resource manager connection factory references to obtain the datasource object as follow:

- Declare the resource reference in the standard deployment descriptor using a `resource-ref` element.
- Lookup the datasource in the enterprise bean environment using the JNDI interface (see section Enterprise Bean's Environment).

The deployer binds the resource manager connection factory references to the actual resource factories that are configured in the server. This binding is done in the JOnAS specific deployment descriptor using the jonas-resource element.

### Example

The declaration of the resource reference in the standard deployment descriptor looks like:

    <resource-ref>
    <res-ref-name>jdbc/AccountExplDs</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    </resource-ref>

The <res-auth> element indicates which of the two resource manager authentication approaches is used:

- Container : the deployer sets up the sign-on information,
- Bean : the bean programmer should use the getConnection method with user and password parameters.

The JOnAS specific deployment descriptor should map the environment JNDI name of the resource to the actual JNDI name of the resource object managed by the EJB server. This is done in the <jonas-resource> element.

      <jonas-entity>
        <ejb-name>AccountExpl</ejb-name>
        <jndi-name>AccountExplHome</jndi-name>
        <jonas-resource>
          <res-ref-name>jdbc/AccountExplDs</res-ref-name>
          <jndi-name>jdbc_1</jndi-name>
        </jonas-resource>
      </jonas-entity>

The ejbStore method of the same Account example with bean-managed persistence is shown below. It performs JDBC operations to update the database record representing the state of the entity bean instance. The JDBC connection is obtained from the datasource associated to the bean. This datasource has been instanciated by the EJB server and is available for the bean through its resource reference name, which is defined in the standard deployment descriptor.

Somewhere in the bean, a reference to a datasource object of the EJB server is initialized:

`it = new InitialContext();`

`ds = (DataSource)it.lookup("java:comp/env/jdbc/AccountExplDs");`

Then, this datasource object is used in the implementation of the methods performing JDBC operations, such as ejbStore, as illustrated below:

    public void ejbStore
        Connection conn = null;
        PreparedStatement stmt = null;
        try { // get a connection
            conn = ds.getConnection();
            // store Object state in DB
            stmt = conn.prepareStatement("update account set customer=?,balance=? where accno=?");
            stmt.setString(1, customer);
            stmt.setDouble(2, balance);
            Integer pk = (Integer)entityContext.getPrimaryKey();
            stmt.setInt(3, pk.accno);
            stmt.executeUpdate();
         } catch (SQLException e) {
            throw new javax.ejb.EJBException("Failed to store bean to database", e);
         } finally {
            try {
                if (stmt != null) stmt.close();    // close statement
                if (conn != null) conn.close();    // release connection
            } catch (Exception ignore) {}
         }
    }

Note that the close statement instruction may be important if the server is intensively accessed by many clients performing entity beans access. If the statement is not closed in the finally block, since stmt is in the scope of the method, it will be deleted at the end of the method (and the close will be implicitly done), however, it may take some time before the Java garbage collector deletes the statement object, therefore, if the number of clients performing entity bean access is important, the DBMS may raise a "two many opened cursors" exception (a JDBC statement corresponds to a DBMS cursor). Since connection pooling is performed by the platform, closing the connection will not result in a physical connection close, and therefore opened cursors will not be closed. So it is preferable to explicitly close the statement in the method.

It could be a good programming rule to put the JDBC connection and JDBC statement close operations in a finally bloc of the try statement.

## Configuring Database Access for Container-managed Persistence

First of all, the standard way to indicate to an EJB platform that an entity bean has container-managed persistence is to fill the `<cmp-field>` tag of the deployment descriptor with the list of container-managed fields (the fields that the container will have in charge to make persistent). In the textual format of the deployment descriptor, this is represented by the following lines:

        <cmp-field>
          <field-name>fieldOne</field-name>
        </cmp-field>
        <cmp-field>
          <field-name>fieldTwo</field-name>
        </cmp-field>

With container-managed persistence, the programmer does not have to develop the code for accessing the data in the relational database; this code is included in the container itself (generated by the platform tools). However, in order that the EJB platform knows how to access the database and which data to read and write in the database, two kinds of information must be provided with the bean :

- first the container should know which database to access, and how to access it. To achieve such a goal, the only needed information is the name of the DataSource which will be used to get the JDBC connection. For container-managed persistence, one and only one DataSource per bean should be used.
- then, it is necessary to know the mapping of the bean fields to the underlying database (which table, which column).

The EJB specification does not specify how this information should be provided to the EJB platform by the bean deployer. Therefore, what is described in the remainder of this section is specific to JOnAS.

The bean deployer is responsible for defining the mapping of the bean fields to the database table columns. The name of the DataSource may be set at deployment time, as it depends on the EJB platform configuration. This database configuration information is defined in the JOnAS specific deployment descriptor via the `jdbc-mapping` element:

        <jdbc-mapping>
          <jndi-name>jdbc_1</jndi-name>
          <jdbc-table-name>accountsample</jdbc-table-name>
          <cmp-field-jdbc-mapping>
          <field-name>mAccno</field-name>
          <jdbc-field-name>accno</jdbc-field-name>
          </cmp-field-jdbc-mapping>
          <cmp-field-jdbc-mapping>
          <field-name>mCustomer</field-name>
          <jdbc-field-name>customer</jdbc-field-name>
          </cmp-field-jdbc-mapping>
          <cmp-field-jdbc-mapping>
          <field-name>mBalance</field-name>
          <jdbc-field-name>balance</jdbc-field-name>
        </jdbc-mapping>

`jdbc_1` is the JNDI name of the DataSource object identifying the database, `accountsample` is the name of the table used to store the bean instances in the database, and `mAccno`, `mCustomer`, `mBalance` are the names of the container-managed fields of the bean to be stored in the `accno`, `customer` and `balance` columns of the `accountsample` table. This example applies for container-managed persistence, in case of bean-managed persistence, the database mapping does not exist.

The `jdbc-mapping` element may also contain information defining the behaviour of the implementation of a find<method> method (i.e. the ejbFind<method> method, that will be generated by the platform tools). This information is represented by the `finder-method-jdbc-mapping` element.

For each finder method, this element allows to define a SQL WHERE clause that will be used in the generated finder method implementation to query the relational table storing the bean entities. Note that the table column names should be used, not the bean field names. Example:

          <finder-method-jdbc-mapping>
            <jonas-method>
              <method-name>findLargeAccounts</method-name>
            </jonas-method>
            <jdbc-where-clause>where balance &gt; ?</jdbc-where-clause>
          </finder-method-jdbc-mapping>

The previous finder method description will cause the platform tools to generate an implementation of ejbFindLargeAccount(double arg) that returns the primary keys of the entity bean objects corresponding to the tuples returned by the "select ... from Account where balance > ?" where '?' will be replaced by the value of the first argument of the findLargeAccount method. If several '?' characters appear in the provided where clause, this means that the finder method has several arguments, and they will correspond to these arguments, respecting the order of the method signature.

In the WHERE clause, the parameters can be followed by a number, that specifies the method parameter number that will be used by the query in this position.
Example: The WHERE clause of the following finder method may be:

          Enumeration findByTextAndDateCondition(String text, java.sql.Date date)

          WHERE (description like ?1 OR summary like ?1) AND (?2 &gt; date)

Note that a `<finder-method-jdbc-mapping>` element for the findByPrimaryKey method isn't necessary; indeed, the meaning of this method is well-known.

The datatypes supported for container-managed fields are the following:

Java Type | JDBC Type | JDBC driver Access methods
boolean | BIT | getBoolean(), setBoolean()
byte | TINYINT | getByte(), setByte()
short | SMALLINT | getShort(), setShort()
int | INTEGER | getInt(), setInt()
long | BIGINT | getLong(), setLong()
float | FLOAT | getFloat(), setFloat()
double | DOUBLE | getDouble(), setDouble
byte[] | VARBINARY or LONGVARBINARY (1) | getBytes(), setBytes()
java.lang.String | VARCHAR or LONGVARCHAR (1) | getString(), setString()
java.lang.Boolean | BIT | getBoolean(), setObject()
java.lang.Integer | INTEGER | getInt(), setObject()
java.lang.Short | SMALLINT | getShort(), setObject()
java.lang.Long | BIGINT | getLong(), setObject()
java.lang.Float | REAL | getFloat(), setObject()
java.lang.Double | DOUBLE | getDouble(), setObject()
java.math.BigDecimal | NUMERIC | getBigDecimal(), setObject()
java.math.BigInteger | NUMERIC | getBigDecimal(), setObject()
java.sql.Date | DATE | getDate(), setDate()
java.sql.Time | TIME | getTime(), setTime()
java.sql.Timestamp | TIMESTAMP | getTimestamp(), setTimestamp()
any serializable class | VARBINARY or LONGVARBINARY (1) | getBytes(), setBytes()

(1) The mapping for String will normally be VARCHAR but will turn into LONGVARCHAR if the given value exceeds the driver's limit on VARCHAR values. The case is similar for byte[] and VARBINARY and LONGVARBINARY values.

## Tuning Container for Entity Bean Optimizations

JOnAS must make a compromise between scalability and performance. Toward this end, we have introduced 3 new tags in the jonas specific deployment descriptor:

### shared

This optional flag must be defined at `True` if the bean persistent state can be accessed outside the JOnAS EJBServer. When this flag is `False`, the EJBServer can do some optimisations like not re-reading the bean state before starting a new transaction.

### min-pool-size

This optional integer value represents the minimum instances that will be created in the pool when the bean is loaded. This will improve bean instance create time, at least for the first ones.

### max-cache-size

This optional integer value represents the maximum of instances in memory. The purpose of this value is to keep JOnAS scalable.