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

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

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

198 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

Relationship between remove() and ejbRemove(). Note that remove() can be called on either the home object or the EJB object.

[Diagram happens to assume bean-managed persistence]

EJB Container/Server

 

 

 

 

 

Home Object

 

 

 

 

 

 

 

 

1: remove()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2: ejbRemove()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Client Code

 

 

 

 

 

 

 

 

 

 

Entity Bean

 

 

 

 

 

 

 

 

 

 

 

Instance

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1: remove()

 

 

 

 

 

 

 

 

 

 

 

 

 

EJB Object

 

2: ejbRemove()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3: Remove database data

entity bean data

Database

Figure 7.6 Destroying an entity bean’s data representation.

For session beans, this context’s interface is javax.ejb.SessionContext. For entity beans, the interface is javax.ejb.EntityContext. Both session contexts and entity contexts extend the more generic javax.ejb.EJBContext interface.

We provide a refresher of the javax.ejb.EJBContext methods in Source 7.3. Table 7.1 explains the meaning of each method.

Entity contexts add two new methods on top of the generic EJB context, shown in Source 7.4.

Let’s look at each of these methods in more detail.

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

Introduction to Entity Beans 199

public interface javax.ejb.EJBContext {

public abstract javax.ejb.EJBHome getEJBHome(); public abstract java.util.Properties getEnvironment();

public abstract java.security.Identity getCallerIdentity(); public abstract boolean isCallerInRole(java.security.Identity); public abstract javax.jts.UserTransaction getUserTransaction(); public abstract void setRollbackOnly();

public abstract boolean getRollbackOnly();

}

Source 7.3 The javax.ejb.EJBContext interface.

getEJBObject()

Call this to retrieve the current, client-specific EJB object that is associated with the entity bean. Remember that clients invoke on EJB objects, not on entity beans directly. Therefore you can use the returned EJB object as a way to pass a reference to yourself, simulating the this argument in Java. getEJBObject() has the same functionality as session beans.

getPrimaryKey()

getPrimaryKey() is new to entity beans. It retrieves the primary key that is currently associated with this entity bean instance. Primary keys uniquely identify an entity bean. When an entity bean is persisted in storage, the primary key can be used to uniquely retrieve the entity bean because you can never have two entity bean database data instances that have the same primary key.

Why would you ever want to call getPrimaryKey()? You’d call it whenever you want to figure out with which database data your instance is associated. Remember that entity bean instances can be reused and pooled, as we saw in Figure 7.3. When the container wants to switch an entity bean instance from one data instance to another, the container needs to passivate and activate that entity bean instance. When this happens, your bean instance may switch to a different data instance and thus a different primary key. But your entity bean instance is never told this explicitly when it’s activated. Rather, your entity bean must perform a getPrimaryKey() callback to the entity context to figure out what data it should be dealing with.

Thus, when you have an entity bean that’s performing any persistent work (with bean-managed persistence), you should be calling getPrimaryKey() whenever you need to figure out what data you’re bean is associated with. This is very useful, for example, in the following methods:

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

200 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 7.1 The javax.ejb.EJBContext Interface’s Methods

METHOD

DESCRI PTION

getHome()

Returns a reference to the

 

home object for that enterprise

 

bean’s class.

USEFULNESS

Useful if your bean needs to access its own home object factory. You can use the home object to create, destroy, or find EJB objects.

getEnvironment()

Returns a list of environment

 

properties that were deployed

 

with the bean. These properties

 

can be used to set arbitrary

 

information that a bean may

 

need, such as locations of files.

getEnvironment() is useful when you deploy your beans with environment properties, and you need to access those environment properties.

getCallerIdentity()

Returns the identity of the client

 

that is invoking methods on the

 

bean instance’s EJB object.

Useful for getting the caller’s identity. You can use this identity for many things. For example, you can retrieve the caller’s distinguished name and use it as a key to information in a database.

isCallerInRole()

Tests if a bean’s client is in a

This method is useful for query-

 

particular security role.

ing whether the authenticated

 

 

client is authorized to perform an

 

 

operation. It relies on the concept

 

 

of a security role, which is a

 

 

group authorized to perform cer-

 

 

tain operations. Note that this

 

 

method is useful for authoriza-

 

 

tion, which is entirely different

 

 

from authentication. Authentica-

 

 

tion verifies that the client is who

 

 

he or she claims to be. This must

 

 

be performed sometime before

 

 

this method is called—such as

 

 

when the client gets his or her

 

 

identity. If the client has an iden-

 

 

tity, then it has been

authenticated.

 

 

setRollbackOnly()

Allows the instance to mark

Useful for forcing a transaction to

 

the current transaction such

abort and roll back.

 

that the only outcome of the

 

 

transaction is a rollback.

 

getRollbackOnly()

Returns a Boolean indicating

 

whether the current transaction

 

has been marked for rollback.

This method will tell you if the current transaction is going to abort. If it’s going to abort, you may be able to bypass logic in your bean, saving valuable computation time.

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

Introduction to Entity Beans 201

Table 7.1 (Continued)

METHOD

getUserTransaction()

Note: This method is supported only if the bean performs its own transactions and is hence deployed with the TX_BEAN_MANAGED transaction attribute. See Chapter 10 for more details on this method.

DESCRI PTION

Returns the javax.transaction

.UserTransaction interface that the bean can use for explicit transaction demarcation.

USEFULNESS

Use this method if you want to perform your own transactions programmatically in your bean.

For some beans, the transparent, automatic transactions that EJB containers offer may be insufficient. This method allows you to control the transaction explicitly yourself.

Once you call this method, your bean can demarcate transactional boundaries using the returned javax.transaction.UserTransaction object. You can then begin, commit, and rollback transactions explicitly.

ejbLoad(). If you recall, ejbStore() and ejbLoad() are bean callbacks to synchronize a bean instance with an underlying storage. ejbStore() saves data to storage, and ejbLoad() reads data from storage. When the container calls ejbStore(), your bean knows exactly what data to save because the bean instance has the data in memory. But when the container calls ejbLoad(), how does your bean know what data to load? After all, bean instances are pooled and can be dynamically assigned to different data. The answer is to use getPrimaryKey(); it will tell you what primary key you should be looking for in the underlying storage when loading database data.

ejbRemove(). If you recall, ejbCreate() and ejbRemove() are callbacks for creating and removing data from an underlying storage, respectively. When the container calls ejbCreate(), your bean knows exactly what data to create in the database because your bean has received information in the parameters of ejbCreate(). But when the container calls ejbRemove(), how does your bean know what data to remove? Because bean instances are pooled and dynamically assigned to handle different data instances, you might be deleting the wrong data. Thus you must call getPrimaryKey() to figure out what data, keyed on the primary key, your bean should remove from the database.

public interface javax.ejb.EntityContext implements javax.ejb.EJBContext {

public abstract javax.ejb.EJBObject getEJBObject();

public abstract java.lang.Object getPrimaryKey();

}

Source 7.4 The javax.ejb.EntityContext interface.

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

202 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

Thus, it’s always important to consider bean pooling when writing your enterprise beans, and getPrimaryKey() is the key to always knowing what data your bean is representing.

Putting It All Together: Walking through an Entity Bean Life Cycle

Throughout this chapter, we’ve touched on various moments in the life cycle of an entity bean instance—when it’s created, when it’s destroyed, and how it’s used. Now that you’ve seen all the elements, let’s wrap up this chapter by examining the big picture and defining this process more concretely. The state machine diagram in Figure 7.7 illustrates the life cycle of an entity bean.

Here is what’s going on in this diagram:

1.The does not exist state represents entity bean instances that have not been instantiated yet.

2.To create a new instance, the container calls the newInstance() method on the entity bean class. This calls your entity bean’s default constructor, bringing a new instance into memory. Next, the container associates your entity bean with an entity context object—this is done via a callback that you implement, called setEntityContext(EntityContext ctx). Note that this step occurs only when the container wants to increase the available pool of entity bean instances—this is not necessarily done when a client connects.

3.After step 2, your entity bean is in a pool of other entity beans. At this point your entity bean does not have any entity bean database data loaded into it, and it does not hold any bean-specific resources, such as socket connections. Your bean instance can be used in this mode to find entity data in the database, by servicing a finder method on behalf of a client. If the container wants to reduce its pool size, it can destroy your bean. The container signals your bean instance that it is about to be destroyed by calling the unsetEntityContext() method on your bean. Once this is done, the container releases any references to your bean, and eventually, the Java garbage collector will clean up the memory your instance had been using. Therefore, your unsetEntityContext() method should prepare your bean to be cleaned up, perhaps by releasing any bean-independent resources your bean had claimed.

4.When the client wants to create some new database data (say, a new order for goods placed over the Internet), it calls a create() method on your entity bean’s home object. The container then grabs an entity bean instance from the pool, and the instance’s ejbCreate() method is called. ejbCreate() initializes the entity bean to a specific data set. For example, if a client calls

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

Introduction to Entity Beans 203

a create() method to create a bank account, it might pass the bank account holder’s name and the initial balance as parameters. Your entity bean’s ejbCreate() method would populate its member variables with these parameters. It would also create the corresponding database representation (if you’re using bean-managed persistence). Now your bean is in the “ready” state.

does not exist

The life cycle of an entity bean. Each method call shown is an invocation from the container to the bean instance.

Note that some minor steps have been left out for clarity.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1: newInstance()

 

1: unsetEntityContext()

2: setEntityContext()

 

2: JVM will garbage collect

 

 

 

 

and call finalize()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

pooled

ejbFind()

 

 

Activate your bean:

 

Passivate your bean:

 

ejbCreate()

 

1: ejbActivate()

 

1: ejbStore()

ejbRemove()

 

 

2: ejbLoad()

 

2: ejbPassivate()

 

 

 

 

 

 

 

 

 

 

 

ejbLoad()

ready

ejbStore()

business method

Figure 7.7 The entity bean life cycle.

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

204 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

5.While your bean is in the ready state, it is tied to specific data and hence a specific EJB object. If there are other entity bean instances that are views into the same database data, the container may occasionally need to synchronize your bean instance with the underlying database, so that you will always be working with the most recent data. The ejbLoad() and ejbStore() methods do this; the container calls them as appropriate, based on how you define your transactions (see Chapter 10).

6.There are two ways for your entity beans to be kicked back into the pool. If a client calls remove() on the home object, then the container will call your instance’s ejbRemove(). The underlying database data is destroyed, and so, of course, your entity bean instance will become disassociated with the client’s EJB object to which it was bound.

7.The second way your bean can return to the pool is if the EJB container decides that your client has timed out, if the container needs to use your bean to service a different client, or if the container is simply running out of resources. At this point, your bean is passivated, and the container calls your ejbStore() method to ensure the database has the most recent version of your in-memory data. Next, the container calls your ejbPassivate() method—allowing your bean instance to release all bean-specific resources. Your bean instance then enters the pool.

8.When the container wants to assign you to an EJB object again, your bean instance must be activated. The container calls your bean’s ejbActivate() method, allowing your bean to acquire bean-specific resources. The container then calls your instance’s ejbLoad() method to load the database data into your bean.

Note that there are a few other minor steps in this process, such as transactional synchronization. Overall, these stages are the essence of an entity bean instance’s life cycle. If you’ve made it this far, then congratulations! You are ready to move on from theoretical concepts to the concrete entity bean programming.

Summary

In this chapter, we’ve taken the first steps toward developing with entity beans. We started by learning about various persistence mechanisms, including object serialization, object/relational mapping, and persistence to pure object databases. We then looked at exactly what an entity bean is, and we saw the files included with an entity bean component. Next, we used our knowledge of session beans as a basis for learning entity beans. After surveying their features, we took a look at the interfaces that EJB provides for entity bean components,

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

Introduction to Entity Beans 205

such as the entity bean interface and the entity context interface. Finally, we stepped through the life cycle of a typical entity bean instance.

But the best is yet to come—in the next two chapters, we’ll learn hands-on about entity bean programming. Chapter 8 starts off by explaining bean-managed persistent entity beans, and it guides you through the steps in developing them using JDBC. Chapter 9 then continues with container-managed persistent entity beans. Not only will we see how the programming styles differ, but we’ll do a full comparison of the promises and realities of the two entity bean programming models. By the time you’re through, you’ll be armed to create your own entity beans in enterprise deployments.

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

C H A P T E R8

Writing Bean-Managed Persistent

Entity Beans

n Chapter 7, we covered some basic entity bean concepts. We learned that there

Iare two kinds of entity beans—bean-managed persistent and container-managed persistent.

In this chapter, we’ll demonstrate how to program bean-managed persistent entity beans. When you code these types of entity beans, you must provide your own data access logic. You are responsible for providing the implementation to map your entity bean instances to and from storage. To do this, you’d typically use a database API such as JDBC or SQL/J. This is in stark contrast to containermanaged persistent entity beans, which have their data access handled for them by the EJB container. This chapter will teach you the basics of bean-managed persistence and show you how to build a simple bean-managed entity bean using JDBC.

Implementation Guidelines for Bean-Managed Persistence

In Chapter 7, we saw that all entity bean classes—both bean-managed persistent and container-managed persistent—must implement the javax.ejb.EntityBean interface. This interface defines callback methods that the container invokes on your beans. What you should put in these methods depends in part on whether you are using bean-managed persistence or container-managed persistence. Table 8.1 is a summary of what you should implement in each method, assuming your entity bean’s persistence is bean-managed. Take a quick glance at the

207

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

Table 8.1 Descriptions and Implementation Guidelines for Bean-Managed Persistent Entities

METHOD

EXPLANATION

setEntityContext()

If the container wants to

 

increase its pool size of bean

 

instances, it will instantiate a

 

new entity bean instance. Fol-

 

lowing 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

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.

ejbFind<…>(<…>)

While your bean instance is

Search through a data store using

(also called finder

still in the pool, the container

a storage API such as JDBC or

methods)

can use your bean to service a

SQL/J. For example, you might

 

finder method. Finder methods

perform a relational query such as

 

locate one or more existing

“SELECT id FROM accounts

 

entity bean data instances in

WHERE balance > 0.”

 

the underlying persistent store.

 

 

You must define at least one

When you’ve found some data, you

 

finder method—

should return the primary keys for

 

ejbFindByPrimaryKey().

that data back to the container by

 

 

creating one or more primary key

 

 

Java object instances. The con-

 

 

tainer will then create EJB objects

 

 

for the client to invoke on and

 

 

possibly associate some entity

 

 

bean instances with those EJB

 

 

objects. Those entity bean

 

 

instances are then no longer in

 

 

the pool—they now have specific

 

 

database data inside of them,

 

 

and they are bound to particular

 

 

EJB objects.

ejbCreate(<…>)

When a client calls create() on

Make sure the client’s initialization

 

a home object, the container

parameters are valid. Explicitly

Note: You do not

then calls ejbCreate() on a

create the database representa-

need to write any

pooled bean instance.

tion of the data via a storage API

ejbCreate()

ejbCreate() methods are

such as JDBC or SQL/J.

methods if you

responsible for creating new

 

don’t want EJB

database data and for

Your entity bean instance is then

clients to be able to

initializing your bean.

no longer in the pool—it now has

create new data-

 

specific database data inside of it.

base data. Instead,

 

The container will bind your

you could mandate

 

instance to a particular EJB object.

208