The Life Cycle of an Entity Bean

To understand how to best develop entity beans, it is important to understand how the container manages them. The EJB specification defines just about every major event in an entity bean’s life, from the time it is instantiated to the time it is garbage collected. This is called the life cycle, and it provides the bean developer and EJB vendors with all the information they need to develop beans and EJB servers that adhere to a consistent protocol. To understand the life cycle, we will follow an entity instance through several life-cycle events and describe how the container interacts with the entity bean during these events. Figure 10-2 illustrates the life cycle of an entity instance.

Entity bean life cycle

Figure 10-2. Entity bean life cycle

This section identifies the points at which the container calls each of the methods described in the EntityBean interface as well as the find methods and the select and home methods. Bean instances must implement the EntityBean interface, which means that invocations of the callback methods are invocations on the bean instance itself.

At each stage of the entity bean’s life cycle, the bean container provides varying levels of access. For example, the EntityContext.getPrimaryKey( ) method will not work if it is invoked in the ejbCreate( ) method, but it does work when called in the ejbPostCreate( ) method. Other EJBContext methods have similar restrictions, as does the JNDI ENC.

Does Not Exist

The entity bean begins life as a collection of files. Included in that collection are the bean’s deployment descriptor, component interfaces, and all the supporting classes generated at deployment time. At this stage, no instance of the bean exists.

The Pooled State

When the EJB server is started, it reads the EJB’s files and instantiates several instances of the entity bean’s bean class, which it places in a pool. The instances are created by calling the Class.newInstance( ) method on the bean class. The newInstance( ) method creates an instance using the default constructor, which has no arguments.[27] This means that the persistence fields of the bean instances are set at their default values; the instances themselves do not represent any data in the database.

Immediately following the creation of an instance, and just before it is placed in the pool, the container assigns the instance its EntityContext. The EntityContext is assigned by calling the setEntityContext( ) method of the EntityBean interface, which is implemented by the bean class. After the instance has been assigned its context, it is entered into the instance pool.

In the instance pool, the bean instance is available to the container as a candidate for servicing client requests. Until it is requested, however, the bean instance remains inactive unless it is used to service a query method (i.e., find or select method) or ejbHome( ) request. Bean instances in the Pooled state typically are used to service query and ejbHome( ) requests, which makes perfectly good sense because they aren’t busy and these methods don’t rely on the bean instance’s state. All instances in the Pooled state are equivalent. None of the instances are assigned to an EJB object, and none of them has meaningful state.

The Ready State

When a bean instance is in the Ready state, it can accept client requests. A bean instance moves to the Ready state when the container assigns it to an EJB object. This occurs under two circumstances: when a new entity bean is being created, or when the container is activating an entity.

Transitioning from the Pooled state to the Ready state via creation

When a client application invokes a create( ) method on an EJB home, several operations must take place before the EJB container can return a remote or local reference (EJB object) to the client. First, an EJB object must be created on the EJB server.[28] Once the EJB object is created, an entity bean instance is taken from the instance pool and assigned to the EJB object. Next, the create( ) method, invoked by the client, is delegated to its corresponding ejbCreate( ) method on the bean instance. After the ejbCreate( ) method completes, a primary key is created.

When the ejbCreate( ) method is done, the ejbPostCreate( ) method on the entity bean instance is called. Finally, after the successful completion of the ejbPostCreate( ) method, the home is allowed to return a remote or local reference—an EJB object—to the client. The bean instance and EJB object are now ready to service method requests from the client. This is one way that the bean instance can move from the Pooled state to the Ready state.

Transitioning from the Pooled state to the Ready state via a query method

When a query method is executed, each EJB object that is found as a result of the query will be realized by transitioning an instance from the Pooled state to the Ready state. When an entity bean is found, it is assigned to an EJB object and its EJB object reference is returned to the client. A found bean follows the same protocol as a passivated bean; it is activated when the client invokes a business method, and will move into the Ready state through activation, as described in the next section.

In many cases (depending on the EJB vendor), found entity beans don’t actually migrate into the Ready state until they are accessed by the client. So, for example, if a find method returns a collection of entity beans, the entity beans may not be activated until they are obtained from the collection or accessed directly by the client. Resources are saved by activating entity beans lazily (as needed).

Transitioning from the Pooled state to the Ready state via activation

The activation process can also move an entity bean instance from the Pooled state to the Ready state. Activation facilitates resource management by allowing a few bean instances to service many EJB objects. Activation was explained in Chapter 3, but we will revisit the process here as it relates to the entity bean instance’s life cycle. Activation presumes that the entity bean has previously been passivated . More is said about this state transition later; for now, suffice it to say that when a bean instance is passivated, it frees any resources that it does not need and leaves the EJB object for the instance pool. When the bean instance returns to the pool, the EJB object is left without an instance to which to delegate client requests. The EJB object maintains its stub connection on the client, so as far as the client is concerned, the entity bean hasn’t changed. When the client invokes a business method on the EJB object, the EJB object must obtain a bean instance. This is accomplished by activating a bean instance.

When a bean instance is activated, it leaves the instance pool (the Pooled state) to be assigned to an EJB object. Once assigned to the proper EJB object, the ejbActivate( ) method is called—the instance’s EntityContext can now provide information specific to the EJB object, but it cannot provide security or transactional information. The ejbActivate( ) callback method can be used in the bean instance to reobtain resources or perform any other necessary work before servicing the client.

When an entity bean instance is activated, nonpersistent instance fields of the bean instance may contain arbitrary (dirty) values and should be reinitialized in the ejbActivate( ) method.

In container-managed persistence, container-managed fields are automatically synchronized with the database after ejbActivate( ) is invoked and before a business method can be serviced by the bean instance. The order in which these things happen in CMP entity beans is:

  1. ejbActivate( ) is invoked on the bean instance.

  2. Persistence fields are synchronized automatically.

  3. ejbLoad( ) notifies the bean that its persistence fields have been synchronized.

  4. Business methods are invoked as needed.

In bean-managed persistence, persistence fields are synchronized by the ejbLoad( ) method after ejbActivate( ) has been called and before a business method can be invoked. Here is the order of operations in bean-managed persistence:

  1. ejbActivate( ) is invoked on the bean instance.

  2. ejbLoad( ) is called to let the bean synchronize its persistence fields.

  3. Business methods are invoked as needed.

Transitioning from the Ready state to the Pooled state via passivation

A bean can move from the Ready state to the Pooled state via passivation, which is the process of disassociating a bean instance from an EJB object when it is not busy. After a bean instance has been assigned to an EJB object, the EJB container can passivate the instance at any time, provided that the instance is not currently executing a method. As part of the passivation process, the ejbPassivate( ) method is invoked on the bean instance. This callback method can be used by the instance to release any resources or perform other processing prior to leaving the EJB object. When ejbPassivate( ) has completed, the bean instance is disassociated from the EJB object server and returned to the instance pool. The bean instance is now back in the Pooled state.

A bean-managed entity instance should not try to save its state to the database in the ejbPassivate( ) method; this activity is reserved for the ejbStore( ) method. The container will invoke ejbStore( ) to synchronize the bean instance’s state with the database prior to passivating the bean.

The most fundamental thing to remember is that, for entity beans, passivation is simply a notification that the instance is about to be disassociated from the EJB object. Unlike stateful session beans, an entity bean instance’s fields are not serialized and held with the EJB object when the bean is passivated. Whatever values were held in the instance’s nonpersistent fields when the entity bean was assigned to the EJB object will be carried with it to its next assignment.

Transitioning from the Ready state to the Pooled state via removal

A bean instance also moves from the Ready state to the Pooled state when it is removed. This occurs when the client application invokes one of the remove methods on the bean’s EJB object or EJB home. With entity beans, invoking a remove method deletes the entity’s data from the database. Once the entity’s data has been deleted from the database, it is no longer a valid entity.

Once the ejbRemove( ) method has finished, the bean instance is moved back to the instance pool and out of the Ready state. It is important that the ejbRemove( ) method release any resources that would normally be released by ejbPassivate( ), which is not called when a bean is removed. This can be done, if need be, by invoking the ejbPassivate( ) method within the ejbRemove( ) method body.

In bean-managed persistence, the ejbRemove( ) method is implemented by the entity bean developer and includes code to delete the entity bean’s data from the database. The EJB container will invoke the ejbRemove( ) method in response to a client’s invocation of the remove( ) method on one of the component interfaces.

In container-managed persistence, the ejbRemove( ) method notifies the entity bean instance that its data is about to be removed from the database. Immediately following the ejbRemove( ) call, the container deletes the entity bean’s data.

In CMP the container also cleans up the entity bean’s relationships with other entity beans in the database. If a cascade delete is specified, it removes each entity bean in the cascade delete relationships. This involves activating each entity bean and calling its ejbActivate( ) methods, loading each entity bean’s state by calling its ejbLoad( ) method, calling the ejbRemove( ) on all of the entity beans in the cascade-delete relationship, and then deleting their data. This process can continue in a chain until all the cascade-delete operations of all the relationships have completed.

Life in the Ready State

A bean is in the Ready state when it is associated with an EJB object and is ready to service requests from the client. When the client invokes a business method, like Ship.getName( ), on the bean’s remote or local reference (EJB object), the method invocation is received by the EJB server and delegated to the bean instance. The instance performs the method and returns the results. As long as the bean instance is in the Ready state, it can service all the business methods invoked by the client. Business methods can be called zero or more times, in any order.

In addition to servicing business methods, an entity bean in the Ready state can execute select methods, which are called by the bean instance while servicing a business method.

The ejbLoad( ) and ejbStore( ) methods, which synchronize the bean instance’s state with the database, can be called only when the bean is in the Ready state. These methods can be called in any order, depending on the vendor’s implementation. Some vendors call ejbLoad( ) before every method invocation and ejbStore( ) after every method invocation, depending on the transactional context. Other vendors call these methods less frequently.

In bean-managed persistence, the ejbLoad( ) method should always use the EntityContext.getPrimaryKey( ) method to obtain data from the database and should not trust any primary key or other data that the bean has stored in its fields. (This is how we implemented it in the bean-managed version of the Ship bean in Chapter 9.) It should be assumed, however, that the state of the bean is valid when calling the ejbStore( ) method.

In container-managed persistence, the ejbLoad( ) method is always called immediately following the synchronization of the bean’s container-managed fields with the database—in other words, right after the container updates the state of the bean instance with data from the database. This provides an opportunity to perform any calculations or reformat data before the instance can service business-method invocations from the client. The ejbStore( ) method is called just before the database is synchronized with the state of the bean instance—just before the container writes the container-managed fields to the database. This provides the CMP entity bean instance with an opportunity to change the data in the container-managed fields prior to their persistence to the database.

In bean-managed persistence, the ejbLoad( ) and ejbStore( ) methods are called when the container deems it appropriate to synchronize the bean’s state with the database. These are the only callback methods that should be used to synchronize the bean’s state with the database. Do not use ejbActivate( ), ejbPassivate( ), setEntityContext( ), or unsetEntityContext( ) to access the database for the purpose of synchronization. You should use the ejbCreate( ) and ejbRemove( ) methods, however, to insert and delete (respectively) the entity’s data into and from the database.

End of the Life Cycle

A bean instance’s life cycle ends when the container decides to remove it from the pool and allow it to be garbage collected. This happens under a few different circumstances. If the container decides to reduce the number of instances in the pool—usually to conserve resources—it releases one or more bean instances and allows them to be garbage collected. The ability to adjust the size of the instance pool allows the EJB server to manage its resources (the number of threads, available memory, etc.) so that it can achieve the highest possible performance.

When an EJB server is shut down, most containers release all the bean instances so that they can be safely garbage collected. Some containers may also decide to release any instances that are behaving unfavorably or that have suffered from some kind of unrecoverable error that makes them unstable. For example, any time an entity bean instance throws a type of RuntimeException from any of its methods, the EJB container will evict that instance from memory and replace it with a stable instance from the instance pool.

When an entity bean instance leaves the instance pool to be garbage collected, the unsetEntityContext( ) method is invoked by the container to alert the bean instance that it is about be destroyed. This callback method lets the bean instance release any resources it maintains before being garbage collected. Once the bean’s unsetEntityContext( ) method has been called, it is garbage collected.

The bean instance’s finalize( ) method may or may not be invoked following the unsetEntityContext( ) method. A bean should not rely on its finalize( ) method, since each vendor handles evicting instances differently.



[27] Constructors should never be defined in the bean class. The default no-argument constructor, which is implicit if no other constructors are declared, must be available to the container.

[28] This is only a conceptual model. In reality, an EJB container and the EJB object may be the same thing, or a single EJB object may provide a multiplexing service for all entities of the same type. The implementation details are not as important as understanding the life-cycle protocol.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.27.251