Download 5. Entity Beans

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Database model wikipedia , lookup

Object-relational impedance mismatch wikipedia , lookup

Transcript
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