Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Java Training: Entity Beans 5.1 5. Entity Beans Overview Entity Bean Life Cycle Writing an Entity Bean SKILLBUILDERS © 2004-2006 SkillBuilders, Inc. Java Training © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.2 5.2 5.2 Entity Beans: Overview... Entities The “things” that a business process manipulates ¾ E.g. Customers, Accounts, Orders, Flights ¾ The data they contain is stored in database tables ¾ Entity Bean ¾ ¾ A bean representing a business entity The object representation of a row of data in a table ¾ Entity beans differ from session beans: Entity beans are always stateful They are always persistent - they map to a database ¾ They are always shared ¾ Client can find existing ones as well as create new ones ¾ ¾ ¾ Entity beans require a primary key Java Training © 2004-2006 SkillBuilders, Inc. An entity bean is an enterprise bean that encapsulates a business object or entity, as opposed to a business process. An entity bean instance represents a unit of data in the database. Familiar examples include Customer, Account, Order, Flight. Entity beans were defined in version 1.0 of EJB, but not required until 1.1. So some early EJB products did not support them. (Originally Sun Microsystems planned to require them in a later version, but apparently the great demand for them induced Sun to accelerate the plan.) Entity beans differ from session beans in several important ways: ¾ Session beans can be stateful or stateless; by their nature, entity beans are always stateful. They encapsulate instance data that comes from and will be written back to a database. ¾ Session beans are usually transient, but may be persistent. Entity beans are always persistent. They map to a database. ¾ Session beans represent clients, so only stateless ones are shared among clients. Stateful session beans are never shared. But entity beans are always shared. ¾ With session beans, a client can create new ones or remove existing ones. (For stateless session beans, creating and removing simply means connecting to or disconnecting from the only instance.) With entity beans the client can also find existing instances by various criteria. As with database tables, this requires definition of a primary key. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.3 5.3 5.3 ...Entity Beans: Overview ¾ Entity beans are shared ¾ Container creates a pool ¾ Instances in use represent distinct entities ¾ Idle instances are returned to pool ¾ When necessary, container can expand or shrink pool EJB EJBContainer Container "Ready" "Ready" instances instances 456 456 RDB RDB Server Server 123 123 Client Client Client Client Pool Poolofofidle idleinstances instances Java Training © 2004-2006 SkillBuilders, Inc. Entity beans can be thought of as the object representation of rows of data. The database contains data for all the entities in the system. At any given moment, a subset of those entities is in use by clients. The EJB container creates a pool of identical bean instances. When a client requests an entity, the container takes an instance from the pool, loads it with data from the database, and puts it into the “ready” category, where it represents that entity to any clients who need it. Entity beans are like stateful session beans in that they have state and, therefore, a client uses the same instance over many method calls. But they resemble stateless session beans in that clients share them. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.4 5.4 5.4 Entity Beans & Persistence... ¾ Persistence can be managed by: The container ¾ The bean itself ¾ ¾ Container-managed persistence (CMP): At deployment, bean's data is mapped to database ¾ Container reads / writes data from / to database as needed ¾ Container can use JDBC or any other database API ¾ Bean need not contain any persistence logic ¾ ¾ How does the container know when to read/write? ¾ Tied to transactions (covered later…) Java Training © 2004-2006 SkillBuilders, Inc. Persistence in an entity bean can be managed by the EJB container or by the bean itself. Container-managed persistence (CMP) works like this: At deployment, the bean's data is mapped to a table in a database. Whenever the data needs to be loaded into or saved from a bean instance, the EJB container reads / writes data from / to the database. The container can use JDBC or any other API to access the database. This frees the bean itself from having to contain any persistence logic. One important question concerns timing: How does the container know when to read/write data? The answer lies in bean transactions, which we cover later. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.5 5.5 5.5 ...Entity Beans & Persistence ¾ Bean-managed persistence (BMP): Bean contains logic for reading / writing data ¾ Container calls life-cycle methods to trigger the logic ¾ ¾ Why manage persistence explicitly? ¾ To use non-JDBC databases ¾ To use features not available otherwise ¾ Flat files, OO databases, etc. ¾ How we will proceed: ¾ ¾ Container-managed persistence is covered here Bean-managed persistence is covered later... Java Training © 2004-2006 SkillBuilders, Inc. The other alternative is bean-managed persistence (BMP), in which the bean contains explicit logic for reading / writing data. This logic lives in life-cycle methods which the container calls at key points. Container-managed persistence is much easier from the developer's viewpoint. So why manage persistence explicitly? JDBC is the J2EE standard way of accessing a database. Most J2EE servers will require a JDBC-accessible database for container-managed persistence. If your data source is not accessible via JDBC, you must manage the persistence yourself. We will cover container-managed persistence here, and bean-managed persistence in a later lesson... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.6 5.6 5.6 Entity Bean Life Cycle... Entity bean life cycle tasks represent SQL operations: ¾ “Creating” an entity: Represents creating a new row in a table ¾ Container executes an insert statement ¾ Triggered by calling Home#create( * ) ¾ ¾ “Removing” an entity: Represents deleting a row from a table ¾ Container executes a delete statement ¾ Triggered by calling EJBObject#remove( ) ¾ ¾ “Finding” an entity: Container executes a select statement ¾ Triggered by calling Home#find*( ) ¾ Java Training © 2004-2006 SkillBuilders, Inc. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.7 5.7 5.7 ...Entity Bean Life Cycle State diagram for an entity bean. See notes for details... Java Training © 2004-2006 SkillBuilders, Inc. This diagram, from the EJB 2.0 specification, shows the life cycle of an entity bean. Key features of the diagram: ¾ Bean class instances can be in one of three states: does not exist, pooled, or ready. Every type of entity bean has its own pool. ¾ A bean moves from does not exist to pooled when the container increases the pool by adding a new instance to it. ¾ A bean moves from pooled to ready in either of two ways. One is when the client creates a new entity (insert a new row in the database); in this case the bean’s ejbCreate( ) and ejbCreate( ) are called. The other is when the client wants to use an existing entity (row of data) for which there is no bean in the pool; in this case an instance is activated. ¾ In the ready state a bean instance will hold data for a particular entity. Its ejbLoad( ), ejbStore( ) and various business methods will be called often. ¾ A bean moves from ready to pooled either when it is passivated or the entity it represents is removed. ¾ A bean moves from pooled to does not exist when the container decreases the pool by letting the instance be garbage collected. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.8 5.8 5.8 Writing an Entity Bean... You must write four key parts of an entity bean: ¾ Some are similar/identical to those of a session bean ¾ The remote interface: ¾ Describes bean's public functions ¾ Identical to session bean ¾ The home interface: ¾ Describes a bean factory ¾ The bean class: ¾ The primary key: ¾ ¾ Provides code for remote and home interfaces Defines key for getting an instance See diagram on next page... ¾ Details follow... Java Training © 2004-2006 SkillBuilders, Inc. To understand how an entity bean works, we will take it apart and study its anatomy. An entity bean is made up of several parts: ¾ The remote interface is a Java interface describing bean's public functions. This exactly the same as CORBA IDL or an RMI remote interface. ¾ The primary key defines the basic key for uniquely identifying an entity bean instance. ¾ The home interface describes a bean factory. ¾ The Bean class actually implements the bean and home interfaces. The diagram on the next page shows how these interfaces and classes interact with each other... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.9 5.9 5.9 ...Writing an Entity Bean Remote Remote java.rmi EnterpriseBean EnterpriseBean javax.ejb EJBObject EJBObject EJBHome EJBHome EntityBean EntityBean CustomerHome CustomerHome CustomerBean CustomerBean bookstore Customer Customer Interface Interface Java Training Class Class Extends Implements © 2004-2006 SkillBuilders, Inc. This diagram illustrates the layout of classes and interfaces for a hypothetical Customer entity bean. It is identical to the one for a session bean in two respects: ¾ The remote interface (Customer) extends EJBObject. ¾ The remote interface (CustomerHome) extends EJBHome. It differs slightly (but predictably) from session bean with respect to the bean class: ¾ The bean class (CustomerBean) implements EntityBean. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.10 5.10 5.10 The Remote Interface... ¾ As with session bean: Defines interface for your entity bean's business methods ¾ Must be public ¾ Must extend javax.ejb.EJBObject ¾ Must satisfy requirements of RMI remote interfaces ¾ ¾ What's in the interface? ¾Methods representing bean properties ¾Entity-related process methods ¾ Methods for bean properties: ¾Entity beans have data, thus have "properties" ¾Do not have to map to database fields ¾JavaBeans defines get/set patterns ¾EJB does not require this but it is still useful Java Training © 2004-2006 SkillBuilders, Inc. As with session beans, when creating an entity bean the first thing you will write is the remote interface for the bean itself. This interface defines how the bean looks to the rest of the system. (Note that this is generally the first step in all distributed object architectures: in Java RMI one starts by writing a remote interface; in CORBA one starts with IDL.) The remote interface for an entity bean must extend the javax.ejb.EJBObject interface, just as for session beans. Too, it must satisfy requirements of RMI remote interfaces. The remote interface for an entity bean will contain two types of methods: ¾ get / set methods representing bean properties. ¾ Entity-related process methods. A "property" is a data attribute of a bean, such as a customer's name or an account's balance. Many such properties will map to database fields, although they do not have to. Continued... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.11 5.11 5.11 ...The Remote Interface ¾ Entity-related process methods: Represent activities performed on bean ¾ E.g. buy( ) and sell( ) on a Portfolio ¾ ¾ See examples in notes... ¾ A Customer bean for the online bookstore ¾ A Portfolio bean for the online brokerage ¾ ¾ Has only property methods Has property and process methods Java Training © 2004-2006 SkillBuilders, Inc. The methods representing bean properties are the familiar get/set patterns defined in the JavaBeans specification, which have become standard in Java programming. A proptype propname property is represented by two methods: public proptype getPropname( ) public void setPropname( proptype value ) For example, a read/write property called description of type String would translate to these two methods: public String getDescription( ) public void setDescription( String value ) If the property were read-only, you would supply the get method only. Note: EJB does not actually require that you adhere to these patterns. But they have become a Java standard and so would still help standardize the design of your interface. The other type of method in the remote interface would represent a process or activity performed on the entity. Typical examples might be buy() & sell() on a Portfolio bean, or process( ) on an Order bean. On the following pages are two sample remote interfaces for entity beans: ¾ A Customer bean for the online bookstore. It has only property methods. ¾ A Portfolio bean for the online brokerage. It has both property and process methods. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans Here is the remote interface for a Customer bean. properties: 5.12 It defines the following ¾ readonly int id ¾ String lastName ¾ String firstName ¾ readonly String fullName import javax.rmi.*; public interface Customer extends javax.ejb.EJBObject { // For readonly int id property: public int getId() throws RemoteException; // For String lastName property: public String getLastName() throws RemoteException; public void setLastName(String value) throws RemoteException; // For String firstName property: public String getFirstName() throws RemoteException; public void setFirstName(String value) throws RemoteException; // For readonly String fullName property: public String getFullName() throws RemoteException; } And here is the remote interface for a Portfolio bean, with a readonly float marketValue property and two additional methods: import javax.rmi.*; public interface Portfolio extends javax.ejb.EJBObject { // For readonly float marketValue property: public float getMarketValue() throws RemoteException; // Methods to buy / sell stocks public void buy(Stock stock, int quantity) throws RemoteException; public void sell(Stock stock, int quantity) throws RemoteException; } © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.13 5.13 5.13 The Primary Key Primary Key Unique identifier to an entity ¾ Unique identifier to a row in a database table ¾ May be system generated or endemic ¾ May be single or compound value ¾ ¾ For example: Customer: system-generated customer ID ¾ Employee: Social-Security # ¾ LineItem in an Order: Order # + product # ¾ Java Training © 2004-2006 SkillBuilders, Inc. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.14 5.14 5.14 Primary Key Class... ¾ Entity beans require a primary key class Container uses PK instance to identify bean instance ¾ In CMP, container creates PK, uses to handle persistence ¾ Deployment descriptor names the class ¾ ¾ Tells container what to instantiate ¾ Requirements for a primary key class: ¾ Class is public ¾ Implements java.io.Serializable ¾ Has a public no-args constructor ¾ Implicit constructor is fine ¾ Has sensible equals( ) & hashCode( ) methods java.io. . java.io java.io. Serializable Serializable Primary Primarykey keyclass class ¾ For single-field, non-primitive key: ¾ Choose the class type of the key field Java Training © 2004-2006 SkillBuilders, Inc. Why a Primary Key Class? Container-managed persistence requires a class to represent the primary key of the entity. The container creates and uses instances of this class at the appropriate times to handle persistence. (A bean does not need such a class if it manages its own persistence, but to maximize reusability you could develop the entity bean to use the primary key class either way.) When the bean is deployed, its deployment descriptor identifies the class so the container knows what to instantiate. Class Requirements A primary key class must meet the following requirements: ¾ It must implement the java.io.Serializable interface, since instances of it will travel across the wire. (Note that primary key objects are copied across, not used remotely.) ¾ It must have a public no-args constructor, since the container will use Class.newInstance( ) to instantiate the class. The implicit constructor provided by the compiler is fine, but if you write additional constructors, you must provide the default constructor yourself. Continued... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.15 5.15 5.15 ...Primary Key Class ¾ For multi-field or primitive keys: Write a custom class ¾ Define a public field for each key component ¾ PK field names must match bean class field names ¾ ¾ Optional features (for BMP or client use): ¾ ¾ Overloaded constructor toString( ) ¾ See notes for examples… Book: Single-field, non-primitive Customer: Single-field, primitive ¾ Order LineItem: Multi-field ¾ ¾ Java Training © 2004-2006 SkillBuilders, Inc. Single-Field Non-Primitive Keys For simple keys that are object types (not primitives), you can use an existing Java class such as String to be the primary key class. Multi-Field & Primitive Keys For keys based on multiple fields, you must write a custom class. The class must meet the requirements listed above, and must: ¾ implement java.io.Serializable. ¾ Have a public no-args constructor. ¾ Have public fields for each key component. The container will assign them values after creating the instance, and will use their values to locate data in the database. The deployment descriptor will map these fields to database fields, but typically the variable names must match those in the bean class. ¾ Have appropriate equals( ) and hashCode( ) methods. For example, equals( ) as defined in java.lang.Object would only return true if two references pointed to the same instance, not to identical instances. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.16 Enhancements You can enhance a primary key class with optional features both to make it easier to use and to insure its proper use: ¾ You can overload the constructor with another that initializes the fields. This is a convenience to clients instantiating the primary key class to locate a bean. ¾ You can explicitly define toString( ). PK Examples Single-Field, Non-Primitive If books are identified by their ISBN (which obviously is a String), for a Book bean you would simply tell the deployment utility that the primary key is a java.lang.String and the field name is isbn. Single-Field, Primitive In our bookstore, Customer is identified by an int key. Although the java.lang.Integer seems a natural wrapper class, it lacks a public default constructor. So instead we provide a custom class: public class CustomerPK implements java.io.Serializable { public int id; // This name MUST match CMP field name in Bean public CustomerPK() {} public CustomerPK(int id) { this.id = id; } public boolean equals(Object objOther) { if(objOther == null || (objOther.getClass() != getClass()) return false; else if(! super.equals(objOther)) return false; else return (id == objOther.id); } public int hashCode() { return id; } public String toString() { return id + ""; } } Continued... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.17 Multi-Field This example shows a primary key class for a compound key that identifies line items in an order by their order number (int) and product number (String): public class LineItemPK implements java.io.Serializable { public int orderId; // These names MUST match public String productId; // CMP field names in Bean public LineItemPK() {} public LineItemPK(int orderId, String productId) { this.orderId = orderId; this.productId = productId; } public boolean equals(Object objOther) { if(objOther == null || (objOther.getClass() != getClass()) return false; else if(! super.equals(objOther)) return false; else return (orderId == objOther.orderId && productId.equals(objOther.productId)); } public int hashCode() { return orderId * 17 + productId.hashCode(); } } © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.18 5.18 5.18 The Home Interface ¾ As with session beans: Every entity bean has a home interface Client uses home to get bean instances ¾ All clients share one home object for given bean type ¾ The home interface must extend javax.ejb.EJBHome ¾ ¾ ¾ An entity home lets a client: ¾ ¾ Create new entities Find existing entities ¾ An entity home will have: ¾ ¾ create( ) methods A findByPrimaryKey( ) method ¾ Details follow... Java Training © 2004-2006 SkillBuilders, Inc. As with session beans, every entity bean has a home interface. This defines the "factory" object that the EJB client uses to create, get and destroy bean instances. Again, all clients share a single home object for the given bean type. And again, the home interface must extend javax.ejb.EJBHome. The home interface will have two sets of methods: As with session beans, it may have create( ) methods. The home interface will also have methods we did not see for session beans: find*( ) methods. These are used to look up existing instances; they correspond to SQL select statements. Specifically, every home interface will have a findByPrimaryKey( ) method, and may have additional finder methods. More on each on the pages that follow... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.19 5.19 5.19 create(*) ¾ “Creating” an entity bean: Represents creating a new row in a table Container executes an insert statement ¾ Triggered by calling Home#create( … ) ¾ ¾ ¾ The create( ) methods: The client uses them to create new entities ¾ Can be overloaded ¾ Most entity homes will have at least one ¾ Occasionally a home should have none ¾ ¾ See notes for two examples... CustomerHome has two create( ) methods ¾ BookHome has none ¾ Java Training © 2004-2006 SkillBuilders, Inc. The home interface will also likely have create( ) methods, at least one and possibly more. The client uses them to create new bean instances; as with session beans, they correspond to constructors. But they also correspond to SQL insert statements; when a client calls create( ), a new row of data is inserted into a table. Occasionally a design includes entities that are inserted into the database only by a system administrator, and only through direct access to the database. Clients are not permitted to create new entities of these types. For example, we would not want to let an EJB client arbitrarily create new books in our bookstore or new stocks in our brokerage. In those cases, the home interface should not have any create( ) methods. See the two examples on the next page... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.20 Here are two examples of home interfaces illustrating the use of create( ) methods. First, the home interface for Book entities; it has no create( ) methods because a bean client cannot create new books; they are added to the database by an administrator: import javax.ejb.*; import javax.rmi.RemoteException; public interface BookHome extends EJBHome { // No create methods; books are added to database // by system administrator. // Finders (shown later...): } The second example is CustomerHome. This one has two creates. But neither takes an ID argument -- even though ID is the primary key -- because the key is generated automatically by the database. import javax.ejb.*; import javax.rmi.RemoteException; public interface CustomerHome extends EJBHome { // Create methods (id is generated automatically): public Customer create() throws RemoteException, CreateException; public Customer create(String lastName, String firstName) throws RemoteException, CreateException; // Finders (shown later...): } © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.21 5.21 5.21 findByPrimaryKey( ) ¾ findByPrimaryKey( ) public public RemoteType RemoteType findByPrimaryKey( findByPrimaryKey( RemoteTypePK RemoteTypePK )) throws throws java.rmi.RemoteException, java.rmi.RemoteException, FinderException FinderException Described explicitly in EJB spec ¾ Looks up entity by primary key, returns remote bean type ¾ public public Book Book findByPrimaryKey(String findByPrimaryKey(String pk) pk) throws... throws... ¾ FinderException Finder throws javax.ejb.FinderException: ¾ Defines all failures to find request objects ¾ ¾ Home can have other find*( ) methods ¾ ¾ To locate single entities or sets Not covered in this course... Java Training © 2004-2006 SkillBuilders, Inc. The EJB spec describes find*( ) methods to be defined in the home interface. These do not exist for session beans; they are unique to entity beans. They are used to locate an existing bean instance (in reality, to create a bean instance from existing data). In container-managed persistence, these methods are implemented automatically by the container. They all have this syntax: findByPrimaryKey( ) is described explicitly in the spec. Obviously it looks up an entity by its primary key value and returns an instance of the remote bean type. For example, the BeanHome interface would have the method shown above. This method throws a javax.ejb.FinderException. exception that defines all failures to find request objects. © 2004-2006 SkillBuilders, Inc. This is a checked V3.1 Java Training: Entity Beans 5.22 5.22 5.22 Finders in Use ¾ An example of finder methods in use: ¾ An updated ShoppingCartBean class ¾ To ¾ ejbCreate( ) uses findByPrimaryKey( ) to locate customer ¾ To ¾ ¾ assign a customer: add a book: addSelection( ) uses findByPrimaryKey( ) to locate book Throws FinderException if failed ¾ See code in notes... Java Training © 2004-2006 SkillBuilders, Inc. Here is an example showing the use of various finder methods in our bookstore shopping cart. The ShoppingCartBean class uses them in several places: ¾ One of the ejbCreate( ) methods uses findByPrimaryKey( ) to locate the customer by ID and assign it to the shopping cart. ¾ The addSelection( ) method uses findByPrimaryKey( ) to locate the desired book by its ISBN and add it to the shopping cart. Note that the ShoppingCartBean class uses instance variables to hold references to the home objects for Book and Customer, rather than look up these objects every time they're needed. See the code on the next page... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.23 ShoppingCart Interface Here is the revised ShoppingCart interface to include two new methods: package bookstore; import java.rmi.RemoteException; public interface ShoppingCart extends javax.ejb.EJBObject { // Methods for selecting books public void addSelection(String strIsbn) throws RemoteException, FinderException; public void removeSelection(String strIsbn) throws RemoteException; public void clear() throws RemoteException; public Book[] getSelections() throws RemoteException; // Method to handle purchase public void buy() throws RemoteException; // Method for a readonly Customer customer property public Customer getCustomer() throws RemoteException; } ShoppingCartBean Class And here is the revised ShoppingCartBean class to implement the two new methods as well as complete the implementation of the existing ones: (Please turn to the next page…) © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.24 package bookstore; import java.util.*; import javax.ejb.*; import javax.naming.*; public class ShoppingCartBean implements SessionBean { //================================================ // Instance Variables //================================================ private Hashtable private Customer _htBooks = new Hashtable(); _cust; private BookHome private CustomerHome _bookhome; _custhome; private SessionContext _ctxt; // For session context //================================================ // Methods for remote interface //================================================ // Method for selecting books public void addSelection(String strIsbn) throws FinderException { // Look up book Book b = null; try { b = _bookhome.findByPrimaryKey(strIsbn); } // Catch FinderException and re-throw with additional message catch(FinderException fe) { String strMsg = "Can't find book " + strIsbn + '\n' + fe.getMessage(); throw new FinderException(strMsg); } _htBooks.add(strIsbn, b); } public void removeSelection(String strIsbn) { _htBooks.remove(strIsbn); } // Continued.... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.25 public void clear() { _htBooks.clear(); } public Book[] getSelections() { int n = _htBooks.size(); Book[] books = new String[n]; Enumeration e = _htBooks.elements(); for( int i = 0; i < n; i++ ) books[i] = (Book) e.nextElement(); return books; } // Method for a readonly Customer customer property public Customer getCustomer() { return _cust; } // Method to handle purchase public void buy() { // Not yet implemented... } //================================================ // Methods for create(*) in home interface //================================================ public void ejbCreate(Customer cust) { _cust = cust; // Assign to instance variable } public void ejbCreate(int iCustID) throws CreateException { // Look up customer Customer cust; try { cust = _custhome.findByPrimaryKey(new CustomerPK(iCustID)); } catch(FinderException fe) { String strMsg = "Can't find customer " + iCustID + '\n' + fe.getMessage(); throw new CreateException(strMsg); } _cust = cust; // Assign to instance variable } // Continued... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.26 //================================================ // Methods required by SessionBean interface //================================================ public void ejbActivate() { } // Not used public void ejbPassivate() { } // Not used public void ejbRemove() { } // Not used public void setSessionContext(SessionContext ctxt) throws EJBException { _ctxt = ctxt; try { getBookHome(); // Get home object. getCustomerHome(); // Get home object. } catch(NamingException ne) { throw new EJBException(ne); } } //================================================ // Private support methods //================================================ // This method looks up BookHome and assigns it to // an instance variable. private void getBookHome() throws NamingException { // Look up book home Context ctxt = ...; // Get initial context _bookhome = ctxt.lookup(...); // Look up home object } // This method looks up CustomerHome and assigns it to // an instance variable. private void getCustomerHome() throws NamingException { // Look up customer home Context ctxt = ...; // Get initial context _customerhome = ctxt.lookup(...); // Look up home object } // Continued... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.27 private Book createBookArrayFromEnumeration(Enumeration e) { ArrayList arraylist = new Vector(); while(e.hasMoreElements()) arraylist.add(e.nextElement()); int n = arraylist.size(); Book[] books = new Book[n]; for( int i = 0; i < n; i++ ) books[i] = (Book) arraylist.get(i); return books; } } // End of ShoppingCartBean class © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.28 5.28 5.28 The Entity Bean Class... ¾ The bean class implements your bean Provides functionality defined in remote bean interface ¾ Responds to methods in home interface ¾ Similar to bean class for session bean ¾ ¾ As with session bean: ¾ ¾ Class is public Has a public default constructor Has all methods of remote interface ¾ Has an ejbCreate( ) for each create( ) of home interface ¾ Java Training © 2004-2006 SkillBuilders, Inc. The fourth part of the entity bean that you write is the bean class itself. As with session beans, this class contains the actual implementation of your bean: It provides the functionality defined in the remote bean interface, as well as methods that respond to the create( ) methods in the home interface. The entity bean class must satisfy a number of basic requirements. Some of these are identical to those we learned for a session bean class: ¾ The class must be public. ¾ It must have a public default constructor. ¾ It must have all the methods of the remote interface, even though it does not officially implement this interface! ¾ It must have an ejbCreate( ) method to match each create( ) method of the home interface. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.29 5.29 5.29 ...The Entity Bean Class ¾ Additional requirements for a CMP bean class: ¾ Class is abstract Has methods for CMP fields Has an ejbPostCreate( ) for each create( ) ¾ Implements javax.ejb.EntityBean interface ¾ ¾ ¾ Details follow... ¾ See example in notes... ¾ A CustomerBean class Java Training © 2004-2006 SkillBuilders, Inc. But a CMP entity bean class has additional, unique requirements: ¾ The class must be abstract. This relates to CMP fields, described below. ¾ It must of course implement the CMP fields. ¾ It must have a second method to match each create( ) method of the home interface, one called ejbPostCreate( ). ¾ Instead of SessionBean, it must implement the counterpart interface, javax.ejb.EntityBean. CustomerBean class shown on the next page. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.30 import javax.ejb.*; import javax.rmi.*; public abstract class CustomerBean implements EntityBean { // Default constructor provided by compiler... //================================================ // Methods for remote interface //================================================ // Methods for id, lastName & firstName properties // are not shown because they correspond to CMP fields. // We’ll see them later... // For readonly String fullName property: public String getFullName() { return getFirstName() + " " + getLastName(); } // Rest of class... } © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.31 5.31 5.31 Handling create(*)... ¾ Home#create(...) triggers creation of new entity ¾ Container executes an SQL insert ¾ Bean class must have two matching methods: ejbCreate( ) is called before insert ejbPostCreate( ) is called after insert ¾ Both are invoked by container upon create ¾ ¾ ¾ Syntax: Java Training ¾ RemoteType RemoteType create( create( Arg Arg List List )) throws throws ...; ...; For a create( ) with this syntax... ¾ …bean class should have these methods: © 2004-2006 SkillBuilders, Inc. public public PKType PKType ejbCreate( ejbCreate( Arg Arg List List )) public void ejbPostCreate( Arg public void ejbPostCreate( Arg List List )) © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.32 5.32 5.32 ...Handling create(*) Q: What happens when client calls Home#create( )? A: The container performs these steps: 1. Gets a bean class instance from pool 2. Calls ejbCreate( ) method of bean instance 3. 4. 5. 6. 7. Reads mapped fields from bean instance Creates primary key object for this entity Inserts new record in database Associates bean instance with a skeleton Calls ejbPostCreate( ) method of bean instance 8. Returns stub to client Java Training © 2004-2006 SkillBuilders, Inc. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.33 5.33 5.33 ejbCreate( ) / ejbPostCreate( ) ¾ ejbCreate(*): public public PKType PKType ejbCreate( ejbCreate( Arg Arg List List )) Called immediately when client calls matching create( ) ¾ Used like a constructor to initialize data ¾ PK (primary key) not yet assigned; data not yet in table ¾ Always returns null in CMP beans ¾ ¾ Container creates a PK object ¾ ejbPostCreate(*): public public void void ejbPostCreate( ejbPostCreate( Arg Arg List List )) Used for subsequent initialization Data is already in database ¾ PK has been assigned ¾ ¾ ¾ In example in notes CustomerBean has two pair of Java Training methods © 2004-2006 SkillBuilders, Inc. The ejbCreate( ) methods are called by the EJB container when a client calls the matching create( ). In an entity bean, the ejbCreate( ) method returns the primary key type. In container-managed beans, the method will simply return null; in bean-managed beans, it will return an actual instance of the primary key type. The ejbPostCreate( ) method has the same argument list but always returns void. See example on next page... © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.34 Continuing our example, CustomerHome has two create( ) methods: public Customer create() throws ...; public Customer create(String lastName, String firstName) throws ...; So CustomerBean requires two ejbCreate( ) / ejbPostCreate( ) pairs. Note that the return type of ejbCreate( ) is CustomerPK but that the methods return null: import javax.ejb.*; public abstract class CustomerBean implements EntityBean { //================================================ // Methods for create(*) in home interface //================================================ public CustomerPK ejbCreate() { return null; // In CMP, always return null } public CustomerPK ejbCreate(String lastName, String firstName) { setLastName(lastName); setFirstName(firstName); return null; // In CMP, always return null } public void ejbPostCreate() { // Nothing to do... } public void ejbPostCreate(String lastName, String firstName) { // Nothing to do... } // Rest of class... } © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.35 5.35 5.35 Defining CMP Fields ¾ In EJB 1.1: ¾ CMP fields were public instance variables in bean class ¾ In EJB 2.0: ¾ CMP fields represented by abstract get/set methods: public public abstract abstract type type getFieldName( getFieldName( ); ); public abstract void setFieldName( public abstract void setFieldName( type type value value ); ); These methods represent the field type fieldName type must be primitive, Serializable class or an EJBObject ¾ Methods do not have to be remote ¾ ¾ ¾ EJB 2.0 products will allow 1.1 technique ¾ But you must choose at deployment time Java Training © 2004-2006 SkillBuilders, Inc. EJB 2.0 significantly changed how you define CMP fields in an entity bean. Previously, they were represented as public instance variables. The container would access them directly. The standard bean get / set methods were only needed if defined in the remote interface. In EJB 2.0, fields are now represented by standard get / set method pairs, which are abstract. (This is why the bean class must be declared abstract!) The container writes a subclass that implements those methods with persistence logic. Note that a given CMP field method may also serve as a business method if it is also defined in the remote interface. EJB 2.0-compliant products will typically also support the previous CMP technique, but you must inform the container at deployment time so it knows what classes to generate. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.36 Here is part of a CustomerBean class defining three CMP fields: ¾ int id ¾ String lastName ¾ String firstName public abstract class CustomerBean implements EntityBean { // For CMP field int id. Notice that only the get method // is defined in the remote interface: public abstract int getId(); // A business method. public abstract void setId(int value); // Not a business method. // For CMP field String lastName property: public abstract String getLastName(); public abstract void setLastName(String value); // For CMP field String firstName property: public abstract String getFirstName(); public abstract void setFirstName(String value); // This method is for the remote interface. // Notice it uses the methods defined above: public String getFullName() { return getFirstName() + " " + getLastName(); } // Rest of class... } © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.37 5.37 5.37 The EntityBean Interface ¾ The bean class must implement EntityBean ¾ Interface in javax.ejb ¾ EntityBean is similar to SessionBean: ¾ Extends EnterpriseBean Defines bean life cycle methods, called by container ¾ Bean can respond or do nothing ¾ See notes for complete listing… ¾ ¾ We will cover EntityBean in detail later... ¾ For now, we will leave the methods empty Java Training © 2004-2006 SkillBuilders, Inc. The entity bean class must implement the EntityBean interface in javax.ejb. Like SessionBean, this interface defines all classes that represent entity bean implementations. It extends javax.ejb.EnterpriseBean, which defines all enterprise beans. (Recall that the latter is a "marker" interface, i.e. one without methods.) EntityBean has seven lifecycle methods (called by container at key points in the bean's lifecycle) which the bean class must implement. As with SessionBean, we'll cover the methods of this interface in detail later; for now we will leave them empty. The complete listing is on the next page: © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.38 Here is the complete listing of the EntityBean interface: public abstract interface EntityBean extends EnterpriseBean, java.io.Serializable { public abstract void ejbLoad( ) throws EJBException, java.rmi.RemoteException; public abstract void ejbStore( ) throws EJBException, java.rmi.RemoteException; public abstract void ejbActivate( ) throws EJBException, java.rmi.RemoteException; public abstract void ejbPassivate( ) throws EJBException, java.rmi.RemoteException; public abstract void ejbRemove( ) throws RemoveException, EJBException, java.rmi.RemoteException; public abstract void setEntityContext(EntityContext ctxt) throws EJBException, java.rmi.RemoteException; public abstract void unsetEntityContext( ) throws EJBException, java.rmi.RemoteException; } © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.39 5.39 5.39 Where We've Been ¾ Entity beans: Represent business objects ¾ Are always stateful ¾ Are usually persistent ¾ ¾ Persistence can be handled by: ¾ ¾ The container The bean ¾ The parts of a bean: Remote interface ¾ Primary key (PK) ¾ Home interface ¾ Bean class ¾ Java Training © 2004-2006 SkillBuilders, Inc. © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.40 5.40 5.40 Entity Bean Workshop ¾ Writing a Container-Managed Entity Bean Java Training © 2004-2006 SkillBuilders, Inc. Your Objective In this exercise you will write an EJB 2.0 container-managed entity bean for accounts and have the bank manipulate it. In this lab you will write the bean and modify other server and client code to use it. In the next lab you will deploy the bean. A. Write the Account Bean You will write three parts of an Account entity bean: remote interface, home interface and bean class. You will write the first two from scratch; the third has been started for you. Note: Consult the JavaDoc on account.* for a full description of the necessary methods. Create an account Package Locate the directory labs\account. directory. You will build your Account EJB in this Continues… © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.41 Write the Remote Interface Write an Account interface that has the following characteristics: 1. A read-only String attribute called number. 2. A read-only float attribute called balance. 3. A read/write String attribute called description. 4. Two methods for moving money: public float credit( float amount ) public float debit( float amount ) This will make a total of six methods. Note: The primary key for this entity bean will be the number attribute by itself. Therefore you do not need to write a special primary key class. Rather, you will use java.lang.String as primary key class. Write the Home Interface Write an AccountHome interface. Give it a create( ) method that takes a float argument for opening balance and a String argument for description. Also give it an appropriate findByPrimaryKey( ) method. Write the AccountBean Class Write an AccountBean class that fulfills the requirements for a container-managed entity bean. Do not start from scratch; rather, copy the file AccountBean.java from the labs\initial\account directory to labs\account. 1. Complete the methods for the three data members. 2. Implement the credit( ) and debit( ) methods in the standard way (add to / subtract from the balance). 3. Give it the requisite methods for the home interface. For ejbCreate( ), use the IdGenerator to get the next ID, like so: int iAcctNum = (int) _igAcctNum.getNextId(); String strAcctNum = iAcctNum + ""; 4. Give it the methods needed to fulfill the EntityBean interface. 5. Declare a private instance variable for the EntityContext and initialize it as you did for the bank bean. Continues… © 2004-2006 SkillBuilders, Inc. V3.1 Java Training: Entity Beans 5.42 Compile Compile everything by running ant compile B. Modify Bank Modify your BankBean class to use the new account bean in place of the dummy account class: 1. Give BankBean an instance variable for an AccountHome object. 2. In the ejbCreate( ) method, look up the AccountHome and initialize the variable. Use the same technique you used in the client application. (Since the two beans are in the same server, you can use an empty InitialContext object.) Choose a JNDI name such as MyAccount (you will assign that name when you deploy the bean). Trap any exception and throw a CreateException. 3. In the createAccount( ) method, use AccountHome#create( ) with the chosen JNDI name. If an error occurs, throw a CreateException. 4. In setCurrentAccount(), use AccountHome#findByPrimaryKey(). If an error occurs, throw a FinderException. 5. In closeCurrentAccount( ), use Account#remove( ). If an error occurs, throw a RemoveException. 6. In the other bank business methods, use the appropriate methods of Account. Most of these should be identical to the methods of the dummy Account class you used before, except that the new Account methods now throw RemoteException. Do not trap this exception, simply allow the BankBean methods to throw it. 7. Save and recompile (ant compile) © 2004-2006 SkillBuilders, Inc. V3.1