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

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

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

Writing Bean-Managed Persistent Entity Beans 229

else {

throw new Exception("Could not find account");

}

/*

* Call the balance() method, and print it */

System.out.println("Initial Balance = " + account.getBalance());

/*

* Deposit $100 into the account */

account.deposit(100);

/*

* Retrieve the resulting balance. */

System.out.println("After depositing 100, account balance = " + account.getBalance());

/*

* Retrieve the Primary Key from the EJB Object */

AccountPK pk = (AccountPK) account.getPrimaryKey();

/*

*Release our old EJB Object reference. Now call

*find() again, this time querying on Account ID

*(i.e. the Primary Key).

*/

account = null;

account = home.findByPrimaryKey(pk);

/*

* Print out current balance */

System.out.println("Found account with ID " + pk + ". Balance = " + account.getBalance());

/*

* Try to withdraw $150 */

System.out.println(

"Now trying to withdraw $150, which is more than is " + “currently available. This should generate an exception..");

account.withdraw(150);

}

catch (Exception e) {

Source 8.6 Client.java (continues).

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

230 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

System.out.println("Caught exception!"); e.printStackTrace();

}

finally { /*

* Destroy the Entity permanently */

try {

System.out.println("Destroying account.."); if (account != null) {

account.remove();

}

}

catch (Exception e) { e.printStackTrace();

}

}

}

}

Source 8.6 Client.java (continued).

The Deployment Descriptor

Now, let’s take a look at our deployment descriptor. The deployment descriptors for entity beans are slightly different from those for their sister session beans. Our deployment descriptor is shown in Table 8.2.

Table 8.2 Deployment Descriptor Settings for AccountBean

DEPLOYMENT

DESCRIPTOR SETTING

VALUE

Bean home name

AccountHome

Enterprise bean class name

com.wiley.compBooks.roman.entity.account.AccountBean

Home interface class name

com.wiley.compBooks.roman.entity.account.AccountHome

Remote interface class name

com.wiley.compBooks.roman.entity.account.Account

Environment properties

see Table 8.3.

Re-entrant

false

Primary key class name

com.wiley.compBooks.roman.entity.account.AccountPK

Container-managed fields

<empty>

 

 

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

Writing Bean-Managed Persistent Entity Beans 231

Table 8.2 illustrates a typical deployment descriptor for a bean-managed persistent entity bean. Notice that we have two new fields that we do not have for session beans:

The primary key class name identifies the Java class for our primary key. Session beans do not have primary keys because they are not persistent.

The container-managed fields entry specifies what fields of your entity bean class are persistent fields. This applies only to container-managed persistent entity beans (described in Chapter 9), and it should be left blank when using bean-managed persistence.

Environment Properties

Next, we have our bean’s custom environment properties. These environment properties allow consumers of your bean to tune your bean’s functionality without touching your bean’s source code (shown originally in Chapter 6). Our bean class retrieves these properties via EntityContext.getEnvironment(). The properties are shown in Table 8.3.

Notice that we’re using enterprise bean environment properties to specify JDBC initialization information. This enables a consumer of our bean to use the database of his or her choice without modifying our bean code. The particular JDBC settings you use will vary depending on your configuration. Consult your database documentation or JDBC driver documentation for more details.

The JDBC_URL setting is passed to the DriverManager to locate the proper database. The jdbc.drivers setting is passed to the DriverManager to locate the proper JDBC driver.

Setting Up the Database

Lastly, you need to create the appropriate database table and columns for our bank accounts. You can do this through your database’s GUI or command-line interface. The book’s included CD-ROM comes with a preconfigured sample database that you can use right away. If you’re using a different database, you

Table 8.3 Environment Properties for AccountBean

ENVIRONMENT

PROPERTY SETTING

VALUE

jdbc.drivers

Your database’s JDBC driver goes here. For example:

 

“com.sun.jdbc.odbc.JdbcOdbcDriver.”

JDBC_URL

Your database’s JDBC URL goes here. For example:

 

“jdbc:odbc:ejbdatabase.”

 

 

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

232 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

should enter the following SQL Data Definition Language (DDL) statements in your database’s SQL interface:

drop table accounts;

create table accounts (id varchar(64), ownername varchar(64), balance

numeric(18));

This creates an empty table of bank accounts. The first column is the bank account id (the primary key), the second column is the bank account owner’s name, and the third column is the bank account balance.

Running the Client Program

To run the client program, type a command similar to the following (depending on what your EJB container’s Java Naming and Directory Interface (JNDI) connection parameters are—see your container’s documentation):

java

-Djava.naming.factory.initial=weblogic.jndi.TengahInitialContextFactory

-Djava.naming.provider.url=t3://localhost:7001

com.wiley.compBooks.entity.Account.Client

The initialization parameters are required by JNDI to find the home object, as we learned in Chapter 4.

Server-Side Output

When you run the client, you should see something similar to the following on the server side. Note that your particular output may vary, due to variances in EJB container behavior.

New Bank Account Entity Bean Java Object created by EJB Container. setEntityContext called

ejbCreate() called.

New Bank Account Entity Bean Java Object created by EJB Container. setEntityContext called

ejbFindByOwnerName(John Smith) called ejbLoad() called.

getBalance() called. ejbStore() called. ejbLoad() called. deposit(100.0) called. ejbStore() called. ejbLoad() called. getBalance() called.

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

Writing Bean-Managed Persistent Entity Beans 233

ejbStore() called. ejbLoad() called. getBalance() called. ejbStore() called. ejbLoad() called. withdraw(150.0) called. ejbRemove() called.

Notice what’s happening here:

■■When our client code called create() on the home object, the container created an entity bean instance. The container first called newInstance() and setEntityContext() to get the entity bean into the available pool of entity beans. The container then serviced our client’s create() method by taking that bean out of the pool. It called the bean instance’s ejbCreate() method, which created some new database data, and returned control back to the container. Finally, the container associated the bean instance with a new EJB object and returned that EJB object to the client.

■■To service our finder method, the container instantiated another entity bean. The container called newInstance() and then setEntityContext() to get that new bean instance into the available pool of entity beans. It then used the bean in the pool to service our finder method. Note that the bean instance is still in the pool and could service any number of finder methods.

■■In addition to the methods that the client calls, our EJB container interleaved a few ejbStore() and ejbLoad() calls to keep the database in synch.

Testing JDBC Database Work

Probably the most frustrating part of an application is doing the database work. Often you will have punctuation errors or misspellings, which are tough to debug when performing JDBC. This is because your JDBC queries are not compiled—they are interpreted at runtime, so you don’t get the nifty things like type checking that the Java language gives you. You are basically at the mercy of the JDBC driver. It may or may not give you useful feedback.

You might consider using SQL/J instead of JDBC. SQL/J precompiles your SQL code, and you don’t have to write all the prepares and JDBC connection code—you just write embedded SQL code. SQL/J is available with Oracle Corporation’s Oracle database and with IBM’s DB2 database.

When performing any kind of database work, the best way to debug is to set up a simple test database. If your queries are not functioning properly, try duplicating and running them against your database using your database’s direct interface. This should help you track down your database problems much more quickly.

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

234 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

Client-Side Output

Running the client program yields the following client-side output:

Initial Balance = 0.0

After depositing 100, account balance = 100.0

Found account with ID 123-456-7890. Balance = 100.0

Now trying to withdraw $150, which is more than is currently available. This should generate an exception..

Caught exception! com.wiley.compBooks.roman.entity.account.AccountException: Your balance is 100.0! You cannot withdraw 150.0!

Destroying account..

We created an entity bean, deposited into it, and tried to withdraw more than we had. The entity bean correctly threw an application-level exception back to us indicating that our balance had insufficient funds.

Summary

In this chapter, you’ve seen how to write bean-managed persistent entity beans. Bean-managed persistent entity beans are useful if you need to control the underlying database operations yourself. EJB’s real advantage comes from containermanaged persistent entity beans. Container-managed persistent entity beans can be developed much more rapidly because the container handles all data access logic for you. The next chapter covers container-managed persistence.

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

C H A P T E R9

Writing Container-Managed

Persistent Entity Beans

n Chapter 8, we wrote a bean-managed persistent entity bean representing a Ibank account. In this chapter, we’ll see how things change when we move to a container-managed model. With container-managed persistence, you don’t implement any persistence logic in the entity bean itself—rather, the EJB container performs storage operations for you. As you will see, this greatly simplifies bean

development.

Before reading this chapter, you should be familiar with the entity bean concepts we covered in Chapter 7.

Container-Managed Fields

A container-managed persistent entity bean allows the container to handle some or all of its data access logic. Rather than coding JDBC or SQL/J operations in your bean class, your container implicitly performs all database operations behind the scenes.

With container-managed persistence, you must make some of your entity bean class’s fields public so that the container can set the fields when it performs database operations on behalf of your bean. The fields that you want to be persistent are called container-managed fields. You don’t have to worry about setting these fields—the EJB container will automatically manipulate them for you behind the scenes when it performs storage operations.

One restriction of container-managed fields is that every field you want to be managed by the container must follow the rules for Java object serialization (we

235

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

236 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

describe these rules in full in Appendix A). This means that primitive types such as doubles and Booleans, as well as serializable classes such as primary key classes or EJB handles to other entity beans, can be container-managed fields.

For example, the following is a snippet of code from our bank account entity bean class that we wrote in Chapter 8:

public class AccountBean implements EntityBean { public String accountID; // PK

public String ownerName; public double balance;

...

}

With container-managed persistence, the container can persist each of these fields for you behind the scenes. When saving your bean instance’s fields, the container is responsible for querying your bean instance for these field values. When loading data into your bean instance, the container sets these fields. This is possible because each of the fields is declared as public.

Of course, you still must inform the container about which fields it should manipulate. You specify this in your bean’s deployment descriptor. The EJB container will inspect the deployment descriptor to figure out which of your entity bean’s fields to manipulate.

Note that not all fields within the bean have to be managed by the container. You might be pulling data manually from a secondary source, or you might have calculated fields. The EJB container will automatically notify your bean class during persistent operations, allowing you to manage these fields.

Primary Key Class

As with bean-managed persistence, container-managed persistence dictates that your primary key class must be serializable. Because the EJB container will work with your primary key, there are new restrictions for how you write your primary key class. The most important restriction is that the fields you have in your primary key must come from the container-managed fields of your entity bean, which we described previously. This restriction allows the EJB container to set, as well as extract, your entity bean’s primary key fields.

For example, take our primary key class from our Chapter 8’s bank account:

public class AccountPK implements java.io.Serializable {

public String accountID;

...

}

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

Writing Container-Managed Persistent Entity Beans 237

This is a valid primary key class for container-managed persistence because it’s serializable and because its public fields come from our bean class’s containermanaged fields.

Implementation Guidelines for Container-Managed Persistence

The method implementations of your entity beans should be different for con- tainer-managed persistent entities. No longer are you controlling the routine persistent operations of your beans, and so many of the methods can be left empty—the container will do it for you. Table 9.1 is a summary of what you should implement in each method, assuming your entity bean’s persistence is container managed. Take a quick glance at the chart for now. As you can see from the table, many of the database-intensive operations have been reduced in scope significantly. You should refer back to the chart when reading through the code in this chapter or when programming your own entity bean classes. The order of methods listed very roughly models the flow of control of an entity bean instance’s life cycle that we saw at the end of Chapter 7.

Table 9.1 Descriptions and Implementation Guidelines for Container-Managed Persistent Entities

METHOD

EXPLANATION

setEntityContext()

If the container wants to

 

increase its pool size of bean

(same as bean-

instances, it will instantiate a

managed persistence)

new entity bean instance.

 

Following this, the container

 

calls the instance’s

 

setEntityContext(). This

 

method associates a bean

 

with context information

 

information about the bean’s

 

environment. Once this method

 

is called, the bean can access

 

information about its

 

environment.

TYPICAL IMPLEMENTATION

Stick the entity context somewhere, such as in a member variable. You can then access the context later to acquire environment information, such as security information, from the container.

You should also request any resources your instance will need regardless of what data the bean represents.

The bean is now in a pool, does not have any specific database data inside of it, and is not bound to any particular EJB object.

continues

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

Table 9.1 (Continued)

METHOD

EXPLANATION

TYPICAL IMPLEMENTATION

ejbFind<…>(<…>) You do not write finder methods for container-managed beans.

(new for containerThe EJB container will handle managed persistence) all issues relating to finding data

for you. But how does the EJB container know what kinds of finder methods you want in your bean? After all, there are an infinite variety of ways to find data in a database. The answer is that your EJB container ships with tools for this purpose. You use the container tools to tell the container what logic to execute when the client performs a finder method on the home object. You’ll see how BEA’s WebLogic does this in the next example.

You should not implement these methods for container-managed persistent entity beans.

ejbCreate(<…>)

(new for containermanaged persistence)

Note: You do not need to write any ejbCreate() methods if you don’t want EJB clients to be able to create new database data. Some systems may allow creation of data to occur via direct database inserts, through batch files or other means.

When a client calls create() on a home object, the container then calls ejbCreate() on a pooled bean instance. ejbCreate() methods are responsible for creating new database data and initializing your bean.

Do not create database data in this method. Rather, simply check that the client parameters are correct, and set your container-managed fields to the parameters passed in. After the EJB container calls your ejbCreate() method, it will extract the container-managed fields from your bean and create the database representation of the data for you.

If you’ll recall, with bean-managed persistence, your ejbCreate() method returns a primary key class to the container. With container-managed persistence, you don’t need to return a primary key class. The EJB container can simply extract data from your public fields and create a primary key object by itself.

Your entity bean instance is then no longer in the pool—it now has specific database data inside it.

The container will bind your instance to a particular EJB objects.

238