Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Mastering Enterprise JavaBeans™ and the Java 2 Platform, Enterprise Edition - Roman E

..pdf
Скачиваний:
41
Добавлен:
24.05.2014
Размер:
6.28 Mб
Скачать

METHOD

EXPLANATION

ejbPostCreate(<…>)

There is one ejbPostCreate(...)

 

for each ejbCreate(...). Each

(new for container-

pair has the same parameters.

managed persistence)

 

 

The container calls your bean

 

instance’s ejbPostCreate(...)

 

method following ejbCreate(...).

TYPICAL IMPLEMENTATION

The container calls ejbPostCreate() after it has associated your bean instance with an EJB object. You can now complete your initialization, by doing anything you need to that requires that EJB object, such as passing your bean’s EJB object reference to other beans.

You might also use this method to reset certain transactionrelated parameters—for example, you could keep a data status flag in the bean to indicate whether a field has been changed. Because the bean instance may have been used before, these fields might have dirty data.

 

 

Note: By now the EJB container

 

 

will have created your primary

 

 

key object, so you can now

 

 

retrieve it and use it.

ejbActivate()

When a client calls a business

Acquire any bean-specific

 

method on an EJB object, but

resources, such as socket

(same as bean-

there is no entity bean instance

connections, that your bean

managed persistence)

bound to the EJB object, the

needs to service a particular

 

container needs to take a bean

client when it’s moved into the

 

from the pool and transition it

ready state.

 

into a ready state. This is called

 

 

activation. On activation, the

 

 

ejbActivate() method is called

 

 

by the EJB container.

 

 

Note: ejbActivate() is never

 

 

called during a transaction.

 

ejbLoad()

The EJB container calls this to

Do not read data from the

 

load database data into your

database in this method. Rather,

(new for container-

bean instance, based on the

the EJB container will read in

Managed Persistence)

current transactional state.

data from the database for you

 

 

automatically right before calling

 

 

your ejbLoad() method. It does

 

 

this by setting your container-

 

 

managed fields to the data it

 

 

reads from the database.

 

 

In this method, you should per-

 

 

form any utilities you need to

 

 

work with the read-in data, such

 

 

as decompressing a text field.

 

 

continues

239

240 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

Table 9.1 (Continued)

METHOD

EXPLANATION

ejbStore()

The EJB container calls this to

 

update the database to the

(new for container-

new values of your in-memory

managed persistence)

fields, thus synchronizing the

 

database. The current transac-

 

tional state dictates when this

 

method is called. Also, this

 

method is called during passiv-

 

ation, directly before

 

ejbPassivate().

TYPICAL IMPLEMENTATION

Do not update the database in this method. Rather, the EJB container will update the database for you automatically right after calling your ejbStore() method. It does this by extracting your container-managed fields and writing them to the database.

In this method, you should prepare your container-managed fields to be written to the database. For example, you can compress the text of your fields if necessary.

ejbPassivate()

The EJB container will call this

Release any resources, such as

 

method when it wants to return

socket connections, that you

(same as bean-

your entity bean to the pool.

allocated in ejbActivate() and

managed persistence)

This is called passivation and

that your bean was holding

 

is the opposite of activation. On

during the ready state for a

 

passivation, the ejbPassivate()

particular client.

 

method is called by the EJB

 

 

container.

 

 

Note: ejbPassivate() is never

 

 

called during a transaction.

 

ejbRemove()

The client calls the home

Do not destroy database data in

 

object’s remove() method to

this method. Rather, simply

(new for container-

destroy database data

perform any operations that

managed persistence)

remove(), which then calls

must be done before the data in

 

your ejbRemove(). Note that

the database is destroyed. The

 

this does not destroy the Java

EJB container will destroy the

 

Object because the object can

data for you right after

 

be pooled and reused for

ejbRemove() is called.

 

different data.

 

unsetEntityContext()

This method disassociates a

 

bean from its environment.

(same as bean-

The container calls this right

managed persistence)

before your entity bean

 

instance is destroyed (when it

 

wants to reduce the pool size).

Release any resources you allocated during setEntityContext(), and get ready to be garbage collected.

Go back to the first page for a quick link to buy this book online!

Writing Container-Managed Persistent Entity Beans 241

Container-Managed Persistence Example:

A Product Line

Let’s see a quick demonstration of container-managed persistence in action, applied to the concept of a product line.

If you’re working for a product-based company, your company’s product line is the suite of products your company offers. For example, if you’re an appliance company, you might offer a dishwasher, a stove, and a dryer. If you’re a computer hardware company, you might offer memory, hard disks, and processors. We’re going to model a generic product as an entity bean that uses containermanaged persistence.

The object model for our product line is detailed in Figure 9.1.

 

<<interface>>

 

<<interface>>

 

 

java.rmi.Remote

 

java.io.Serializable

 

 

 

Comes with Java 2 platform

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

<<interface>>

javax.ejb.EnterpriseBean

<<interface>> <<interface>> javax.ejb.EJBObject javax.ejb.EJBHome

<<interface>>

javax.ejb.EntityBean

Comes with EJB distribution

<<interface>>

 

<<interface>>

 

Product Bean

 

Product

Product

 

Product

 

Implementation

 

 

 

 

Primary Key Class

Remote Interface

 

Home Interface

 

Class

 

 

 

 

 

 

 

 

 

 

 

 

Suppplied by Bean provider (we will write)

Product

 

Product

EJB Object

 

Home Object

 

 

 

Generated for us by container vendor's tools

Figure 9.1 The object model for our product line.

Go back to the first page for a quick link to buy this book online!

242 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

Let’s take a look at each of the files that we must create for our entity bean component.

Product.java

Our remote interface is specified by Product.java, shown in Source 9.1.

Our remote interface is very similar to Chapter 8’s bank account remote interface. It has methods to modify the entity bean instance’s fields and throws remote exceptions to indicate system-level errors.

ProductHome.java

Next, we have the product’s home interface, ProductHome.java, presented in Source 9.2.

package com.wiley.compBooks.roman.entity.product;

import javax.ejb.*;

import java.rmi.RemoteException;

/**

*These are the public business methods of ProductBean.

*This interface is what clients operate on when they

*interact with beans. The EJB Server vendor will

*implement this interface; the implemented object instance

*is called the EJB Object, which delegates invocations to

*instances of the ProductBean class.

*/

public interface Product extends EJBObject {

// Getter/setter methods for Entity Bean fields

public String getName() throws RemoteException;

public void setName(String name) throws RemoteException;

public String getDescription() throws RemoteException;

public void setDescription(String description) throws RemoteException;

public double getBasePrice() throws RemoteException;

public void setBasePrice(double price) throws RemoteException;

public String getProductID() throws RemoteException;

}

Source 9.1 Product.java.

Go back to the first page for a quick link to buy this book online!

Writing Container-Managed Persistent Entity Beans 243

package com.wiley.compBooks.roman.entity.product;

import javax.ejb.*;

import java.rmi.RemoteException; import java.util.Enumeration;

/**

*This is the home interface for Product. This interface

*is implemented by the EJB Server's glue-code tools.

*The implemented object is called the Home Object and

*serves as a factory for EJB Objects.

*

*One create() method is in this Home Interface, which

*corresponds to the ejbCreate() method in the Product file. */

public interface ProductHome extends EJBHome {

/*

*This method creates the EJB Object.

*Notice that the Home Interface returns an EJB Object,

*whereas the Bean returns void. This is because the

*EJB Container is responsible for generating the EJB

*Object, whereas the Bean is responsible for

*initialization.

*

*@param productID The number of the product (unique)

*@param name The name of the product

*@param description Product description

*@param basePrice Base Price of product

*

* @return The newly created EJB Object. */

Product create(String productID, String name, String description, double basePrice) throws CreateException, RemoteException;

//Finder methods. These are implemented by the

//container. You can customize the functionality of

//these methods by using the EJB Container tools.

public Product findByPrimaryKey(ProductPK key) throws FinderException, RemoteException;

public Enumeration findByName(String name) throws FinderException, RemoteException;

public Enumeration findByDescription(String description) throws FinderException, RemoteException;

Source 9.2 ProductHome.java (continues).

Go back to the first page for a quick link to buy this book online!

244 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

public Enumeration findByBasePrice(double basePrice) throws FinderException, RemoteException;

public Enumeration findExpensiveProducts(double minPrice) throws FinderException, RemoteException;

public Enumeration findCheapProducts(double maxPrice) throws FinderException, RemoteException;

public Enumeration findAllProducts() throws FinderException, RemoteException;

}

Source 9.2 ProductHome.java (continued).

Our home interface defines a single create() method to create a new product in the database. It returns a Product EJB object so the client can manipulate the entity bean data and throws a javax.ejb.CreateException to indicate an appli- cation-level problem.

We also expose all sorts of finder methods to find existing products. Some of the finders return a single EJB object, while others return a java.util.Enumeration of multiple EJB objects. This is needed if the finder methods find more than one matching object. Note that findByPrimaryKey() should never return an enumeration because primary keys must be unique.

ProductPK.java

Our primary key class is defined by ProductPK.java, shown in Source 9.3.

As with our Bank Account, our primary key is a simple string. And as we’ve found out, there are restrictions for what our primary key can be. Our primary key fields are coming from the container-managed fields of the entity bean class, as is required with container-managed persistence. In particular, our primary key represents the ID string of a product (such as a product SKU number).

ProductBean.java

Next, we have our container-managed entity bean implementation, ProductBean

.java, shown in Source 9.4.

This bean is more complex than our bank account example. We’ve defined many finder methods, and we have four persistent fields. Yet even though we’ve added all this complexity, our bean is less than 40 percent of the size of our Bank Account

Go back to the first page for a quick link to buy this book online!

Writing Container-Managed Persistent Entity Beans 245

package com.wiley.compBooks.roman.entity.product;

import java.io.Serializable;

/**

*Primary Key class for our 'Product' Container-Managed

*Entity Bean

*/

public class ProductPK implements java.io.Serializable {

/*

*Note that the primary key fields must be a

*subset of the the container-managed Bean fields.

*The fields we are marking as container-managed in

*our Bean are productID, name, desc, and basePrice.

*Therefore our PK fields need to be from that set.

*/

public String productID;

public ProductPK(String productID) { this.productID = productID;

}

public ProductPK() {

}

public String toString() { return productID.toString();

}

}

Source 9.3 ProductPK.java.

bean. This is an amazing reduction in code complexity. And because our bean has no database code in it, we have reduced the chance for bugs in our bean that would be due to user error working with JDBC code. This is a huge savings in development and testing time.

We have four container-managed fields, all with public scope. They’re public so that the container can manipulate them. Our ejbCreate() method simply sets our container-managed fields to the passed-in client parameters. The EJB container will extract those fields and set up the database data for us. Notice that our ejbCreate() method does not return a primary key because the EJB container does that for us.

The rest of our bean is just empty methods and comments. There’s almost no logic at all. Our bean class is just data with some accessor methods.

Go back to the first page for a quick link to buy this book online!

246 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

package com.wiley.compBooks.roman.entity.product;

import java.sql.*; import javax.naming.*; import javax.ejb.*; import java.util.*;

import java.rmi.RemoteException;

/**

*Entity Bean that demonstrates Container-Managed persistence.

*This is a product that's persistent. It has an ID #, a name,

*a description, and a base price.

*/

public class ProductBean implements EntityBean {

protected EntityContext ctx;

//Container-managed state fields. Note that they must

//be public.

public String

productID;

// PK

public

String

name;

 

public

String

description;

 

public double basePrice;

public ProductBean() {

System.out.println("New Product Entity Bean Java Object created by EJB Container.");

}

//

//Business Logic Methods

//Simple getter/setter methods of Entity Bean fields.

public String getName() throws RemoteException { System.out.println("getName() called."); return name;

}

public void setName(String name) throws RemoteException { System.out.println("getName() called.");

this.name = name;

}

public String getDescription() throws RemoteException { System.out.println("getDescription() called.");

Source 9.4 ProductBean.java (continues).

Go back to the first page for a quick link to buy this book online!

Writing Container-Managed Persistent Entity Beans 247

return description;

}

public void setDescription(String description) throws RemoteException { System.out.println("setDescription() called.");

this.description = description;

}

public double getBasePrice() throws RemoteException { System.out.println("getBasePrice() called."); return basePrice;

}

public void setBasePrice(double price) throws RemoteException { System.out.println("setBasePrice() called."); this.basePrice = price;

}

public String getProductID() { System.out.println("getProductID() called."); return productID;

}

//

// EJB-required methods

//

/**

*Called by Container.

*Implementation can acquire needed resources.

*/

public void ejbActivate() throws RemoteException { System.out.println("ejbActivate() called.");

}

/**

*EJB Container calls this method right before it

*removes the Entity Bean from the database.

*Corresponds to when client calls home.remove().

*/

public void ejbRemove() throws RemoteException { System.out.println("ejbRemove() called.");

}

/**

*Called by Container.

*Releases held resources for passivation.

*/

Source 9.4 ProductBean.java (continues).

Go back to the first page for a quick link to buy this book online!

248 M A S T E R I N G E N T E R P R I S E J A V A B E A N S

public void ejbPassivate() throws RemoteException { System.out.println("ejbPassivate () called.");

}

/**

*Called from the Container. Updates the entity bean

*instance to reflect the current value stored in

*the database.

*Because we're using Container-Managed Persistence, we

*can leave this method blank. The EJB Container will

*automatically set our public fields to the correct values.

*/

public void ejbLoad() throws RemoteException { System.out.println("ejbLoad() called.");

}

/**

*Called from the Container. Updates the database to

*reflect the current values of this in-memory Entity Bean

*instance representation.

*Because we're using Container-Managed Persistence, we can

*leave this method blank. The EJB Container will

*automatically save our public fields into the database.

*/

public void ejbStore() throws RemoteException {

System.out.println("ejbStore() called.");

}

/**

*Called by Container. Associates this Bean instance with

*a particular context. Once done, we can query the

*Context for environment info, such as Bean customizations

*via properties.

*/

public void setEntityContext(EntityContext ctx) throws RemoteException { System.out.println("setEntityContext called");

this.ctx = ctx;

}

/**

*Called by Container. Disassociates this Bean instance

*with a particular context environment.

*/

public void unsetEntityContext() throws RemoteException {

Source 9.4 ProductBean.java (continues).

Go back to the first page for a quick link to buy this book online!