Container Managed Persistence 2.02.1


Container Managed Persistence 2.0/2.1

Overview

Figure 5-7 provides a sweeping overview of the classes and interfaces of an entity bean with container-managed persistence since version 2.0, which supports the remote client view. On the right is the entity bean class, whose objects are managed by the EJB container at run time. On the left are the interfaces over which the client accesses the bean and that are implemented via the home or remote object of the EJB container.

click to expand
Figure 5-7: Remote interfaces and classes of the CMP entity bean (EJB 2.0).

In the figure all symbolic names that must be replaced during actual programming by the proper terms appear in pointy brackets (<abc>). A plus sign (+) denotes a public method. Abstract methods are written in a slant font.

The entity bean class implements the interface javax.ejb.EntityBean. In this entity bean class the bean provider implements the actual functionality of the bean. For each persistent attribute two abstract access methods (get and set) are defined.

The get method is for reading the attribute. It possesses no parameters, and its return value has the data type of the persistent attribute.

The set method is for writing the attribute. It has one parameter with the data type of the persistent attribute and no return value. The EJB container takes over implementation of this method at deployment.

In the upper left part of Figure 5-7 is the class for the bean's primary key. Since objects of this class must be transported between server and client over the network, this class must be serializable. It implements the interface java.io.Serializable. In the primary key class are defined the attributes that form the primary key of the associated entity bean class. For each (virtual) persistent attribute of the bean a public attribute is defined. The data type is the same as for the return value of the get method. If the primary key consists of only a single attribute, then its data type can be used as primary key class. In this case no special primary key class needs to be implemented.

Figure 5-8 provides a sweeping overview of the classes and interfaces of an entity bean with container-managed persistence since version 2.0, which supports the local client view. On the right is the entity bean class, and on the left are the interfaces that are used by the client and are implemented by the local home object or local object of the EJB container. The entity bean class of the local client view is identical to that of the remote client view. The differences between the two cases are manifested by the EJB container through the implementation of the relevant interfaces. The bean class and bean instance remain untouched. For the client of an entity bean the differences between local and remote client views are the same as for session beans. These differences have been discussed already, in Chapter 4.

click to expand
Figure 5-8: Local interfaces and classes of the CMP entity bean (EJB 2.0).

The primary key class should implement java.io.Serializable in the case of the local and remote client views, since objects of this class may be used only inside or outside of a single Java process. Every entity bean is specified in the deployment descriptor (see Listing 5-1) (entity). Here a unique name for the entity bean is defined (ejb-name). Moreover, the home interface (home), the remote interface (remote), the bean class (ejb-class), and the primary key class (prim-key-class) are completely specified. In the element a distinction is made as to whether one is dealing with an entity bean with container-managed persistence (Container) or with bean-managed persistence (Bean). Furthermore, it must be specified that the entity bean is using the persistence mechanism of version 2.x of the EJB specification (cmp-version). Finally, a name for the entity bean's persistence schema must be given (abstract-schema-name). This name will be used later by the deployer for mapping the data of the entity bean to the current persistence medium. Moreover, this name plays an important role in EJB-QL.

Listing 5-1: Schematic deployment descriptor for an entity bean.

start example
 <?xml version="1.0" ?> <ejb-jar version="2.1" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">   <enterprise-beans>     <entity>        <ejb-name>name of the bean</ejb-name>        <home>home interface</home>        <remote>remote interface</remote>        <ejb-class>bean class</ejb-class>        <persistence-type>container orbean</persistence-type>        <prim-key-class>primary key class</prim-key-class>        <reentrant>True or False</reentrant>        <cmp-version>2.x</cmp-version>        <abstract-schema-name>            name of the persistence schema        </abstract-schema-name>        ...   </enterprise-beans>   ... </ejb-jar> 
end example

Like a session bean, an entity bean can be configured externally via the bean environment. The entries for the bean environment are made in the deployment descriptor. Working with the bean environment was dealt with in Chapter 4, on session beans, and we shall not repeat that material here.

The following sections present programming with the necessary definitions in the deployment descriptor for aspects of entity bean with container-managed persistence 2.0/2.1. To this topic belong the persistent attributes of an entity bean, state management of the EJB container, the generation and deletion of an entity bean, search methods (finder and select methods), and the methods of the application logic.

Attributes

The names of all persistent attributes for which abstract getter/setter methods have been defined are declared in the deployment descriptor. Each name must begin with a lowercase letter. This is how during installation the tools of the EJB container identify the abstract methods responsible for storing the attributes. The declaration takes place within the entity section and is represented schematically in Listing 5-2.

Listing 5-2: Definition of an attribute of an entity bean in the deployment descriptor.

start example
 ...     <entity>       ...       <cmp-field>          <description>description of the attribute1</description>          <field-name>attributeName 1(e.g., surname)</field-name>       </cmp-field>       <cmp-field>          <description>description of the attribute2</description>          <field-name> attributeName 2 (e.g., given name)</field-name>       </cmp-field>       ...     </entity> ... 
end example

For each persistent attribute abstract access or mutator methods (commonly known as getter/setter methods) are defined in the entity bean class. Their names begin with get (read access) and set (write access), followed by the name of the attribute with the beginning of each word an uppercase letter (Listing 5-3).

Listing 5-3: Access methods for an attribute of an entity bean.

start example
 ... public abstract void set<attributeName>(<type>) public abstract <type> get<attributeName>(); ... 
end example

A persistent attribute of an entity bean for which, for example, the abstract methods getMyAttribute and setMyAttribute were defined will be declared in the deployment descriptor of the entity bean under the element field-name with the value myAttribute.

The client does not have direct access to the getter/setter methods for reading and writing the persistent attributes of an entity bean. The entity bean must make available corresponding methods in the local or remote interface that permit indirectly the writing and reading of the persistent attributes, by delegating read and write access to the getter/setter methods. The attributes of the primary key may not be changed after the entity bean is generated, since that would jeopardize the integrity of the data.

State Management

At the top of Figures 5-7 and 5-8 are the methods for state management. In the case of container-managed persistence the EJB container calls these methods in order to inform the bean instance of state transitions. These include the methods for management of the context and for activation and passivation, which we already know about from our discussion of session beans. In addition, there are the methods ejbLoad and ejbStore, which belong to the persistence mechanism of the bean.

void setEntityContext(EntityContext ctx)

The method setEntiyContext is called by the EJB container when a bean instance is generated and changes into the state Pooled. It serves to initialize the bean. The EJB container gives the entity bean its context. This method should only save the context and not possess any business-logic-related functionality.

void unsetEntityContext()

This method is called by the EJB container when it no longer needs a bean instance and wishes to remove it from the pool. The call informs the bean instance that the associated context will be invalid.

void ejbActivate()

The EJB container calls this method to inform the entity bean instance that it has received a particular entity bean identity. The identity that it now possesses can be discovered using the entity context.

The bean instance changes into the state Ready-Async. In this state in the EntityContext the primary key can be queried with getPrimaryKey, and the remote and local interfaces with getEJBObject and getEJBLocalObject, respectively. However, the bean instance has not yet been synchronized with the database, and thus the values of the persistent attributes have not yet been set.

This method can be used to open a database connection or to reserve other resources. It is important to note that there are no transactions available to this method.

void ejbPassivate()

This method is the complement to ejbActivate. It is called by the EJB container when the bean instance is transformed from the state Ready to the state Pooled. Thereafter, the bean instance no longer possesses a bean identity. However, in this method the bean identity can still be used, since the state transition is not yet closed when this method is called.

This method is used to release resources that were reserved with ejbActivate or later in the state Ready.

void ejbLoad()

The method ejbLoad is called by the EJB container after the state of the bean instance has been synchronized with the database. This is necessary if the bean instance was not initialized or if the database contents have changed due to a parallel access. The EJB container can synchronize the bean at any time in the state with the persistence medium. This frequently occurs before a method of the application logic is called. The bean changes from the state Ready-Async into the state Ready-Sync.

The entity bean can use this method, for example, to recalculate transient attributes from persistent attributes (which the EJB container has just synchronized with the persistence medium).

void ejbStore()

When a client changes the state of an entity bean, the altered attribute values must be rewritten to the database. As a result, the bean instance changes from the state Ready-Update into the state Ready-Sync.

Generating and Deleting

The methods for generating and deleting entity bean identities are part of identity management and are displayed in the second group in Figures 5-7 and 5-8. These methods are to be found in the (local) home interface and are available to the client already before it knows about a bean instance.

<primKeyClass> ejbCreate(<args>)

For the generation of entity beans there are one or more methods, all called ejbCreate and all of which define the primary key class of the bean as return value. The methods are distinguished by their parameters and can be freely defined by the bean developer. These methods are not part of the entity bean interface, since the parameters and return types are different for each entity bean class.

The methods are available to the client and are therefore also declared in the entity bean's (local) home interface. The signatures of the methods in the bean class and in the (local) home interface are differentiated by their return values and their names. The methods in the (local) home interface have the bean's remote or home interface as return value and are called create. The methods of the bean class use the primary key as return value and have ejb as a prefix in their names. The EJB container manages the necessary conversion between the primary key as return value of the ejbCreate method of the entity bean and the remote or local object of the create method of the (local) home interface.

The bean developer has the task in this method of initializing all or a part of the persistent attributes with the aid of the passed parameters. The transaction context for the ejbCreate methods is set in the deployment descriptor.

void ejbPostCreate(<args>)

For each ejbCreate method the bean developer must define an ejbPostCreate method with the same parameter types and with no return value. The ejbPostCreate method is always executed by the EJB container after the corresponding ejbCreate method with the same transaction context.

Further initialization methods can be executed in these methods. In contrast to the ejbCreate methods, the bean identity is available to these methods. With the execution of ejbCreate and ejbPostCreate the bean instance changes from the state Pooled into the state Ready-Update.

void ejbRemove()

For managing bean identities we also have the methods for deleting beans. The client gives the order to delete an entity bean identity by a call to the method remove in the (local) home, remote, or local interface. The method ejbRemove on the bean instance is then called by the EJB container before the entity bean identity has been deleted. After deletion, the bean instance passes into the state Pooled. The method ejbPassivate is not called for this state transition.

In the case of container-managed persistence the bean developer does not have to implement deletion. The EJB container takes care of deleting the data. The method ejbRemove gives the bean developer the possibility of releasing additional resources before the entity bean is deleted.

The method ejbRemove can also be called by the EJB container with a transaction. Here, the associated transaction attribute in the deployment descriptor defines the behavior of the EJB container (see Chapter 7).

Search Methods

Finder Method

There are several search methods available. By definition, a bean can always be found by means of its primary key. Thus the associated method findByPrimaryKey must always exist. This search can have only a single entity bean as its target.In addition, there can be other search methods that search according to other criteria. By the naming convention, their names always begin with find, followed by a descriptive name for the search method. These methods can be defined for a single targetor a set of targets.

The search methods are declared in the (local) home interface, and the associated searches are defined in the deployment descriptor with EJB-QL (EJB Query Language). An implementation in the bean class is not required (or, to put it better, not possible) in the case of container-managed persistence.

Searches that are allowed only one target use the bean's remote or local interface directly as data type for the return value. If a search can have several targets, then java.util.Enumeration (Java 1.1) or java.util.Collection (Java 1.2) is used as data type for the return value. The method findByPrimaryKey possesses exactly one parameter, which is, in fact, the primary key. For the other search methods parameters can be declared arbitrarily.

Listing 5-4 shows an imaginary example of a home interface that defines the search methods findByPrimaryKey (must) and findByAttributeA (may). The latter method can return several targets and therefore uses java.util.Collection as return value. A search method always declares an exception of type javax.ejb.FinderException. If we are dealing with the remote client view, then in addition, the exception java.rmi.RemoteException is declared. An exception of type FinderException is then triggered if a system error occurs during the execution of the search method. With search methods that return exactly one element as target, an exception of type javax.ejb.ObjectNotFoundException is triggered if no suitable element was found. ObjectNotFoundException is derived from FinderException. With search methods that return several elements, an empty set is returned if no suitable element could be found.

Listing 5-4: Imaginary example of a home interface with find methods.

start example
 ... public interface SomeHome extends EJBHome {     ...     public Some findByPrimaryKey(SomePK pk)         throws FinderException, RemoteException;     public Collection findByAttributeA(double attrValue)         throws FinderException, RemoteException;     ... } 
end example

For every search method (other than the method findByPrimaryKey) there is defined in the deployment descriptor a search (query). The search query (ejb-ql) is associated with the particular search method via the element query-method. The name must agree with the name of the search method in the home interface. All parameters (method-params) are given in the order in which they appear in the method definition. For each parameter the data type (method-param) must be defined.

The definition of the search is formulated in EJB-QL, which will be discussed in detail later in this chapter. Listing 5-5 shows the definition of a search for the method findByAttributeA in anticipation of what is to come in this section.

Listing 5-5: EJB-QL for the method findByAttributeA

start example
 ... <enterprise-beans>   <entity>     ...     <query>       <query-method>         <method-name>findByAttributeA</method-name>         <method-params>           <method-param>double</method-param>         </method-params>       </query-method>       <ejb-ql>         SELECT OBJECT(a) FROM SomeBean AS a WHERE a.attributeA = ?1       </ejb-ql>     </query>   </entity> </enterprise-beans> ... 
end example

The defined parameters of the search method can be used in the search. They are referred to by their position in the definition. Thus the first parameter is addressed as ?1, the second as ?2, and the nth as ?< n>.

Select Methods

Select methods are similar to finder methods, except that they are more complex and are used by a bean internally, for example, in business methods. They are not designed for client use and are not published in the (local), home, remote, and local interfaces. The select methods are declared in the bean class as abstract methods with the prefix ejbSelect, and the associated search is defined in the deployment descriptor with EJB-QL. At the time of installation in the EJB container, the tools of the EJB container take care of the generation of a concrete method that at run time can be used by the entity bean instance.

Select methods, like finder methods, can return one or several references to other entity beans. However, they can also return values of persistent attributes of entity beans. Select methods can declare arbitrary parameters. The parameters are used in the finder methods for limiting the set of search results.

Listing 5-6 shows an imaginary example of an entity bean that defines the select methods ejbSelectAllABeansByName and ejbSelectAllABeanNames. The former method is to return all entity beans of type ABean whose names correspond to the passed attribute. The latter method returns all names that are used by ABean instances. It thus returns a set of String objects, which are the values of the persistent attribute name of all the Enterprise Beans of type ABean.

Listing 5-6: Pseudocode for the bean class of a select method.

start example
 ... public abstract BBean implements EntityBean {   ...   public abstract Collection ejbSelectAllABeansByName(String name)     throws FinderException;   public abstract Collection ejbSelectAllABeanNames()     throws FinderException   ... } 
end example

Listing 5-7 shows the definition of a search for the select methods in the deployment descriptor using EJB-QL. As we have already mentioned, EJB-QL will be discussed in a later section of this chapter. This example is a foretaste of the use of EJB-QL.

Listing 5-7: EJB-QL for the bean's select methods.

start example
 ... <enterprise-beans>   <entity>     ...     <query>       <query-method>         <method-name>ejbSelectAllABeansByName</method-name>         <method-params>           <method-param>java.lang.String</method-param>         </method-params>       </query-method>       <ejb-ql>         SELECT OBJECT(a) FROM ABean AS a WHERE a.name = ?1       </ejb-ql>     </query>     <query>       <query-method>         <method-name> ejbSelectAllABeanNames</method-name>         <method-params>            <!-- This method has no parameters -->         </method-params>       </query-method>       <ejb-ql>         SELECT DISTINCT a.name FROM ABean AS a       </ejb-ql>     </query>   </entity> </enterprise-beans> ... 
end example

The select method ejbSelectAllABeansByName returns references to other entity beans. These can be entity beans that support the local or remote client view. If an entity bean has a remote and a local interface, then according to the standard, a reference to the local interface of the entity bean is returned. With the element result-type-mapping within the element query it can be expressly determined whether a reference to the local or remote interface of the entity bean is returned. Permissible values for the element result-type-mapping are Local for a reference to the bean's local interface, and Remote for a reference to the bean's remote interface.

With select methods one can search for all entity beans and their attributes that are defined within the same deployment descriptor as the entity bean that is defined by a particular select method. Select methods can be used in an entity bean in home methods, business methods, and in the methods ejbLoad and ejbStore.

A select method has no transactional context of its own. Whether it is executed in a transaction depends on the transactional context of the method that calls the select method (for transactions, see Chapter 7).

Application Logic and Home Methods

The last group of methods constitute the application logic. Here is where the actual functionality of the entity bean is implemented. Normally, these methods refer to a particular bean instance. In the application methods (business methods) the access methods for reading and writing of attributes and relationships are used. The business methods are implemented by the bean developer in the bean class and published in the remote or local interface. The definition in the bean class has the same signature as the definition in the remote or local interface (see Figures 5-7 and 5-8). The name of the method may not be a reserved method name (not get<name>, set<name>, or ejb<name>).

In exceptional cases, however, there is also application logic that does not refer to a specific instance. This can be realized as a so-called home method. Home methods are published in the (local) home interface and are available to the client, even if it has no available entity bean instance. Its name in the bean class always begins with ejbHome, followed by a name for the method. In the home interface the prefix is omitted (see also Figures 5-7 and 5-8). The name for the method may not be a reserved method name (not create<name> or find<name>).

In the implementation of a home method one needs to note that the object has no identity. The particular ejbHome method is called on an instance in the state Pooled. Therefore, no access methods other than the select methods may be called. Furthermore, the generation and deletion of bean instances is prohibited.

The application methods in the home and remote interfaces of the remote client view always define the RemoteException, while the methods in the bean class use EJBException to signal a system error. The exeception EJBException is transformed by the EJB container into a RemoteException. Application methods of the local home and local interfaces do not define any exception of type RemoteException. If an error occurs, then EJBException is relayed directly to the local client.

The EJB container controls all calls to the methods of a bean. It delegates the method calls on the (local) home, remote, or local interface to the corresponding methods of the entity bean instance. The client never directly accesses the bean instance. The EJB container uses its position as intermediary between client and bean instance for a variety of tasks. For example, the EJB container ensures that a method is executed with the correct transaction context. It evaluates the transaction attribute of the method in the deployment descriptor, compares this with the client's transaction context, and then carries out the necessary actions to comply with the method's transactional requirements (see Chapter 7). Other examples of tasks of the EJB container are access protection for beans (see Chapter 8) and error logging.

Example Counter

To clarify the fundamental aspects of an entity bean with container-managed persistence 2.0, which was dealt with in this section, we will now look at a simple example; an application with many remote clients must manage a variety of counters; the counters should be available to all clients and be centrally managed; and each client must have the ability to change a particular counter. The counter may not be less than 0 nor greater than 100.

The entity bean Counter fulfills these requirements. It supports the remote client view. With it, it is possible to manage various counters on the application server that are accessible by all clients. Each client can read and change the state of a particular counter.

First the remote interface of the counter bean is defined, which represents the functionality with respect to remote clients (see Listing 5-8). It defines the method inc for increasing a particular counter, the method dec to decrease a particular counter, and the method getValue to return the current state of a particular counter.

Listing 5-8: Remote interface of the counter bean.

start example
 package ejb.counter; import java.rmi.RemoteException; import javax.ejb.EJBObject; public interface Counter extends EJBObject {     public void inc()         throws RemoteException, CounterOverflowException;     public void dec()         throws RemoteException, CounterOverflowException;     public int getValue()         throws RemoteException; } 
end example

In addition to the RemoteException, the methods inc and dec declare the exceptions CounterOverflowException (see Listing 5-9). It is triggered if the state of a counter overflows, that is, if the value after a decrement would be less than 0 or if the value after an increment would be over 100.

Listing 5-9: Exception CounterOverflowException.

start example
 package ejb.counter; public class CounterOverflowException extends Exception {     public CounterOverflowException() {         super();     }     public CounterOverflowException(String message) {         super(message);     } } 
end example

A further component of the counter bean is the home interface (Listing 5-10). It defines the method create, by which a new counter can be generated. The counter has an ID in the form of a string object. The counter can be uniquely identified with this ID and can be located using the method findByPrimaryKey. Moreover, the initial state of the counter is passed to the counter in the method create. Furthermore, the home interface defines a home method for the counter bean with the name getAllCounterIds. It returns the IDs of all existing counters in the form of string objects. This functionality is not coupled to a particular counter and is therefore implemented in the home method. A client has the ability to determine via the home method what counters exist. If it has an interest in a particular counter, then it can access that counter using its ID with the method findByPrimaryKey.

Listing 5-10: Home interface of the counter bean.

start example
 package ejb.counter; import javax.ejb.CreateException; import javax.ejb.EJBHome; import javax.ejb.FinderException; import java.rmi.RemoteException; public interface CounterHome extends EJBHome {     public Counter create(String counterId, int initCounterValue)         throws CreateException, RemoteException;     public Counter findByPrimaryKey(String counterId)         throws FinderException, RemoteException;     public java.util.Collection getAllCounterIds()         throws RemoteException; } 
end example

After the home and remote interfaces have been defined, the bean class is defined (see Listing 5-11). It is an abstract class that implements the interface javax.ejb.EntityBean. It defines the method ejbCreate, corresponding to the create method of the home interface (as well as the method ejbPostCreate prescribed by the specification). The counter bean has two persistent attributes, namely, counterId and counterValue. The attribute counterId serves as the primary key of the counter bean. For each attribute the abstract getter/setter methods are defined.

Listing 5-11: Bean class of the counter bean.

start example
 package ejb.counter; import javax.ejb.CreateException; import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.ejb.FinderException; public abstract class CounterBean implements EntityBean {     public final static int VALUE_MAX = 100;     public final static int VALUE_MIN = 0;     private transient EntityContext ctx;     //The create method of the home interface     public String ejbCreate(String counterId,                             int initCounterValue)         throws CreateException     {         if(counterId == null) {             throw new CreateException("counterId is null!");         }         if(initCounterValue < VALUE_MIN ||            initCounterValue > VALUE_MAX)         {             String s = "initCounterValue out of range: "                      + initCounterValue;             throw new CreateException(s);         }         this.setCounterId(counterId);         this.setCounterValue(initCounterValue);         return null;     }     public void ejbPostCreate(String counterId,                               int initCounterValue)     {}     //Abstract getter/setter methods     public abstract void setCounterId(String id);     public abstract String getCounterId();     public abstract void setCounterValue(int value);     public abstract int getCounterValue();         //Abstract select methods         public abstract java.util.Collection ejbSelectAllCounterIds()             throws FinderException;         //Methods of the remote interface         public void inc() throws CounterOverflowException {             if(this.getCounterValue() < VALUE_MAX) {                 this.setCounterValue(this.getCounterValue() + 1);             } else {                 String s = "Cannot increase above " + VALUE_MAX;                 throw new CounterOverflowException(s);             }         }         public void dec() throws CounterOverflowException {             if(this.getCounterValue() > VALUE_MIN) {                 this.setCounterValue(this.getCounterValue() - 1);             } else {                 String s = "Cannot decrease below " + VALUE_MIN;                 throw new CounterOverflowException(s);             }         }         public int getValue() {             return this.getCounterValue();         }         //Methods of the entity bean interface         public void ejbActivate() {}         public void ejbPassivate() {}         public void setEntityContext(EntityContext ctx) {             this.ctx = ctx;         }         public void unsetEntityContext() {             this.ctx = null;         }         public void ejbLoad() {}         public void ejbStore() {}         public void ejbRemove() {}         // Home methods         public java.util.Collection ejbHomeGetAllCounterIds() {             java.util.ArrayList al = new java.util.ArrayList();             try {             java.util.Collection col =                 this.ejbSelectAllCounterIds();             java.util.Iterator it = col.iterator();             while(it.hasNext()) {                 al.add(it.next());             }         } catch(FinderException ex) {             ex.printStackTrace();         }         return al;     } } 
end example

In addition to the abstract methods for the persistent attributes, an abstract ejbSelect method is defined. It returns all counter IDs in the form of string objects and is used by the home method getAllCounterIds in carrying out its responsibilities. The home method getAllCounterIds of the home interface gets the prefix ejbHome in the bean class, as required by the specification.

The methods inc, dec, and getValue of the remote interface are also implemented in the bean class. The callback methods of the entity bean interface remain largely empty. In the case of container-managed persistence the EJB container takes over the lion's share of the work, so that for the bean class itself there is little to implement.

Finally, the deployment descriptor of the counter bean is defined (see Listing 5-12). Worthy of note is the element query, in which the method ejbSelectAllCounterIds is declaratively implemented using EJB-QL, which will be discussed later in this chapter. Moreover, in the assembly descriptor it is set that the methods inc and dec must be called in a transaction, again a foretaste of Chapter 7, in which transactions will be handled in detail.

Listing 5-12: Deployment descriptor of the counter bean.

start example
 <?xml version="1.0" ?> <ejb-jar version="2.1" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">   <enterprise-beans>     <entity>       <ejb-name>Counter</ejb-name>       <home>ejb.counter.CounterHome</home>       <remote>ejb.counter.Counter</remote>       <ejb-class>ejb.counter.CounterBean</ejb-class>       <persistence-type>Container</persistence-type>       <prim-key-class>java.lang.String</prim-key-class>       <reentrant>False</reentrant>       <cmp-version>2.x</cmp-version>       <abstract-schema-name>CounterBean</abstract-schema-name>       <cmp-field>         <description>The Id of the counter</description>         <field-name>counterId</field-name>       </cmp-field>       <cmp-field>         <description>The value of the counter</description>         <field-name>counterValue</field-name>       </cmp-field>       <primkey-field>counterId</primkey-field>       <query>         <query-method>           <method-name>ejbSelectAllCounterIds</method-name>           <method-params>           </method-params>         </query-method>         <ejb-ql>           SELECT DISTINCT cb.counterId FROM CounterBean AS cb         </ejb-ql>       </query>     </entity>   </enterprise-beans>   <assembly-descriptor>     <container-transaction>       <method>         <ejb-name>Counter</ejb-name>         <method-name>inc</method-name>       </method>       <method>         <ejb-name>Counter</ejb-name>         <method-name>dec</method-name>       </method>       <trans-attribute>Required</trans-attribute>     </container-transaction>   </assembly-descriptor> </ejb-jar> 
end example

With this the components of the entity bean counter are complete from the point of view of the bean developer. One task for deployment yet to be done is the mapping of the bean's persistent attributes to the database. These tasks are generally handled by the deployer. How these instructions are to be made depends on the application server. Listing 5-13 shows an imaginary example of how such instructions might be given.

Listing 5-13: Imaginary database mapping for the counter bean.

start example
 <database-mapping>     <bean-mapping>         <ejb-name>Counter</ejb-name>         <data-source-name>postgres</data-source-name>         <table-name>counter</table-name>         <field-map>             <cmp-field>counterId</cmp-field>             <dbms-column>id</dbms-column>         </field-map>         <field-map>             <cmp-field>counterValue</cmp-field>             <dbms-column>value</dbms-column>         </field-map>     </bean-mapping> </database-mapping> 
end example

The attributes of the entity bean counter are stored in a table with the name counter. The bean attribute counterId is stored in the column id, the attribute counterValue in the column value. The persistence manager should use the preconfigured JDBC data source with the JNDI name postgres for the connection. Listing 5-14 shows the SQL statement for the generation of the table counter.

Listing 5-14: SQL statement for generating the table counter.

start example
 CREATE TABLE COUNTER (   ID VARCHAR(128) NOT NULL UNIQUE,   VALUE INTEGER NOT NULL ) 
end example

To conclude, Listing 5-15 shows how an imaginary client might use the counter bean.

Listing 5-15: Imaginary example of a client of the counter bean.

start example
 ...   InitialContext ctx = new InitialContext();   Object o = ctx.lookup("Counter");   CounterHome counterHome =     (CounterHome)PortableRemoteObject.narrow(o, CounterHome.class);   Counter counter = counterHome.create("carsInGarage", 0);   ...   try {       counter.inc();   } catch(CounterOverflowException ex) {       throw new IllegalStateException("garage is full");   }   ...   try {       counter.dec();   } catch(CounterOverflowException ex) {       this.garageIsEmpty = true;   } ... 
end example




Enterprise JavaBeans 2.1
Enterprise JavaBeans 2.1
ISBN: 1590590880
EAN: 2147483647
Year: 2006
Pages: 103

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