In the first article in this series, I touched upon how EJB specification architects have enhanced the EJB specs to meet the goals that were set out for EJB 2. In particular, I discussed integration of JMS with EJB, the addition of local interfaces for EJBs to provide lightweight access to EJBs from local clients. In this part, we will continue taking a look at the goals of the EJB 2 specifications and details as to how those goals have been achieved.
Goals of the EJB 2.0 Specification
The Proposed Final Draft 2 specifically lists the goals for the 2.0 specification as:
- Define the integration of EJB with the Java Message Service (JMS)
- Provide a local client view and support for efficient, lightweight access to EJBs from local clients
- Provide improved support for the persistence of entity beans
- Provide improved support for management of relationships among entity beans
- Provide a query syntax for entity bean finder methods
- Provide support for additional methods in the home interface
- Provide for network interoperability among EJB servers.
Goals 1 and 2 have been discussed in the previous article.
Goal 3: Improved support of entity bean persistence
The lifetime of an entity bean is not dependent on the lifetime of the JVM in which it executes. The state of entity beans is retained between JVM process invocations. We call this entity bean persistence of which there are two types, namely Container Managed Persistence (CMP) and Bean Managed Persistence (BMP). As the names say, the persistence schema, relationships, and mechanisms can be hard-coded by the bean itself or be managed by the container through the deployment descriptor.
The earlier specification was limited in the sense that it was too simplistic. Only the persistent instance variables of an entity bean could be exposed and persisted. There was no support for exposing relationships between beans. This was largely due to the fact that EJBs had only remote interfaces and it was heavy for the container to access the EJB through its remote interfaces to load and store its state.
Using the foundations of local interfaces that provide lightweight access to the EJB, the container is now empowered to perform flexible, incremental field access to the state of the entity bean. To illustrate let's take an example of a Subscriber object that is further modeled as having instance fields such as Address, Preferences, etc. The instance fields can be modeled as local interface entity beans and the Subscriber as a remote interface entity bean. Clients that need to access the Subscriber object do so through its remote interface. The container is equipped with the knowledge of the relationship between the Subscriber bean and the Address and Preferences dependent beans and automatically manages its load and store without requiring the bean developer to load and store the dependent objects explicitly through code. This is an improvement over the EJB 1.1 specification, resulting in new concepts of Container Managed Relationships (CMR) and dependent objects. This also enables the persistent system to have finer grained access to the dependent objects by loading them lazily or incrementally.
In order to introduce this level of CMP and CMR, significant changes have been made to the specifications. Entity beans using CMP are now abstract classes that do not define the fields of CMP. These fields are specified in the deployment descriptor instead. The bean developer need only define the get and set methods of these fields. Here is an error-prone condition that may need some attention. If the fields defined in the deployment descriptor have discrepancies with the accessor methods, errors will occur. The container should catch this. The container now provides all the implementations of the abstract entity bean class and the accessor/mutator methods.
Containers that support EJB 2 must also support EJB 1.1 for backward compatibility. Since EJB 1.1 does not support local interfaces, there is practically no unified way of integrating the new with the old, resulting in the EJB 2 entity bean persistence contracts being separate from those of EJB 1.1. Developers must choose either one or the other. This adds some overhead of seemingly duplicate interfaces but allows the developer to choose the type and level of CMP that is required.
One-hundred percent delegation of entity bean persistence to the container is realized with the addition of Container Managed Relationships. All the bean developer needs to do is describe the fields and relationships to the container through the deployment descriptor, and the container handles all the data access and updates automatically. The offset of this delegation is that the bean deployer must perform some extra steps.
Goal 4: Improved support for management of relationships among entity beans
Earlier specifications of EJB did not provide support for CMR between beans. It was not possible earlier to specify that an entity bean or a set of entity beans were related to another entity bean or set of entity beans and have the container manage these relations. All such relations had to be hard coded and managed by the bean developer (bean managed relationships, if you will). EJB 2 specifies a relationship architecture allowing the bean developer to declare relationships and have the container manage the state and persistence of the relationship.
Relationships may be of three types, one-to-one, one-to-many, and many-to-many. Examples would be a Subscriber and its Personal profile, a Subscriber and its Buddy List of Subscribers and a set of newsletters sent to a set of Subscribers within a stipulated time period. All of these need to be persisted and the relations between the entity beans need to be managed in event of changes by the container.
The work of container persistence has already been tackled in earlier specifications. The container gains knowledge of the relationships between the entity beans from the <relationship> field of the deployment descriptor.
Entity beans on either side of the relationship use accessor methods to access the involved bean. Again, local interfaces provide the necessary view of exposed accessors. Any bean with defined local interfaces can be a target of a relationship. Also the CMR fields must not be exposed through remote interfaces.
The bean developer simply uses the accessors to access the bean, just like any other field. Accessors for one-to-many or many-to-many relationship fields use the java.util.Collections or the java.util.Set API. The implementation of CMR fields are delegated to the container.
The entity beans fields that are part of relationships are defined in the beans abstract persistence schema though the <cmr-field> element. Elements of the deployment descriptor that describe the type of the relationship are <ejb-relation> and <ejb-relationship-role>.
CMR is a significant step forward that allows server-side application developers to realistically and explicitly model complex component relationships. Shielding the bean developer from management details of relationships allows the bean developer to focus more attention on complex business logic.
The much improved CMR and CMP will be a widely popular addition to EJB 2. In the next article I will introduce the remaining goals of the EJB 2.0 specs, what they mean, and how they impact bean developers.