EJB.9.1 Concepts


EJB.9.1.1 Runtime Execution Model

This section describes the runtime model and the classes used in the description of the contract between an entity bean and its container. (See Figure EJB.9-1.)

Figure EJB.9-1. Overview of the Entity Bean Runtime Execution Model

An enterprise bean instance is an object whose class was provided by the bean provider.

An entity EJBObject is an object whose class was generated at deployment time by the container provider's tools. The entity EJBObject class implements the entity bean's remote interface. A client never references an entity bean instance directly ”a client always references an entity EJBObject whose class is generated by the container provider's tools.

An entity EJBHome object provides the life cycle operations (create, remove, find) for its entity objects. The class for the entity EJBHome object is generated by the container provider's tools at deployment time. The entity EJBHome object implements the entity bean's home interface that was defined by the bean provider.

EJB.9.1.2 Granularity of Entity Beans

This section provides guidelines to the bean providers for modeling of business objects as entity beans.

In general, an entity bean should represent an independent business object that has an independent identity and life cycle, and is referenced by multiple enterprise beans and/or clients .

A dependent object should not be implemented as an entity bean. Instead, a dependent object is better implemented as a Java class (or several classes) and included as part of the entity bean on which it depends.

A dependent object can be characterized as follows . An object B is a dependent object of an object A, if B is created by A, accessed only by A, and removed by A. This implies, for example, that if B exists when A is being removed, B is automatically removed as well. It also implies that other programs can access the object B only indirectly through object A. In other words, the object A fully manages the life cycle of the object B.

For example, a purchase order might be implemented as an entity bean, but the individual line items on the purchase order should be implemented as helper classes, not as entity beans. An employee record might be implemented as an entity bean, but the employee address and phone number should be implemented as helper classes, not as entity beans.

The state of an entity object that has dependent objects is often stored in multiple records in multiple database tables.

In addition, the bean provider must take into consideration the following factors when making a decision on the granularity of an entity object:

  • Every method call to an entity object via the remote and home interface is potentially a remote call. Even if the calling and called entity beans are collocated in the same Java virtual machine, the call must go through the container, which must create copies of all the parameters that are passed through the interface by value (i.e., all parameters that do not extend the java.rmi.Remote interface). The container is also required to check security and apply the declarative transaction attribute on the inter-component calls. The over-head of an inter-component call will likely be prohibitive for object interactions that are too fine-grained.

  • The EJB deployment descriptor does not provide a mechanism for describing object schemas (the relationships among the fine-grained objects, and how fine-grained objects are mapped to the underlying database). If these relationships need to be visible at deployment time, the information describing the relationships must be passed from the bean provider to the deployer through some means outside of the EJB specification.

EJB.9.1.3 Entity Persistence (Data Access Protocol)

An entity bean implements an object view of an entity stored in an underlying database, or an entity implemented by an existing enterprise application (for example, by a mainframe program or by an ERP application). The data access protocol for transferring the state of the entity between the entity bean instances and the underlying database is referred to as object persistence .

The entity bean component protocol allows the entity bean provider either to implement the entity bean's persistence directly in the entity bean class or in one or more helper classes provided with the entity bean class (bean-managed persistence), or to delegate the entity bean's persistence to the container provider tools used at deployment time (container-managed persistence).

In many cases, the underlying data source may be an existing application rather than a database. (See Figure EJB.9-2.)

Figure EJB.9-2. Client View of Underlying Data Sources Accessed Through Entity Bean

EJB.9.1.3.1 Bean-Managed Persistence

In the bean-managed persistence case, the entity bean provider writes database access calls (e.g., using JDBC API technology or SQLJ) directly in the entity bean component. The data access calls are performed in the ejbCreate(...) , ejbRemove() , ejbFind<METHOD> (), ejbLoad() , and ejbStore() methods and/or in the business methods .

The data access calls can be coded directly into the entity bean class, or they can be encapsulated in a data access component that is part of the entity bean.

We expect that most enterprise beans will be created by application development tools which will encapsulate data access in components. These data access components will probably not be the same for all tools. This EJB specification does not define the architecture for data access objects or strategies.

Directly coding data access calls in the entity bean class may make it more difficult to adapt the entity bean to work with a database that has a different schema, or with a different type of database.

If the data access calls are encapsulated in data access components, the data access components may optionally provide deployment interfaces to allow adapting data access to different schemas or even to a different database type. These data access component strategies are beyond the scope of the EJB specification.

EJB.9.1.3.2 Container-Managed Persistence

In the container-managed persistence case, the bean provider does not write the database access calls in the entity bean. Instead, the container provider's tools generate the database access calls at the entity bean's deployment time (i.e., when the entity bean is installed into a container). The entity bean provider must specify in the deployment descriptor the list of the instance fields for which the container provider tools must generate access calls.

The advantage of using container-managed persistence is that the entity bean can be largely independent from the data source in which the entity is stored. The container tools can generate classes that use JDBC API or SQLJ to access the entity state in a relational database, or classes that implement access to a non-relational data source, such as an IMS database, or classes that implement function calls to existing enterprise applications.

The disadvantage is that sophisticated tools must be used at deployment time to map the entity bean's fields to a data source. These tools and containers are typically specific to each data source.

The essential difference between an entity with bean-managed persistence and one with container-managed persistence is that in the bean-managed case, the data access components are provided as part of the entity bean, whereas in the container-managed case, the data access components are generated at deployment time by the container tools.

EJB.9.1.4 Instance Life Cycle

An entity bean instance is in one of the following three states:

  • It does not exist.

  • Pooled state. An instance in the pooled state is not associated with any particular entity object identity.

  • Ready state. An instance in the ready state is assigned an entity object identity. (See Figure EJB.9-3.)

    Figure EJB.9-3. Life Cycle of an Entity Bean Instance

The following steps describe the life cycle of an entity bean instance:

  • An entity bean instance's life starts when the container creates the instance using newInstance() . The container then invokes the setEntityContext() method to pass the instance a reference to the EntityContext interface. The EntityContext interface allows the instance to invoke services provided by the container and to obtain the information about the caller of a client-invoked method.

  • The instance enters the pool of available instances. Each entity bean has its own pool. While the instance is in the available pool, the instance is not associated with any particular entity object identity. All instances in the pool are considered equivalent, and therefore any instance can be assigned by the container to any entity object identity at the transition to the ready state. While the instance is in the pooled state, the container may use the instance to execute any of the entity bean's finder methods (shown as ejbFind<METHOD>(...) in the diagram). The instance does not move to the ready state during the execution of a finder method.

  • An instance transitions from the pooled state to the ready state when the container selects that instance to service a client call to an entity object. There are two possible transitions from the pooled to the ready state: through the ejbCreate(...) and ejbPostCreate(...) methods, or through the ejbActivate() method. The container invokes the ejbCreate(...) and ejbPostCreate(...) methods when the instance is assigned to an entity object during entity object creation (i.e., when the client invokes a create method on the entity bean's home object). The container invokes the ejbActivate() method on an instance when an instance needs to be activated to service an invocation on an existing entity object ”this occurs because there is no suitable instance in the ready state to service the client's call.

  • When an entity bean instance is in the ready state, the instance is associated with a specific entity object identity. While the instance is in the ready state, the container can invoke the ejbLoad() and ejbStore() methods zero or more times. A business method can be invoked on the instance zero or more times. Invocations of the ejbLoad() and ejbStore() methods can be arbitrarily mixed with invocations of business methods. The purpose of the ejbLoad and ejbStore methods is to synchronize the state of the instance with the state of the entity in the underlying data source ”the container can invoke these methods whenever it determines a need to synchronize the instance's state.

  • The container can choose to passivate an entity bean instance within a transaction. To passivate an instance, the container first invokes the ejbStore method to allow the instance to synchronize the database state with the instance's state, and then the container invokes the ejbPassivate method to return the instance to the pooled state.

  • Eventually, the container will transition the instance to the pooled state. There are two possible transitions from the ready to the pooled state: through the ejbPassivate() method and through the ejbRemove() method. The container invokes the ejbPassivate() method when the container wants to disassociate the instance from the entity object identity without removing the entity object. The container invokes the ejbRemove() method when the container is removing the entity object (i.e., when the client invoked the remove() method on the entity object's remote interface, or one of the remove() methods on the entity bean's home interface).

  • When the instance is put back into the pool, it is no longer associated with an entity object identity. The container can assign the instance to any entity object within the same entity bean home.

  • An instance in the pool can be removed by calling the unsetEntityContext() method on the instance.

Notes:
  1. The EntityContext interface passed by the container to the instance in the setEntityContext method is an interface, not a class that contains static information. For example, the result of the EntityContext.getPrimaryKey() method might be different each time an instance moves from the pooled state to the ready state, and the result of the getCallerPrincipal() and isCallerInRole(...) methods may be different in each business method.

  2. A RuntimeException thrown from any method of the entity bean class (including the business methods and the callbacks invoked by the container) results in the transition to the "does not exist" state. The container must not invoke any method on the instance after a RuntimeException has been caught. From the client perspective, the corresponding entity object continues to exist. The client can continue accessing the entity object through its remote interface because the container can use a different entity bean instance to delegate the client's requests . Exception handling is described further in Chapter EJB.12.

  3. The container is not required to maintain a pool of instances in the pooled state. The pooling approach is an example of a possible implementation, but it is not the required implementation. Whether the container uses a pool or not has no bearing on the entity bean coding style.

EJB.9.1.5 The Entity Bean Component Contract

This section specifies the contract between an entity bean and its container. The contract specified here assumes the use of bean-managed persistence. The differences in the contract for container-managed persistence are defined in Section EJB.9.4.

EJB.9.1.5.1 Entity Bean Instance's View

The following describes the entity bean instance's view of the contract: The entity bean provider is responsible for implementing the following methods in the entity bean class:

  • A public constructor that takes no arguments. The container uses this constructor to create instances of the entity bean class.

  • public void setEntityContext(EntityContext ic);

    A container uses this method to pass a reference to the EntityContext interface to the entity bean instance. If the entity bean instance needs to use the EntityContext interface during its lifetime, it must remember the EntityContext interface in an instance variable.

    This method executes with an unspecified transaction context (refer to Section EJB.11.6.3 for how the container executes methods with an unspecified transaction context). An identity of an entity object is not available during this method.

    The instance can take advantage of the setEntityContext() method to allocate any resources that are to be held by the instance for its lifetime. Such resources cannot be specific to an entity object identity because the instance might be reused during its lifetime to serve multiple entity object identities.

  • public void unsetEntityContext();

    A container invokes this method before terminating the life of the instance.

    This method executes with an unspecified transaction context. An identity of an entity object is not available during this method.

    The instance can take advantage of the unsetEntityContext() method to free any resources that are held by the instance. (These resources typically had been allocated by the setEntityContext() method.)

  • public PrimaryKeyClass ejbCreate(...);

    There are zero [1] or more ejbCreate(...) methods, whose signatures match the signatures of the create(...) methods of the entity bean home interface. The container invokes an ejbCreate(...) method on an entity bean instance when a client invokes a matching create(...) method to create an entity object.

    [1] An entity enterprise bean has no ejbCreate(...) and ejbPostCreate(...) methods if it does not define any create methods in its home interface. Such an entity enterprise bean does not allow the clients to create new EJB objects. The enterprise bean restricts the clients to accessing entities that were created through direct database inserts .

    The implementation of the ejbCreate(...) method typically validates the client-supplied arguments, and inserts a record representing the entity object into the database. The method also initializes the instance's variables . The ejbCreate(...) method must return the primary key for the created entity object.

    An ejbCreate(...) method executes in the transaction context determined by the transaction attribute of the matching create(...) method, as described in Section EJB.11.6.2.

  • public void ejbPostCreate(...);

    For each ejbCreate(...) method, there is a matching ejbPostCreate(...) method that has the same input parameters but the return value is void . The container invokes the matching ejbPostCreate(...) method on an instance after it invokes the ejbCreate(...) method with the same arguments. The entity object identity is available during the ejbPostCreate(...) method. The instance may, for example, obtain the remote interface of the associated entity object and pass it to another enterprise bean as a method argument.

    An ejbPostCreate(...) method executes in the same transaction context as the previous ejbCreate(...) method.

  • public void ejbActivate();

    The container invokes this method on the instance when the container picks the instance from the pool and assigns it to a specific entity object identity. The ejbActivate() method gives the entity bean instance the chance to acquire additional resources that it needs while it is in the ready state.

    This method executes with an unspecified transaction context. The instance can obtain the identity of the entity object via the getPrimaryKey() or getEJBObject() method on the entity context. The instance can rely on the fact that the primary key and entity object identity will remain associated with the instance until the completion of ejbPassivate() or ejbRemove() .

    Note that the instance should not use the ejbActivate() method to read the state of the entity from the database; the instance should load its state only in the ejbLoad() method.

  • public void ejbPassivate();

    The container invokes this method on an instance when the container decides to disassociate the instance from an entity object identity, and to put the instance back into the pool of available instances. The ejbPassivate() method gives the instance the chance to release any resources that should not be held while the instance is in the pool. (These resources typically had been allocated during the ejbActivate() method.)

    This method executes with an unspecified transaction context. The instance can still obtain the identity of the entity object via the getPrimaryKey() or getEJBObject() method of the EntityContext interface.

    Note that an instance should not use the ejbPassivate() method to write its state to the database; an instance should store its state only in the ejbStore() method.

  • public void ejbRemove();

    The container invokes this method on an instance as a result of a client's invoking a remove method. The instance is in the ready state when ejbRemove() is invoked and it will be entered into the pool when the method completes.

    This method executes in the transaction context determined by the transaction attribute of the remove method that triggered the ejbRemove method. The instance can still obtain the identity of the entity object via the getPrimaryKey() or getEJBObject() method of the EntityContext interface.

    The container synchronizes the instance's state before it invokes the ejbRemove method. This means that the state of the instance variables at the beginning of the ejbRemove method is the same as it would be at the beginning of a business method.

    An entity bean instance should use this method to remove the entity object's representation in the database.

    Since the instance will be entered into the pool, the state of the instance at the end of this method must be equivalent to the state of a passivated instance. This means that the instance must release any resource that it would normally release in the ejbPassivate() method.

  • public void ejbLoad();

    The container invokes this method on an instance in the ready state to inform the instance that it must synchronize the entity state cached in its instance variables from the entity state in the database. The instance must be prepared for the container to invoke this method at any time that the instance is in the ready state.

    If the instance is caching the entity state (or parts of the entity state), the instance must not use the previously cached state in the subsequent business method. The instance may take advantage of the ejbLoad method, for example, to refresh the cached state by reading it from the database.

    This method executes in the transaction context determined by the transaction attribute of the business method that triggered the ejbLoad method.

  • public void ejbStore();

    The container invokes this method on an instance to inform the instance that the instance must synchronize the entity state in the database with the entity state cached in its instance variables. The instance must be prepared for the container to invoke this method at any time that the instance is in the ready state.

    An instance must write any updates cached in the instance variables to the database in the ejbStore() method.

    This method executes in the same transaction context as the previous ejbLoad or ejbCreate method invoked on the instance. All business methods invoked between the previous ejbLoad or ejbCreate method and this ejbStore method are also invoked in the same transaction context.

  • public PrimaryKeyClass or collection ejbFind<METHOD>(...);

    The container invokes this method on the instance when the container selects the instance to execute a matching client-invoked find<METHOD>(...) method. The instance is in the pooled state (i.e., it is not assigned to any particular entity object identity) when the container selects the instance to execute the ejbFind<METHOD> method on it, and it is returned to the pooled state when the execution of the ejbFind<METHOD> method completes.

    The ejbFind<METHOD> method executes in the transaction context determined by the transaction attribute of the matching find(...) method, as described in Section EJB.11.6.2.

    The implementation of an ejbFind<METHOD> method typically uses the method's arguments to locate the requested entity object or a collection of entity objects in the database. The method must return a primary key or a collection of primary keys to the container (see Section EJB.9.1.8).

EJB.9.1.5.2 Container's View

This subsection describes the container's view of the state management contract. The container must call the following methods:

  • public void setEntityContext(ec);

    The container invokes this method to pass a reference to the EntityContext interface to the entity bean instance. The container must invoke this method after it creates the instance, and before it puts the instance into the pool of available instances.

    The container invokes this method with an unspecified transaction context. At this point, the EntityContext is not associated with any entity object identity.

  • public void unsetEntityContext();

    The container invokes this method when the container wants to reduce the number of instances in the pool. After this method completes, the container must not reuse this instance.

    The container invokes this method with an unspecified transaction context.

  • public PrimaryKeyClass ejbCreate(...);

    public void ejbPostCreate(...);

    The container invokes these two methods during the creation of an entity object as a result of a client invoking a create(...) method on the entity bean's home interface.

    The container first invokes the ejbCreate(...) method whose signature matches the create(...) method invoked by the client. The ejbCreate(...) method returns a primary key for the created entity object. The container creates an entity EJBObject reference for the primary key. The container then invokes a matching ejbPostCreate(...) method to allow the instance to fully initialize itself. Finally, the container returns the entity object's remote interface (i.e., a reference to the entity EJBObject ) to the client.

    The container must invoke the ejbCreate(...) and ejbPostCreate(...) methods in the transaction context determined by the transaction attribute of the matching create(...) method, as described in Section EJB.11.6.2.

  • public void ejbActivate();

    The container invokes this method on an entity bean instance at activation time (i.e., when the instance is taken from the pool and assigned to an entity object identity). The container must ensure that the primary key of the associated entity object is available to the instance if the instance invokes the getPrimaryKey() or getEJBObject() method on its EntityContext interface.

    The container invokes this method with an unspecified transaction context.

    Note that instance is not yet ready for the delivery of a business method. The container must still invoke the ejbLoad() method prior to a business method.

  • public void ejbPassivate();

    The container invokes this method on an entity bean instance at passivation time (i.e., when the instance is being disassociated from an entity object identity and moved into the pool). The container must ensure that the identity of the associated entity object is still available to the instance if the instance invokes the getPrimaryKey() or getEJBObject() method on its entity context.

    The container invokes this method with an unspecified transaction context.

    Note that if the instance state has been updated by a transaction, the container must first invoke the ejbStore() method on the instance before it invokes ejbPassivate() on it.

  • public void ejbRemove();

    The container invokes this method before it ends the life of an entity object as a result of a client invoking a remove operation.

    The container invokes this method in the transaction context determined by the transaction attribute of the invoked remove method.

    The container must ensure that the identity of the associated entity object is still available to the instance in the ejbRemove() method (i.e., the instance can invoke the getPrimaryKey() or getEJBObject() method on its EntityContext in the ejbRemove() method).

    The container must ensure that the instance's state is synchronized from the state in the database before invoking the ejbRemove() method (i.e., if the instance is not already synchronized from the state in the database, the container must invoke ejbLoad before it invokes ejbRemove ).

  • public void ejbLoad();

    The container must invoke this method on the instance whenever it becomes necessary for the instance to synchronize its instance state from its state in the database. The exact times that the container invokes ejbLoad depend on the configuration of the component and the container, and are not defined by the EJB architecture. Typically, the container will call ejbLoad before the first business method within a transaction to ensure that the instance can refresh its cached state of the entity object from the database. After the first ejbLoad within a transaction, the container is not required to recognize that the state of the entity object in the database has been changed by another transaction, and it is not required to notify the instance of this change via another ejbLoad call.

    The container must invoke this method in the transaction context determined by the transaction attribute of the business method that triggered the ejbLoad method.

  • public void ejbStore();

    The container must invoke this method on the instance whenever it becomes necessary for the instance to synchronize its state in the database with the state of the instance's fields. This synchronization always happens at the end of a transaction. However, the container may also invoke this method when it passivates the instance in the middle of a transaction, or when it needs to transfer the most recent state of the entity object to another instance for the same entity object in the same transaction (see Section EJB.11.7).

    The container must invoke this method in the same transaction context as the previously invoked ejbLoad or ejbCreate method.

  • public primary key type or collection ejbFind<METHOD>(...);

    The container invokes the ejbFind<METHOD>(...) method on an instance when a client invokes a matching find<METHOD>(...) method on the entity bean's home interface. The container must pick an instance that is in the pooled state (i.e., the instance is not associated with any entity object identity) for the execution of the ejbFind<METHOD>(...) method. If there is no instance in the pooled state, the container creates one and calls the setEntityContext(...) method on the instance before dispatching the finder method.

    After the ejbFind<METHOD>(...) method completes, the instance remains in the pooled state. The container may, but is not required to, activate the objects that were located by the finder using the transition through the ejbActivate() method.

    The container must invoke the ejbFind<METHOD>(...) method in the transaction context determined by the transaction attribute of the matching find(...) method, as described in Section EJB.11.6.2.

    If the ejbFind<METHOD> method is declared to return a single primary key, the container creates an entity EJBObject reference for the primary key and returns it to the client. If the ejbFind<METHOD> method is declared to return a collection of primary keys, the container creates a collection of entity EJBObject references for the primary keys returned from ejbFind<METHOD> , and returns the collection to the client. (See Section EJB.9.1.8 for information on collections.)

EJB.9.1.6 Operations Allowed in the Methods of the Entity Bean Class

Table EJB.9-1 defines the methods of an entity bean class in which the enterprise bean instances can access the methods of the javax.ejb.EntityContext interface, the java:comp/env environment naming context, resource managers, and other enterprise beans.

If an entity bean instance attempts to invoke a method of the EntityContext interface, and the access is not allowed in Table EJB.9-1, the container must throw the java.lang.IllegalStateException.

If an entity bean instance attempts to access a resource manager or an enterprise bean, and the access is not allowed in Table EJB.9-1, the behavior is undefined by the EJB architecture.

Table EJB.9-1. Operations Allowed in the Methods of an Entity Bean

Bean Method

Bean Method Can Perform the Following Operations

constructor

setEntityContext

unsetEntityContext

EntityContext methods: getEJBHome

JNDI access to java:comp/env

ejbCreate

EntityContext methods: getEJBHome, getCallerPrincipal, getRollbackOnly, isCallerInRole, setRollbackOnly

JNDI access to java:comp/env

Resource manager access

Enterprise bean access

ejbPostCreate

EntityContext methods: getEJBHome, getCallerPrincipal, getRollbackOnly, isCallerInRole, setRollbackOnly, getEJBObject, getPrimaryKey

JNDI access to java:comp/env

Resource manager access

Enterprise bean access

ejbRemove

EntityContext methods: getEJBHome, getCallerPrincipal, getRollbackOnly, isCallerInRole, setRollbackOnly, getEJBObject, getPrimaryKey

JNDI access to java:comp/env

Resource manager access

Enterprise bean access

ejbFind

EntityContext methods: getEJBHome, getCallerPrincipal, getRollbackOnly, isCallerInRole, setRollbackOnly

JNDI access to java:comp/env

Resource manager access

Enterprise bean access

ejbActivate

ejbPassivate

EntityContext methods: getEJBHome, getEJBObject, getPrimaryKey

JNDI access to java:comp/env

ejbLoad

ejbStore

EntityContext methods: getEJBHome, getCallerPrincipal, getRollbackOnly, isCallerInRole, setRollbackOnly, getEJBObject, getPrimaryKey

JNDI access to java:comp/env

Resource manager access

Enterprise bean access

business method from remote interface

EntityContext methods: getEJBHome, getCallerPrincipal, getRollbackOnly, isCallerInRole, setRollbackOnly, getEJBObject, getPrimaryKey

JNDI access to java:comp/env

Resource manager access

Enterprise bean access

Additional restrictions:

  • The getRollbackOnly and setRollbackOnly methods of the EntityContext interface should be used only in the enterprise bean methods that execute in the context of a transaction. The container must throw the java.lang.IllegalStateException if the methods are invoked while the instance is not associated with a transaction.

Reasons for disallowing operations:

  • Invoking the getEJBObject and getPrimaryKey methods is disallowed in the entity bean methods in which there is no entity object identity associated with the instance.

  • Invoking the getCallerPrincipal and isCallerInRole methods is disallowed in the entity bean methods for which the container does not have a client security context.

  • Invoking the getRollbackOnly and setRollbackOnly methods is disallowed in the entity bean methods for which the container does not have a meaningful transaction context. These are the methods that have the NotSupported , Never , or Supports transaction attribute.

  • Accessing resource managers and enterprise beans is disallowed in the entity bean methods for which the container does not have a meaningful transaction context or client security context.

EJB.9.1.7 Caching of Entity State and the ejbLoad and ejbStore Methods

An instance of an entity bean with bean-managed persistence can cache the entity object's state between business method invocations. An instance may choose to cache the entire entity object's state, part of the state, or no state at all.

The container-invoked ejbLoad and ejbStore methods assist the instance with the management of the cached entity object's state. The instance must handle the ejbLoad and ejbStore methods as follows:

  • When the container invokes the ejbStore method on the instance, the instance must push all cached updates of the entity object's state to the underlying database. The container invokes the ejbStore method at the end of a transaction, and may also invoke it at other times when the instance is in the ready state. (For example, the container may invoke ejbStore when passivating an instance in the middle of a transaction, or when transferring the instance's state to another instance to support distributed transactions in a multi-process server.)

  • When the container invokes the ejbLoad method on the instance, the instance must discard any cached entity object's state. The instance may, but is not required to, refresh the cached state by reloading it from the underlying database.

The following examples, which are illustrative but not prescriptive, show how an instance may cache the entity object's state:

  • An instance loads the entire entity object's state in the ejbLoad method and caches it until the container invokes the ejbStore method. The business methods read and write the cached entity state. The ejbStore method writes the updated parts of the entity object's state to the database.

  • An instance loads the most frequently used part of the entity object's state in the ejbLoad method and caches it until the container invokes the ejbStore method. Additional parts of the entity object's state are loaded as needed by the business methods. The ejbStore method writes the updated parts of the entity object's state to the database.

  • An instance does not cache any entity object's state between business methods. The business methods access and modify the entity object's state directly in the database. The ejbLoad and ejbStore methods have an empty implementation.

We expect that most entity developers will not manually code the cache management and data access calls in the entity bean class. We expect that they will rely on application development tools to provide various data access components that encapsulate data access and provide state caching.

EJB.9.1.7.1 ejbLoad and ejbStore with the NotSupported Transaction Attribute

The use of the ejbLoad and ejbStore methods for caching an entity object's state in the instance works well only if the container can use transaction boundaries to drive the ejbLoad and ejbStore methods. When the NotSupported [2] transaction attribute is assigned to a remote interface method, the corresponding enterprise bean class method executes with an unspecified transaction context (see Section EJB.11.6.3). This means that the container does not have any well-defined transaction boundaries to drive the ejbLoad and ejbStore methods on the instance.

[2] This applies also to the Never and Supports attributes.

Therefore, the ejbLoad and ejbStore methods are "unreliable" for the instances that the container uses to dispatch the methods with an unspecified transaction context. The following are the only guarantees that the container provides for the instances that execute the methods with an unspecified transaction context:

  • The container invokes at least one ejbLoad between ejbActivate and the first business method in the instance.

  • The container invokes at least one ejbStore between the last business method on the instance and the ejbPassivate method.

Because the entity object's state accessed between the ejbLoad and ejbStore method pair is not protected by a transaction boundary for the methods that execute with an unspecified transaction context, the bean provider should not attempt to use the ejbLoad and ejbStore methods to control caching of the entity object's state in the instance. Typically, the implementation of the ejbLoad and ejbStore methods should be a no-op (i.e., an empty method), and each business method should access the entity object's state directly in the database.

EJB.9.1.8 Finder Method Return Type

EJB.9.1.8.1 Single-Object Finder

Some finder methods (such as ejbFindByPrimaryKey ) are designed to return at most one entity object. For these single-object finders , the result type of the find<METHOD>(...) method defined in the entity bean's home interface is the entity bean's remote interface. The result type of the corresponding ejbFind<METHOD>(...) method defined in the entity's implementation class is the entity bean's primary key type.

The following code illustrates the definition of a single-object finder.

 // Entity's home interface  public AccountHome extends javax.ejb.EJBHome {    ...     Account findByPrimaryKey(AccountPrimaryKey primkey)        throws FinderException, RemoteException;     ...  }  // Entity's implementation class  public AccountBean implements javax.ejb.EntityBean {    ...     public AccountPrimaryKey ejbFindByPrimaryKey(             AccountPrimaryKey primkey)        throws FinderException     {       ...     }     ...  } 
EJB.9.1.8.2 Multi-Object Finders

Some finder methods are designed to return multiple entity objects. For these multi-object finders, the result type of the find<METHOD>(...) method defined in the entity bean's home interface is a collection of objects implementing the entity bean's remote interface. The result type of the corresponding ejbFind<METHOD>(...) implementation method defined in the entity bean's implementation class is a collection of objects of the entity bean's primary key type.

The bean provider can choose two types to define a collection type for a finder:

  • The JDK 1.1 java.util.Enumeration interface

  • The Java 2 java.util.Collection interface

A bean provider that wants to ensure that the entity bean is compatible with containers and clients based on JDK 1.1 software must use the java.util.Enumeration interface for the finder's result type. [3]

[3] The finder will be also compatible with Java 2 platform-based containers and clients.

A bean provider targeting only containers and clients based on the Java 2 platform can use the java.util.Collection interface for the finder's result type.

The bean provider must ensure that the objects in the java.util.Enumeration or java.util.Collection returned from the ejbFind<METHOD>(...) method are instances of the entity bean's primary key class.

The following is an example of a multi-object finder method definition compatible with containers and clients that are based on both JDK 1.1 and the Java 2 platform:

 // Entity's home interface  public AccountHome extends javax.ejb.EJBHome {    ...     java.util.Enumeration findLargeAccounts(double limit)         throws FinderException, RemoteException;     ...  }  // Entity's implementation class  public AccountBean implements javax.ejb.EntityBean {    ...     public java.util.Enumeration ejbFindLargeAccounts(           double limit) throws FinderException     {       ...     }     ...  } 

The following is an example of a multi-object finder method definition that is compatible only with containers and clients based on Java 2:

 // Entity's home interface  public AccountHome extends javax.ejb.EJBHome {    ...     java.util.Collection findLargeAccounts(double limit)        throws FinderException, RemoteException;     ...  }  // Entity's implementation class  public AccountBean implements javax.ejb.EntityBean {    ...     public java.util.Collection ejbFindLargeAccounts(           double limit) throws FinderException     {       ...     }     ...  } 

EJB.9.1.9 Standard Application Exceptions for Entities

The EJB specification defines the following standard application exceptions:

  • javax.ejb.CreateException

  • javax.ejb.DuplicateKeyException

  • javax.ejb.FinderException

  • javax.ejb.ObjectNotFoundException

  • javax.ejb.RemoveException

This section describes the use of these exceptions by entity beans with bean-managed persistence. The use of the exceptions by entity beans with container-managed persistence is the same, with one additional element: The responsibilities for throwing the exceptions apply to the data access methods generated by the container provider's tools.

EJB.9.1.9.1 CreateException

From the client's perspective, a CreateException (or a subclass of CreateException ) indicates that an application level error occurred during the create(... ) operation. If a client receives this exception, the client does not know, in general, whether the entity object was created but not fully initialized , or not created at all. Also, the client does not know whether or not the transaction has been marked for rollback. (However, the client may determine the transaction status using the UserTransaction interface.)

The bean provider throws the CreateException (or subclass of CreateException ) from the ejbCreate(...) and ejbPostCreate(...) methods to indicate an application-level error from the create or initialization operation. Optionally, the bean provider may mark the transaction for rollback before throwing this exception.

The bean provider is encouraged to mark the transaction for rollback only if data integrity would be lost if the transaction were committed by the client. Typically, when a CreateException is thrown, it leaves the database in a consistent state, allowing the client to recover. For example, ejbCreate may throw the CreateException to indicate that the some of the arguments to the create(...) methods are invalid.

The container treats the CreateException as any other application exception. See Section EJB.12.3.

EJB.9.1.9.2 DuplicateKeyException

The DuplicateKeyException is a subclass of CreateException . It is thrown by the ejbCreate(...) methods to indicate to the client that the entity object cannot be created because an entity object with the same key already exists. The unique key causing the violation may be the primary key, or another key defined in the underlying database.

Normally, the bean provider should not mark the transaction for rollback before throwing the exception.

When the client receives the DuplicateKeyException , the client knows that the entity was not created, and that the client's transaction has not typically been marked for rollback.

EJB.9.1.9.3 FinderException

From the client's perspective, a FinderException (or a subclass of FinderException ) indicates that an application level error occurred during the find(... ) operation. Typically, the client's transaction has not been marked for rollback because of the FinderException .

The bean provider throws the FinderException (or subclass of FinderException ) from the ejbFind<METHOD>(...) methods to indicate an application-level error in the finder method. The bean provider should not, typically, mark the transaction for rollback before throwing the FinderException .

The container treats the FinderException as any other application exception. See Section EJB.12.3.

EJB.9.1.9.4 ObjectNotFoundException

The ObjectNotFoundException is a subclass of FinderException . It is thrown by the ejbFind<METHOD>(...) methods to indicate that the requested entity object does not exist.

Only single-object finders (see Section EJB.9.1.8) should throw this exception. Multi-object finders must not throw this exception. Multi-object finders should return an empty collection as an indication that no matching objects were found.

EJB.9.1.9.5 RemoveException

From the client's perspective, a RemoveException (or a subclass of RemoveException ) indicates that an application level error occurred during a remove(... ) operation. If a client receives this exception, the client does not know, in general, whether the entity object was removed or not. The client also does not know if the transaction has been marked for rollback. (However, the client may determine the transaction status using the UserTransaction interface.)

The bean provider throws the RemoveException (or subclass of RemoveException ) from the ejbRemove() method to indicate an application-level error from the entity object removal operation. Optionally, the bean provider may mark the transaction for rollback before throwing this exception.

The bean provider is encouraged to mark the transaction for rollback only if data integrity would be lost if the transaction were committed by the client. Typically, when a RemoveException is thrown, it leaves the database in a consistent state, allowing the client to recover.

The container treats the RemoveException as any other application exception. See Section EJB.12.3.

EJB.9.1.10 Commit Options

The entity bean protocol is designed to give the container the flexibility to select the disposition of the instance state at transaction commit time. This flexibility allows the container to optimally manage the caching of an entity object's state and the association of an entity object identity with the enterprise bean instances.

The container can select from the following commit-time options:

  • Option A: The container caches a "ready" instance between transactions. The container ensures that the instance has exclusive access to the state of the object in the persistent storage. Therefore, the container does not have to synchronize the instance's state from the persistent storage at the beginning of the next transaction.

  • Option B: The container caches a "ready" instance between transactions. In contrast to Option A, in this option the container does not ensure that the instance has exclusive access to the state of the object in the persistent storage. Therefore, the container must synchronize the instance's state from the persistent storage at the beginning of the next transaction.

  • Option C: The container does not cache a "ready" instance between transactions. The container returns the instance to the pool of available instances after a transaction has completed.

Table EJB.9-2 provides a summary of the commit-time options.

Table EJB.9-2. Summary of Commit-Time Options
 

Write Instance State to Database

Instance Stays Ready

Instance State Remains Valid

Option A

Yes

Yes

Yes

Option B

Yes

Yes

No

Option C

Yes

No

No

Note that the container synchronizes the instance's state with the persistent storage at transaction commit for all three options.

The selection of the commit option is transparent to the entity bean implementation ”the entity bean will work correctly regardless of the commit-time option chosen by the container. The bean provider writes the entity bean in the same way.

The object interaction diagrams in Section EJB.9.5.4 illustrate the three alternative commit options in detail.

EJB.9.1.11 Concurrent Access from Multiple Transactions

When writing the entity bean business methods, the bean provider does not have to worry about concurrent access from multiple transactions. The bean provider may assume that the container will ensure appropriate synchronization for entity objects that are accessed concurrently from multiple transactions.

The container typically uses one of the following implementation strategies to achieve proper synchronization. (These strategies are illustrative, not prescriptive.)

  • The container activates multiple instances of the entity bean, one for each transaction in which the entity object is being accessed (Figure EJB.9-4). The transaction synchronization is performed automatically by the underlying database during the database access calls performed by the business methods; and by the ejbLoad , ejbCreate , ejbStore , and ejbRemove methods. The database system provides all the necessary transaction synchronization; the container does not have to perform any synchronization logic. The commit-time options B and C in Section EJB.9.5.4 apply to this type of container.

    Figure EJB.9-4. Multiple Clients Can Access the Same Entity Object Using Multiple Instances

With this strategy, the type of lock acquired by ejbLoad leads to a trade-off. If ejbLoad acquires an exclusive lock on the instance's state in the database, then throughput of read-only transactions could be impacted. If ejbLoad acquires a shared lock and the instance is updated, then ejbStore will need to promote the lock to an exclusive lock. This may cause a deadlock if it happens concurrently under multiple transactions.

  • The container acquires exclusive access to the entity object's state in the database. The container activates a single instance (Figure EJB.9-5) and serializes the access from multiple transactions to this instance. The commit-time option A in Section EJB.9.5.4 applies to this type of container.

    Figure EJB.9-5. Multiple Clients Can Access the Same Entity Object Using a Single Instance

EJB.9.1.12 Non-Reentrant and Reentrant Instances

An entity bean provider entity can specify that an entity bean is non-reentrant. If an instance of a non-reentrant entity bean executes a client request in a given transaction context, and another request with the same transaction context arrives for the same entity object, the container will throw the java.rmi.RemoteException to the second request. This rule allows the bean provider to program the entity bean as single-threaded, non-reentrant code.

The functionality of some entity beans may require loopbacks in the same transaction context. An example of a loopback is when the client calls entity object A, A calls entity object B, and B calls back A in the same transaction context. The entity bean's method invoked by the loopback shares the current execution context (which includes the transaction and security contexts) with the bean's method invoked by the client.

If the entity bean is specified as non-reentrant in the deployment descriptor, the container must reject an attempt to reenter the instance via the entity bean's remote interface while the instance is executing a business method. (This can happen, for example, if the instance has invoked another enterprise bean, and the other enterprise bean tries to make a loopback call.) The container must reject the loopback call and throw the java.rmi.RemoteException to the caller. The container must allow the call if the bean's deployment descriptor specifies that the entity bean is reentrant.

Reentrant entity beans must be programmed and used with great caution. First, the bean provider must code the entity bean with the anticipation of a loopback call. Second, since the container cannot, in general, tell a loopback from a concurrent call from a different client, the client programmer must be careful to avoid code that could lead to a concurrent call in the same transaction context.

Concurrent calls in the same transaction context targeted at the same entity object are illegal and may lead to unpredictable results. Since the container cannot, in general, distinguish between an illegal concurrent call and a legal loopback, application programmers are encouraged to avoid using loopbacks. Entity beans that do not need callbacks should be marked as non-reentrant in the deployment descriptor, allowing the container to detect and prevent illegal concurrent calls from clients.



Java 2 Platform, Enterprise Edition. Platform and Component Specifications
Java 2 Platform, Enterprise Edition: Platform and Component Specifications
ISBN: 0201704560
EAN: 2147483647
Year: 2000
Pages: 399

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net