Entity Beans and CMP 2.0 in Borland Enterprise Server

Here we'll examine how entity beans are deployed in the Borland Enterprise Server and how persistence of entities can be managed. This is not, however, an introduction to entity beans and should not be treated as such. Rather, this document will explore the implications of using entity beans within Borland Partitions. We'll discuss descriptor information, persistence options, and other container-optimizations. Information on the Borland-specific deployment descriptors and implementations of Container-Managed Persistence (CMP) will be documented in favor of general EJB information that is generally available from the J2EE Specifications from Sun Microsystems.

Entity Beans

Entity beans represent a view of data stored in a database. Entity beans can be fine-grained entities mapping to a single table with a one-to-one correspondence between entity beans and table rows. Or, entity beans can span multiple tables and present data independent of the underlying database schema. Entity beans can have relationships with one another, can be queried for data by clients, and can be shared among different clients.

Deploying your Entity Bean to one of the Borland Enterprise Server Partitions requires that it be packaged as a part of a JAR. The JAR must include two descriptor files: ejb-jar.xml and the proprietary ejb-borland.xml file. The ejb-jar.xml descriptor is fully-documented in the J2EE 1.3 Specification. The DTD for ejb-borland.xml is reproduced in this document and aspects of its usage documented here. The Borland proprietary descriptor allows for the configuration of a number of properties that can be set to optimize container performance and manage the persistence of your entity beans.

Container-managed persistence and Relationships

Borland's EJB container provides tools that generate the persistence calls at the time that the entity bean is deployed; that is, when the entity bean is installed into a Partition. The tools use the deployment descriptors to determine the instance fields which must be persisted. Instead of coding the database access directly in the bean, the bean provider of a container-managed entity bean must specify in the deployment descriptor those instance fields for which the container tools must generate access calls. The container has sophisticated deployment tools capable of mapping the fields of an entity bean to its data source.

Container-managed persistence has many advantages over bean-managed persistence. It is simpler to code because bean provider does not have to code the database access calls. Handling of persistence can also be changed without having to modify and recompile the entity bean code. The Deployer or Application Assembler can do this by modifying the deployment descriptor when deploying the entity bean. Shifting the database access and persistence handling to the container not only reduces the complexity of code in the bean, it also reduces the scope of possible errors. The bean provider can focus on debugging the business logic of the bean rather than the underlying system issues.

Borland's Persistence Manager (PM) not only persists CMP fields but also CMP relationships. The container manages bean relationships and maintain the referential integrity of these relationships. Just as you defined container-managed persistence fields in a bean's deployment descriptor, you can now define container-managed relationship fields in the deployment descriptor. The container supports relationships of various cardinalities, including one-to-one, one-to-many, and many-to-many.

Packaging Requirements

Like session beans, entity beans can expose their methods with a remote interface or with a local interface. The remote interface exposes the bean's methods across the network to other, remote components. The local interface exposes the bean's methods only to local clients; that is, clients located on the same EJB container.

Entity beans that use EJB 2.0 container-managed persistence should use the local model. That is, the entity bean's local interface extends the EJBLocalObject interface. The bean's local home interface extends the EJBLocalHome interface. You must deploy these interfaces as well as an implementation of your bean's class.

Each Entity Bean must also have corresponding entries in its JAR's deployment descriptors. The standard deployment descriptor, ejb-jar.xml contains essentially three different types of deployment information. These are:

  1. General Bean Information: This corresponds to the <enterprise-beans> elements found in the descriptor file and is used for all three types of beans. This information also includes information on the bean's interfaces and class, security information, environmental information, and even query declarations.
  2. Relationships: This corresponds to the <relationships> elements found in the descriptor file and applies to entity beans using CMP only. This is where container-managed relationships are spelled out.
  3. Assembly Information: This corresponds to the <assembly-descriptor> element which explains how the beans interact with the application as a whole. Assembly information is broken down into four categories:

In addition, each Entity Bean also provides persistence information in the Borland-specific descriptor file, ejb-borland.xml. In this descriptor file, you specify information used by the Borland CMP engine and PM to persist entities in a backing store. This information includes:

All of these can be accessed through the Deployment Descriptor Editor. You should refer to the EJB 2.0 specification for DTD information and the proper use of the descriptor files.

Generating Entity Bean Primary Keys

Each Entity Bean must have a unique primary key that used to identify the bean instance. The primary key can be represented by a Java class that must be a legal value type in RMI-IIOP. Therefore, it extends the java.io.Serializable interface. It must also provide an implementation of the Object.equals(Object other) and Object.hashCode() methods.

Normally, the primary key fields of entity beans must be set in the ejbCreate() method. The fields are then used to insert a new record into the database. This can be a difficult procedure, however, bloating the method, and many databases now have built-in mechanisms for providing appropriate primary key values. A more elegant means of generating primary keys is for the user to implement a separate class that generates primary keys. This class can also implement database-specific programming logic for generating primary keys.

You may either generate primary keys by hand, use a custom class, or allow the container to use the database tools to perform this for you. If you use a custom class, implement the com.borland.ejb.pm.PrimaryKeyGenerationListener interface, discussed below. To use the database tools, you can set properties for the CMP engine to generate primary keys depending upon the database vendor.

Generating primary keys from a user class

With enterprise beans, the primary key is represented by a Java class containing the unique data. This primary key class can be any class as long as that class is a legal value type in RMI-IIOP, meaning it extends the java.io.Serializable interface. It must also provide an implementation of the Object.equals(Object other) and Object.hashCode() methods, two methods which all Java classes inherit by definition.

Generating primary keys from a custom class

To generate primary keys from a custom class, you must write a class that implements the com.borland.ejb.pm.PrimaryKeyGenerationListener interface.

Note: this is a new interface for generating primary keys. In previous versions of Borland Enterprise Server, this class was com.inprise.ejb.cmp.PrimaryKeyGenerator. This interface is still supported, but Borland recommends using the newer interface when possible.

Next, you must inform the container of your intention to use your custom class to generate primary keys for your entity beans. To do this, you set a table property primaryKeyGenerationListener to the class name of your primary key generator.

Implementing primary key generation by the CMP engine

Primary key generation can also be implemented by the CMP engine. Borland provides four properties to support primary key generation using database specific features. These properties are:

All of these properties are table properties except ignoreOnInsert, which is a column property. Setting table and column properties is discussed here.

Oracle Sequences: using getPrimaryKeyBeforeInsertSql

The property getPrimaryKeyBeforeInsertSql is typically used in conjunction with Oracle Sequences. The value of this property is a SQL statement used to select a primary key generated from a sequence. For example, the property could be set to:

SELECT MySequence.NEXTVAL FROM DUAL

The CMP engine would execute this SQL and then extract the appropriate value from the ResultSet. This value will then be used as the primary key when performing the subsequent INSERT. The extraction from the ResultSet is based on the primary key's type

SQL Server: using getPrimaryKeyAfterInsertSql and ignoreOnInsert

Two properties need to be specified for cases involving SQL Server. The getPrimaryKeyAfterInsertSql property specified the SQL to execute after the INSERT has been performed. As above, the CMP engine extracts the primary key from the ResultSet based on the primary key's type. The property ignoreOnInsert must also be set to the name of the identity column. The CMP engine will then know not to set that column in the INSERT.

JDataStore JDBC3: using useGetGeneratedKeys

Borland's JDataStore supports the new JDBC3 method java.sql.Statement.getGeneratedKeys(). This method is used to obtain primary key values from newly inserted rows. No additional coding is necessary, but note that this method is unsupported in other databases and is recommended for use only with Borland JDataStore. To use this method, set the boolean property useGetGeneratedKeys to True.

A note on reentrancy

By default, entity beans are not reentrant. When a call within the same transaction context arrives at the entity bean, it causes the exception java.rmi.RemoteException to be thrown.

You can declare an entity bean reentrant in the deployment descriptor; however, take special care in this case. The critical issue is that a container can generally not distinguish between a (loopback) call within the same transaction and a concurrent invocation (in the same transaction context) on that same entity bean.

When the entity bean is marked reentrant, it is illegal to allow a concurrent invocation within the same transaction context on the bean instance. It is the programmer's responsibility to ensure this rule.

Container-Managed Persistence in Borland Enterprise Server

The Borland Enterprise Server's EJB Container is fully J2EE 1.3 compliant. It implements both container-managed persistence (CMP) for Enterprise JavaBeans implementing either the EJB 1.1 and/or EJB 2.0 specifications. The bean provider designs persistence schemas for their entity beans, determined the methods for accessing container-managed fields and relationships, and defines these in the beans' deployment descriptor. The deployer maps this persistence schema to the database and creates any other necessary classes for the beans' maintenance.

The EJB 2.0 Specification from Sun Microsystems details the specifics for the bean and container contracts in Chapters 10 and 11. Creating the persistence schema is not in the scope of this document, but is well-discussed in both the Sun specification and in the Borland JBuilder documentation, the relevant parts of which are the Enterprise JavaBeans Developer's Guide and the Distributed Application Developer's Guide.

About the Persistence Manager

The Persistence Manager (PM) provides a data-access layer for reading and writing entity beans. It also provides navigation and maintenance support for relationships between entities and extensions to EJB-QL. Currently, the PM only supports data access to relational database by means of JDBC. The PM uses an optimistic concurrency approach to data access. Conflicts in resource state are resolved before transaction commit or rollback by use of verified SQL update and delete statements.

Although the PM does not manage transactions (this is the container's responsibility) it is aware of transaction start and completion and can therefore manage entity state. The PM uses the TxContext class to represent the root of managed entities during transaction lifecycles. When the container manages a transaction it asks the PM for the associated TxContext instance. If none exists, as is the case when a new transaction has started, one is created by the PM. When a transaction is completing, the container calls the method TxContext.beforeCompletion() to alert the PM to verify entity state.

The PM has complete responsibility for entity data storage and the maintenance of the state of relationships between entities. Relationship editing is also managed by the PM. This simplifies interactions with the container and allows the PM to optimize its read and write operations. This approach also suppresses duplicate find requests by tracking returned primary keys for requested entities. Data from duplicate find operations can then be returned from the first load of the entity's data.

Borland CMP engine's CMP 2.0 implementation

In CMP 2.0, the details of constructing finder and select methods have been pushed into the EJB 2.0 specification. Users should thoroughly inspect the specification for details on implementing their database SQL. The Borland EJB Container is fully-compliant with the EJB 2.0 specification and supports all of its features.

The implementation class for an entity bean using 2.0 container-managed persistence is different from that of a bean using 1.1 container-managed persistence. The major differences are as follows:

Table Mapping for CMP 2.0 is accomplished using the vendor-specific ejb-borland.xml deployment descriptor. The descriptor is a companion to the ejb-jar.xml descriptor described in the EJB 2.0 specification. Borland uses the XML tag <cmp2-info> as an enclosure for table mapping data as needed. Then you use the <table-properties> and its associated <column-properties> elements to specify particular information about the entity bean's implementation.

Persistence Schema

The Borland CMP 2.0 engine can create the underlying database schema based on the structure of your entity beans and the information provided in the entity bean deployment descriptors. You don't need to provide any CMP mapping information in such cases. Simply follow the instructions for "Specifying tables and datasources," below. Or, the CMP engine can adapt to an existing underlying database schema. Doing so, however, requires you to provide information to the CMP engine about your database schema. In such cases, you should refer to the CMP mapping sections, below, as well as CASE 2 in "Specifying tables and datasources."

Specifying tables and datasources

The minimum information required in ejb-borland.xml is an entity bean name and an associated datasource. A datasource is a class used to obtain connections to a database, JMS implementation, or backing store of some other type. There are two means of providing this information.

CASE 1: A development environment without existing database tables using either JDataStore or Cloudscape databases. In this case, the Borland CMP engine creates tables automatically, assuming that the entity bean name is the same as the desired table name. You need only provide the bean's name and its associated datasource as a property:

<entity>

	<ejb-name>CustomerEJB</ejb-name>

	<property>

		<prop-name>ejb.datasource</property>

		<prop-value>serial://ds/myDatasource</prop-value>

	</property>

</entity>

The Borland CMP engine will automatically create tables in this datasource based on the bean's name and fields.

CASE 2: A deployment environment with (or without) existing database tables using supported databases. In this case, you need to supply information on the tables to which the entities map. You'll provide a table name in the <entity> portion of the descriptor, and some properties in the <table-properties> portion:

<entity>

	<ejb-name>CustomerEJB</ejb-name>

	<cmp2-info>

		<table-name>CUSTOMER</table-name>

	</cmp2-info>

</entity>

.

.

<table-properties>

	<table-name>CUSTOMER</table-name>

		<property>

			<prop-name>datasource</prop-name>

			<prop-value>serial://ds/myDatasource</prop-value>

		</property>

</table-properties>

Note that the datasource property is called datasource when specified in the <table-properties> element and ejb.datasource when in the <entity> element. If you are using a database other than JDataStore or Cloudscape and would like to have the Borland CMP engine automatically create this table, add the following XML to the <table-properties> element:

.

.

<table-properties>

	<table-name>CUSTOMER</table-name>

		<property>

			<prop-name>createTables</prop-name>

			<prop-value>True</prop-value>

		</property>

</table-properties>

Basic Mapping of CMP fields to columns

Basic field mapping is accomplished using the <cmp-field> element in the ejb-borland.xml deployment descriptor. In this element, you specify a field name and a corresponding column to which it maps. Consider the following XML for an entity bean called LineItem, which maps two fields, orderNumber and line, to two columns, ORDER_NUMBER and LINE:

<entity>

	<ejb-name>LineItem</ejb-name>

	<cmp2-info>

		<cmp-field>

			<field-name>orderNumber</field-name>

			<column-name>ORDER_NUMBER</column-name>

		</cmp-field>

		<cmp-field>

			<field-name>line</field-name>

			<column-name>LINE</column-name>

		</cmp-field>

	</cmp2-info>

</entity>

Mapping one field to multiple columns

Many users may employ coarse-grained entity beans that implement a Java class to represent more fine-grained data. For example, an entity bean might use an Address class as a field, but may need to map elements of the class (like AddressLine1, AddressCity, and so forth) to an underlying database. To do this, you use the <cmp-field-map> element, which defines a field map between your fine-grained class and its underlying database representation. Note that such classes must implement java.io.Serializable and all their data members must be public.

Consider an entity bean called Customer that uses the class Address to represent a customer's address. The Address class has fields for AddressLine, AddressCity, AddressState, and AddressZip. Using the following XML, we can map the class to its representation in a database with corresponding columns:

<entity>

	<ejb-name>Customer</ejb-name>

	.

	.

	<cmp2-info>

		<cmp-field>

			<field-name>Address</field-name>

			<cmp-field-map>

				<field-name>Address.AddressLine</field-name>

				<column-name>STREET</column-name>

			</cmp-field-map>

			<cmp-field-map>

				<field-name>Address.AddressCity</field-name>

				<column-name>CITY</column-name>

			</cmp-field-map>

			<cmp-field-map>

				<field-name>Address.AddressState</field-name>

				<column-name>STATE</column-name>

			</cmp-field-map>

			<cmp-field-map>

				<field-name>Address.AddressZip</field-name>

				<column-name>ZIP</column-name>

			</cmp-field-map>

		</cmp-field>

	</cmp2-info>

	.

	.

</entity>

Note that we use one <cmp-field-map> element per database column.

Mapping CMP fields to multiple tables

You may have an entity that contains information persisted in multiple tables. These tables must be linked by at least one column representing a foreign key in the linked table. For example, you might have a LineItem entity bean mapping to a table LINE_ITEM with a primary key LINE that is a foreign key in a table called QUANTITY. The LineItem entity also contains some fields from the QUANTITY table that correspond to LINE entries in LINE_ITEM. Here's what our LINE_ITEM table might look like:

LINE ORDER_NO ITEM QUANTITY COLOR SIZE
001 XXXXXXX01 Kitty Sweater 2 red XL

QUANTITY, COLOR, and SIZE are all values that are also stored in the QUANITY table, shown here. Note the identical values for some of the fields. This is because the LINE_ITEM table itself stores information in the QUANTITY table, using the LineItem entity to provide composite information.

LINE QUANTITY COLOR SIZE
001 2 red XL

Again, we can describe these relationships using a combination of <cmp-field> elements and a <table-ref> element. The <cmp-field> elements define the fields found in LineItem. Since there are some fields that require information from QUANTITY, we'll specify that generically by using a TABLE_NAME.COLUMN_NAME syntax. For instance, we'd define LINE_ITEM's COLOR column as QUANITY.COLOR. Finally, we'll specify the linking column, LINE, that makes up our primary key/foreign key relationship. We'll do this using the <table-ref> element.

Now let's look at the XML. First we define the CMP fields for the LineItem entity bean:

<entity>

	<ejb-name>LineItem</ejb-name>

	.

	.

	<cmp2-info>

		<cmp-field>

			<field-name>orderNumber</field-name>

			<column-name>ORDER_NO</column-name>

		</cmp-field>

		<cmp-field>

			<field-name>line</field-name>

			<column-name>LINE</column-name>

		</cmp-field>

		<cmp-field>

			<field-name>item</field-name>

			<column-name>ITEM</column-name>

		</cmp-field>

		<cmp-field>

			<field-name>quantity</field-name>

			<column-name>QUANTITY.QUANTITY</column-name>

		</cmp-field>

		<cmp-field>

			<field-name>color</field-name>

			<column-name>QUANTITY.COLOR</column-name>

		</cmp-field>

		<cmp-field>

			<field-name>size</field-name>

			<column-name>QUANTITY.SIZE</column-name>

		</cmp-field>	

		

Next, we specify the linking column between LINE_ITEM and QUANTITY by using a <table-ref> element.

		<table-ref>

			<left-table>

				<table-name>LINE_ITEM</table-name>

				<column-list>

					<column-name>LINE</column-name>

				</column-list>

			</left-table>

			<right-table>

				<table-name>QUANTITY</table-name>

				<column-list>

					<column-name>LINE</column-name>

				</column-list>

			</right-table>

		</table-ref>

	</cmp2-info>

</entity>

Specifying relationships between tables

To specify relationships between tables, you use the <relationships> element in ejb-borland.xml. Within the <relationships> element, you define an <ejb-relationship-role> containing the role's source (an entity bean) and a <cmr-field> element containing the relationship. The descriptor then uses <table-ref> elements to specify relationships between two tables, a <left-table> and a <right-table>. You must observe the following cardinalities:

Within the <left-table> and <right-table> elements, you specify a column list that contains the column names to be linked together. The column list corresponds to the <column-list> element in the descriptor. The XML is:

<!ELEMENT column-list (column-name+)>

Let's look at some relationships to see how this XML is put into practice:

CASE 1: a unidirectional one-to-one relationship. Here, we have a Customer entity bean with a primary key, CUSTOMER_NO, that is also used as a primary key for an entity called SpecialInfo, which contains special customer information stored in a separate table. We need to specify a relationship between these two entities. The Customer entity uses a field called specialInformation to map to the SpecialInfo bean. We specify two relationship roles -- one for each bean -- and assign either to left- and/or right-table. Then we specify the name of their related column for both.

 <relationships>

	<ejb-relation>

		<ejb-relationship-role>

			<relationship-role-source>

				<ejb-name>Customer</ejb-name>

			</relationship-role-source>

			<cmr-field>

				<cmr-field-name>specialInformation</cmr-field-name>

				<table-ref>

					<left-table>

						<table-name>CUSTOMER</table-name>

						<column-list>CUSTOMER_NO</column-list>

					</left-table>

					<right-table>

						<table-name>SPECIAL_INFO</table-name>

						<column-list>CUSTOMER_NO</column-list>

					</right-table>

				</table-ref>

			</cmr-field>

		</ejb-relationship-role>

Next, we finish the <ejb-relation> entry by providing its other half, the SpecialInfo bean. Since this is a mono-directional relationship, we don't need to specify any table elements. We only need add the following, defining the other half of the relationship and its source:

		<ejb-relationship-role>

			<relationship-role-source>

				<ejb-name>SpecialInfo</ejb-name>

			</relationship-role-source>

		</ejb-relationship-role>

	</ejb-relation>

</relationships>

CASE 2: a bidirectional one-to-many relationship. Here, we have a Customer entity bean with a primary key, CUSTOMER_NO, that is also a foreign key in an Order entity bean. We want the Borland EJB Container to manage this relationship. The Customer bean uses a field called "orders" that links a customer to his orders. The Order bean uses a field called "customers" for linking in the reverse direction. First, we define the relationship and its source for the first direction: setting up the mapping for a Customer's orders.

<relationships>

	<ejb-relation>

		<ejb-relationship-role>

			<relationship-role-source>

				<ejb-name>Customer</ejb-name>

			</relationship-role-source>

			<cmr-field>

				<cmr-field-name>orders</cmr-field-name>

Then, we add the table references to specify the relationship between the tables. We're basing this relationship on the CUSTOMER_NO column, which is a primary key for Customer and a foreign key for Orders:

				<table-ref>

					<left-table>

						<table-name>CUSTOMER</table-name>

						<column-list>

							<column-name>CUSTOMER_NO</column-name>

						</column-list>

					</left-table>

					<right-table>

						<table-name>ORDER</table-name>

						<column-list>

							<column-name>CUSTOMER_NO</column-name>

						</column-list>

					</right-table>

				</table-ref>

			</cmr-field>

		</ejb-relationship-role>

We're not quite done with our relationship, though. Now, we need to complete it by specifying the relationship role for the other direction:

		<ejb-relationship-role>

			<relationship-role-source>

				<ejb-name>Customer</ejb-name>

			</relationship-role-source>

			<cmr-field>

				<cmr-field-name>customers</cmr-field-name>

				<table-ref>

					<left-table>

						<table-name>ORDER</table-name>

						<column-list>

							<column-name>CUSTOMER_NO</column-name>

						</column-list>

					</left-table>

					<right-table>

						<table-name>CUSTOMER</table-name>

						<column-list>

							<column-name>CUSTOMER_NO</column-name>

						</column-list>

					</right-table>

				</table-ref>

			</cmr-field>

		</ejb-relationship-role>

	</ejb-relation>

	.

	.

</relationships>

CASE 3: a many-to-many relationship. If you define a many-to-many relationship, you must also have the CMP engine create a cross-table which models a relationship between the left table and the right table. Do this using the <cross-table> element, whose XML is:

<!ELEMENT cross-table (table-name, column-list, column-list)>

You may name this cross-table whatever you like using the <table-name> element. The two <column-list> elements correspond to columns in the left and right tables whose relationship you wish to model. For example, consider two tables, EMPLOYEE and PROJECT, which have a many-to-many relationship. An employee can be a part of multiple projects, and projects have multiple employees. The EMPLOYEE table has three elements, an employee number (EMP_NO), a last name (LAST_NAME), and a project ID number (PROJ_ID). The PROJECT table contains columns for the project ID number (PROJ_ID), the project name (PROJ_NAME), and assigned employees by number (EMP_NO).

To model the relationship between these two tables, a cross-table must be created.. For example, to create a cross-table that shows employee names and the names of the projects on which they are working, the <table-ref> element would look like the following:

<table-ref> 
<left-table>
<table-name>EMPLOYEE</table-name>
<column-list>
<column-name>EMP_NO</column-name>
<column-name>LAST_NAME</column-name>
<column-name>PROJ_ID</column-name>
</column-list>
</left-table>
<cross-table>
<table-name>EMPLOYEE_PROJECTS</table-name>
<column-list>
<column-name>EMP_NAME</column-name>
<column-name>PROJ_ID</column-name>
</column-list>
<column-list>
<column-name>PROJ_ID</column-name>
<column-name>PROJ_NAME</column-name>
</column-list>
</cross-table>
<right-table>
<table-name>PROJECT</table-name>
<column-list>
<column-name>PROJ_ID</column-name>
<column-name>PROJ_NAME</column-name>
<column-name>EMP_NO</column-name>
</column-list>
</right-table>
</table-ref>

Since these are "secondary tables" and therefore have no primary keys, the PROJ_ID column appears in both column lists. This could also be the common column EMP_NO, depending upon how you wish to model the data.

Setting Properties

Most properties for Enterprise JavaBeans can be set in their deployment descriptors. The Borland Deployment Descriptor Editor (DDEditor) also allows you to set properties and edit descriptor files. Use of the Deployment Descriptor Editor is described in the Borland Enterprise Server User's Guide. Use properties in the deployment descriptor to specify information about the entity bean's interfaces, transaction attributes, and so forth, plus information that is unique to an entity bean. In addition to the general descriptor information for entity beans, here are also three sets of properties that can be set to customize CMP implementations -- entity properties, table properties, and column properties. Entity properties can be set either by the EJB Designer Tab in the Deployment Descriptor Editor or in the XML directly.

Using the Deployment Descriptor Editor

You can use the Deployment Descriptor Editor, which is part of the Borland Enterprise Server AppServer Edition, to set up all of the container-managed persistence information. You should refer to the Borland Enterprise Server User's Guide for complete information on the use of the Deployment Descriptor Editor and other related tools. Most operations for CMP 2.0 are performed via the EJB Designer, a component of the Deployment Descriptor Editor. The following table shows descriptor information and where in the Deployment Descriptor Editor that information can be entered.

J2EE 1.3 Entity Bean (CMP 2.0 via the EJB Designer)

Descriptor Element Navigation Tree Node/Panel Name DDEditor Tab
Entity Bean name Bean General
Entity Bean class Bean General
Home Interface Bean General
Remote Interface Bean General
Local Home Interface Bean General
Local Interface Bean General
Home JNDI Name Bean General
Local Home JNDI Name Bean General
Persistence Type (CMP or BMP) Bean General
CMP Version Bean General
Primary Key Class Bean General
Reentrancy Bean General
Icons Bean General
Environment Entries Bean Environment
EJB References to other Beans Bean EJB References
EJB Links Bean EJB References
Resource References to data objects/connection factories Bean Resource References
Resource Reference type Bean Resource References
Resource Reference Authentication Type Bean Resource References
Security Role References Bean Security Role References
Entity Properties Bean Properties
Security Identity Bean Security Identity
EJB Local References to beans in the name JAR Bean EJB Local References
EJB Local Links Bean EJB Local References
Resource Environmental References for JMS Bean Resource Env Refs
Container Transactions Bean:Container Transactions Container Transactions
Transactional Method Bean:Container Transactions Container Transactions
Transactional Method Interface Bean:Container Transactions Container Transactions
Transactional Attribute Bean:Container Transactions Container Transactions
Method Permissions Bean:Method Permissions Method Permissions
Entity, Table, and Column Properties JAR EJB Designer (see below)

Setting CMP 2.0 Properties

Borland Enterprise Server uses its EJB Designer, a component of the Deployment Descriptor Editor, to set some CMP 2.0 properties. The EJB Designer is fully-documented in the User's Guide.

Editing Entity properties

To edit Entity properties using the EJB Designer:

  1. Start the DDEditor and open the deployment descriptor for the JAR containing your entity beans.
  2. Select the top-level object in the DDEditor's Navigation Pane. In the Properties Pane you will see three tabs -- General, XML, and EJB Designer.
  3. Choose the EJB Designer Tab and left-click on any of the bean representations that appear. Click the Properties button. The Entity Beans Properties window appears.
  4. Edit the properties you desire and click OK. The properties themselves are discussed below.

Editing Table and Column properties

Table and Column properties can only be set by editing the ejb-borland.xml descriptor file from the DDEditor's Vendor XML Tab. To edit or add Table and Column properties:

  1. Start the DDEditor and open the deployment descriptor for the JAR containing your entity beans.
  2. Select the top-level object in the DDEditor's Navigation Pane. In the Properties Pane you will see three tabs -- General, XML, and EJB Designer.
  3. Select the XML Tab. Two additional Tabs are now available in the Properties Pane -- Standard and Vendor. Choose Vendor.
  4. Locate either the <column-properties> or <table-properties> elements and add property definitions in accordance with the borland-specific DTD, shown here. Germane entries are in bold. Descriptions of the entity, table, and column properties follow, including their data type, default values, and a property description.

Entity Properties

Property Type Default Description
ejb.invalidateFinderCollectionAtCommit java.lang.Boolean False Whether or not to optimize transaction commit by invalidating finder collections.
ejb.maxBeansInCache java.lang.Integer 1000 The maximum number of beans in the Option A cache. If the cache exceeds this limit, entities will be moved to the ready pool by calling ejbPassivate().
ejb.cacheCreate java.lang.Boolean True Whether or not to attempt to cache the entity bean until the transaction commits.
ejb.maxBeansInPool java.lang.Integer 1000 The maximum number of beans in the ready pool. If the ready pool exceeds this limit, entities will be removed from the container by calling unsetEntityContext().
ejb.TransactionCommitMode Enumerated Shared

Indicates the disposition of an entity bean with respect to a transaction. Acceptable values are:

  • Exclusive: This entity has exclusive access to the particular table in the database. The state of the bean at the end of the last committed transaction can be assumed to be the state of the bean at the beginning of the next transaction.
  • Shared: This entity shares access to the particular table in the database. However, for performance reasons, a particular bean remains associated with a particular primary key between transactions to avoid extraneous calls to ejbActivate() and ejbPassivate() between transactions. The bean stays in the active pool.
  • None: This entity shares access to the particular table in the database. A particular bean does not remain associated with a particular primary key between transactions, but goes back to the ready pool after every transaction.

Table Properties

Property Type Default Description
datasource java.lang.String None JNDI datasource name of the database for this table.
optimisticConcurrencyBehavior java.lang.String UpdateModifiedFields

Specifies the behavior the PM should exhibit when updates occur on shared tables. Acceptable values are:

  • UpdateAllFields: perform an update on all of an entity's fields, regardless if they were modified or not.
  • UpdateModifiedFields: perform an update only on fields known to have been modified prior to the update being issued.
  • VerifyModifiedFields: verify the entity's modified fields against the database prior to update.
  • VerifyAllFields: verify all the entity's fields against the database prior to update regardless if they were modified or not.
useGetGeneratedKeys java.lang.Boolean False Whether to use the JDBC3 java.sql.Statement.getGeneratedKeys() method to populate the primary key from autoincrement/sequence SQL fields. Currently, only Borland JDataStore supports this statement.
primaryKeyGenerationListener java.lang.String None Specifies a class, written by the user, that implements com.borland.ejb.pm.PrimaryKeyGenerationListener interface and generates primary keys..
jdbcAccesserFactory java.lang.String None A factory class that can provide accessor class implementations to get values from a java.sql.ResultSet, and set values for a java.sql.PreparedStatement.
getPrimaryKeyBeforeInsertSql java.lang.String None SQL statement to execute before inserting a row to provide primary key column names.
getPrimaryKeyAfterInsertSql java.lang.String None SQL statement to execute after inserting a row to provide primary key column names.
useAlterTable java.lang.Boolean False Whether or not to use the SQL ALTER statement to alter an entity's table to add columns for fields that do not have a matching column.
createTableSql java.lang.String None One or more SQL statements used to create the table if it needs to be created automatically.
createTables java.lang.Boolean False The Borland CMP engine automatically creates tables for Cloudscape and JDataStore databases -- that is, in the development environment. To enable automatic table creation in other databases, you must set this flag to true.

Column Properties

Property Type Default Description
ignoreOnInsert java.lang.String None Specifies the column that must not be set during the execution of an INSERT statement. This property is used in conjunction with the getPrimaryKeyAfterInsertSql property.
createColumnSql java.lang.String None The Borland CMP engine uses a lookup table to determine the standard Java-to-SQL mapping for the column's data type. Occasionally this lookup table is incorrect or inconsistent with a database vendor's SQL implementation. To override the standard data-type lookup and specify the data type manually, use this property.
columnJavaType java.lang.String None

Java type used to create this column if the table needs to be created automatically. The acceptable values are:

  • java.lang.Boolean
  • java.lang.Byte
  • java.lang.Character
  • java.lang.Short
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Float
  • java.math.BigDecimal
  • java.lang.String
  • java.sql.Time
  • java.sql.Date
  • java.sql.TimeStamp
  • java.io.Serializable

This property is ignored if createColumnSql is set.