Developing Entity Beans
- A Closer Look at Entity Beans
- Developing a CMP Bean
- Developing a BMP Bean
- Advanced Container-Managed Persistence
- Transactions
- Container Security
- Design Guidelines
- In Practice
- Summary
In This Chapter
- A Closer Look at Entity Beans
- Developing a CMP Bean
- Developing a BMP Bean
- Advanced Container-Managed Persistence
- Transactions
- Container Security
- Design Guidelines
Entities have a singular purpose: to represent an entity of data from a given data source. This typically represents a record within a database. The beauty of this component is the capability to manipulate the data stored within a data store through a standard interface instead of having to send manipulation calls directly to the data source in any manner. This technique of wrapping manipulation to a data source is not new; you might know it as object to relational mapping.
This object mapping requires that an entity bean be responsible for inserting, updating, selecting, and removing data within the data source. This process of managing the communication between the component and the data source is called persistence. In other words, persistence is this process of writing the information to an external data source. As you discovered in Chapter 21, "An Architectural Overview of Enterprise JavaBeans," we defined two types of entity beans. Using the first entity type, the container manages all the persistence itself. This entity type is called container managed persistence (CMP). The other type informs the container that you, the developer, are required to manage all the manipulation to your given data source. This type is called bean managed persistence (BMP).
The most current version of entity beans is defined within the EJB 2.0 specification. The EJB 2.0 specification does not abandon support for 1.1 beans. There are a number of significant changes between 1.1 and 2.0, such that you cannot develop one bean that will work with both specifications.
As we work to understand Enterprise JavaBeans, and more specifically in this section entity beans, we will look at examples and even put them into practice. We will explore the following topics:
-
Developing CMP and BMP beans
-
Deploying entity beans
-
Using entity beans
A Closer Look at Entity Beans
As we look at an entity, you will see that it is an object-oriented representation of the data contained within a data source. This important feature allows you as a developer to easily represent data in a relational data source as an object within Java. Ultimately, Java requires data to be represented within an object footprint, and this makes the process simple.
It is important for you to understand that entity beans are a single representation of data, whereas a session bean can have multiple instances of the bean representing data. This implies an important difference between entity beans and session beans: The life span of a session bean is dependent on the life span of the client, whereas the life span of an entity bean is a relationship to data.
Bean Life Cycle
Unlike session beans, an entity bean survives beyond the client session using it. Even though the client creates an instance of an entity bean, the entity bean remains available until the container and only the container decides to remove it.
If we investigate the sequence diagram, shown in Figure 23.1, we can see that, as in the session bean, the entity's sequence diagram has a similar-looking state transition diagram (refer to Figure 22.2).
When the client invokes the create() method on the home interface, the bean is then created and placed within the pool of available beans. This pool contains all currently instantiated entity beans of this type. In the sequence diagram, you will see that the transition from Does not exist to pooled varies between BMP and CMP.
At some point, the container may decide to "garbage" collect pooled beans. The container calls unsetEntityContext() to deallocate the current associated entity of data. The EJB specification does not define the frequency or trigger for this action to execute, only that the bean must have the capability to accomplish this. In other words, different vendors trigger the garbage collector at different times. For example, Borland's Enterprise Server executes it on the length of inactivity of the bean.
If the client then invokes one of the finder methods, the bean finds the instance of the data in the data source, copies the primary key into the instance's member variables, and finally returns the bean to the pool. In many instances, this does not cause the entire instance to be loaded into the entity bean. This happens when the ejbLoad() method is called to synchronize the data with the data source.
Figure 23.1 Client's perspective of the state of an entity bean.What Are CMP and BMP Anyway?
The main goal for having two different types of entity beans is to give developers the ultimate flexibility for implementing entity beans as they see fit, but clients of the bean do not have to be aware or concerned with the implementation.
This is accomplished by giving you container managed persistence and bean managed persistence. First, container managed persistence addresses one of the main goals of Enterprise JavaBeans, which is to split work between the component developer and the container. The goals for container managed persistence are basic and important:
Free up the developer to work on business logic rather than persistence. This is accomplished by allowing the container to manage all the persistence and loading of data. For example, if you are developing an order entry system, you can communicate only to a data source using SQL, thus the communication is well defined and fairly repetitive except for the data context.
Persistence services can be developed by persistence specialists. In other words, this means that persistence is most likely going to run faster, with more transactional safety, and scale better. Using the EJB 2.0 specification has expanded greatly the performance and capabilities of the container managed persistence bean.
CMP beans are portable across EJB containers and data sources. EJB containers that support the EJB 2.0 specification facilitate the movement of an entity bean from one container to another rather seamlessly. In fact, some containers even attempt to work in specific database vendor features for performance and scalability but still allowing portability.
Finally, bean managed persistence is an alternative to using container managed persistence. Just as the name implies, it allows the bean to persist the instance in which the bean developer must implement. The goals of bean managed persistence are slightly more nebulous. For example, anything you cannot accomplish in a container managed persistence bean, you can accomplish in a bean managed persistence component. Some of these include the following:
You might have specific JDBC features that are required for your DBMS vendor. For example, you might need to accomplish your persistence with stored procedures or bulk inserts. Note: Some vendors have added stored procedure communication to container managed persistence.
You might have proprietary object-to-relational mapping provided by another tool. For example, TopLink is a popular object mapping tool that generates the code for bean managed persistence.
You might need to encapsulate communicating to a nonrelational data store. For example, you might want to communicate to a mainframe or mini using a proprietary data store for a given application.
It is unlikely that you cannot accomplish all of an application's persistence requirements using container managed persistence. The EJB 2.0 specifications include many new features for CMP beans that make BMP almost obsolete in most occasions.
EJB 2.0 Versus EJB 1.1
There were two large problems with the EJB 1.1 specification as it related to entity beans. The EJB 2.0 specifications focused on these two problems:
It was difficult to build coarse-grained entity beans.
Finder methods lacked portability.
The Enterprise JavaBean 2.0 specifications have provided a number of new features to fill some of the gaps found in the EJB 1.1 specification. Table 23.1 presents some of the problems found after many applications were written using the EJB 1.1 specification and how the 2.0 specification resolves them.
Table 23.1 EJB 1.1 Specification Versus EJB 2.0 Specifications
EJB 1.1 Problem |
EJB 2.0 Solution |
No good pattern to represent dependent objects within an entity bean |
The introduction of local interfaces, which allow for modeling of dependent objects as another bean but still allow for good performance. |
Load-on-demand and dirty checking of data |
EJB 2.0 CMP has abstract methods available for the implementation of load-on-demand and dirty checking. |
No portable way to ensure the contents of a collection within a container's persistence strategy |
The EJB container maintains collection classes that simplify the object-to-relational mapping. |
Data-aliasing contention created when two or more entities reference the same dependent object |
Dependent objects are managed as entity objects by the container. The container then manages the state of the entity component. This ultimately allows for synchronization within the transaction with multiple entities being represented as multiple aliases. |
No portable implementation of finder methods |
A portable query language was implemented based on a subset of SQL. |
With these new features, most of which have been added to container managed persistence, entity beans have become extremely powerful and efficient. A developer can simply model most if not all of the persistence requirements within JBuilder allowing you to work on your business methods rather than plumbing.
Primary Keys
As we have looked at entity beans to this point, the key consideration is that relational data is represented in the object world. Therefore, just as the relational world represents a unique instance of data with a primary key, you must do the same in the object world. This special class is called the primary key. Its sole purpose is to uniquely identify an instance of an entity bean. In other words, the primary key class contains all the information required to find an entity within the persistent data store. To accomplish this successfully, a number of rules must be followed:
The primary key instances must be any legal type in RMI/IIOP. In other words, it must be serializable.
It must provide a hashcode() and equals() method.
It must uniquely identify a single instance of the data stored within the persistent data store. For example, the primary key of the table is probably a good primary key for the entity.
In container managed persistence, the class must have a constructor that takes no arguments. Because the container is responsible for creating instances, it must have the capability to create a primary key class.
The Interface
The beauty of entity beans is that, whenever you develop a CMP or BMP, the interface is the same to the client. This allows for the user of the bean to be isolated from the overall implementation of the bean. This is where session beans and entity beans differ greatly; a session bean has a method for each business method required. For CMP beans, you let the container provide the implementation of the interface, whereas with BMP beans you, as the developer, implement the interface. We'll now take a look at the interface provided for Enterprise JavaBeans (see Listing 23.1).
Listing 23.1 EntityBean Interface for Implementation by the Entity Bean
// JBuilder API Decompiler stub source generated from class file // Jul 5, 2002 // -- implementation of methods is not available package javax.ejb; // Imports import java.rmi.RemoteException; public abstract interface EntityBean extends EnterpriseBean { // Methods void ejbActivate() throws EJBException, RemoteException; void ejbLoad() throws EJBException, RemoteException; void ejbPassivate() throws EJBException, RemoteException; void ejbRemove() throws RemoveException, EJBException, RemoteException; void ejbStore() throws EJBException, RemoteException; void setEntityContext(EntityContext entityContext) throws EJBException, RemoteException; void unsetEntityContext() throws EJBException, RemoteException; }
In addition to implementation of the preceding interface, the bean developer is required to also implement an ejbCreate() and an ejbPostCreate() that correspond with each create() method signature within the home interface.
As you look at this interface, you will see that it supports the four basic operations required of any persistent data store; they are known as CRUD. The four basic operations you might want to perform on data are
Create (C)
Read (R)
Update (U)
Delete (D)
Each of the four operations of a persistent data store is represented by a corresponding entity interface callback method. Create relates to ejbCreate() and ejbPostCreate(). Reading is implemented using ejbLoad(). Update is implemented using the ejbStore(), and finally delete is implemented using ejbRemove(). These callbacks are then managed by the container based entirely on the life cycle of the entity bean.
In addition to the CRUD requirements, you also have a few other methods to implement. If you compare the ejbActivate() and ejbPassivate() methods to that defined within a session bean, you will notice they are similar. By default, an entity bean saves its instance data to a secondary data store so that the requirements of activation and passivation are not as important. More importantly, it uses ejbActivate() as a notification mechanism when the entity bean's instance has been associated with a primary key class. ejbPassivate() is then called to notify the entity that the primary key is being disassociated with the primary key class and is available to another instance.
Finally, the last two methods are setEntityContext() and unsetEntityContext(). The setEntityContext() method allows a bean to access the bean's context. This is important when using entity beans because you use the context to associate the primary key to an instance. The unsetEntityContext() allows you to remove the allocation of resources.