|
|
Enterprise Java Beans(EJB)
-
Enterprise
beans are server components written in the Java programming language.
-
Enterprise
beans contain the business logic for your application.
Session
Beans
-
A session bean
represents a client in the J2EE server.
-
A session bean converses with the client, and
can be thought of as an extension of the client.
-
Each session bean can have only one
client.
-
When the client terminates, its
corresponding session bean also
terminates. Therefore, a session
bean is transient, or non-persistent.
Entity Beans
-
An entity bean represents a
business object in a persistent storage mechanism such as a database
-
might be stored as
a row in the customer table of a relational database.
-
An entity bean's
information does not have to be stored in a relational database. It could be
stored in an object database, a legacy application, a file, or some other
storage mechanism.
-
The persistence of an entity bean can be
managed by either the entity bean itself, or by the EJB container.
-
Bean-managed persistence requires you to write
the data access code in the Bean.
-
Container-managed persistence means that the
EJB container handles the data access calls automatically.
Comparing Session and Entity
Beans
|
|
Session Bean
|
Entity Bean
|
|
Purpose
|
Performs a task for a
client.
|
Represents a business
entity object that exists in persistent storage.
|
|
Shared
Access
|
May have one client.
|
May be shared by
multiple clients.
|
|
Persistence
|
Not persistent. When
the client terminates its session bean is no longer available.
|
Persistent. Even when
the EJB container terminates, the entity state remains in a database.
|
Java
BeansTM Components and
Enterprise
Beans
-
JavaBeans components and
enterprise beans are not the same. Although both components are written in
the Java programming language, they are not interchangeable.
-
JavaBeans
components define a convention for making a Java class instance customizable
by design tools, allowing the tools to link these customized objects via
events.
-
Enterprise
beans implement multi-user, transactional services.
Programming Restrictions for
Enterprise
Beans
To avoid conflicts with the
services provided by container,, enterprise beans are restricted from
performing certain operations:
-
Managing or synchronizing
threads
-
Accessing files or directories with the
java.io
package
-
Using AWT functionality to
display information or to accept information from a
keyboard
-
Listening on a socket, accepting
connections on a socket, or using a socket for
multicast
-
Setting a socket factory used by
ServerSocket, Socket, or the stream handler factory used by the URL
class
-
Loading a native library
Database Access
·
Both session and entity
beans can access a database.
·
include SQL calls in a
session bean under the following circumstances:
·
The application is
relatively simple.
·
The data returned by the SQL
call will not be used by multiple clients.
·
The data does not represent
a business entity.
-
access a database from an
entity bean if any of the following conditions are true:
-
More than one client will use the data
returned by the database call.
-
The data represents a business
entity.
-
You want to hide the relational model from
the session bean.
Session Beans
·
A session bean represents a
single client inside the J2EE server.
·
The client accesses remote
services by invoking the session bean's methods.
·
The session bean performs
work for its client, shielding the client from complexity by executing
business tasks inside the server.
·
As its name suggests, a
session bean is similar to an interactive session.
o
A session bean is not
shared-- it may have just one client, in the same way that an interactive
session may have just one user.
o
Like an interactive session,
a session bean is not persistent.
o
When the client terminates,
its session bean appears to terminate and is no longer associated with the
client.
·
Session beans are powerful
because they extend the reach of your clients into remote servers-- yet
they're easy to build. The following section shows you how to construct a
simple session bean.
Session Bean Class
The session bean must meet
these requirements:
-
It implements the
SessionBean
interface.
-
The class is defined as
public.
-
The class cannot be defined as
abstract or final.
-
It implements one or more
ejbCreate
methods.
-
It implements the business
methods.
-
It contains a
public constructor with no
parameters.
-
It must not define the
finalize method.
The
SessionBean Interface
-
extends the
EnterpriseBean
interface, which in turn extends the Serializable interface.
-
The
SessionBean interface declares the ejbRemove, ejbActivate,
ejbPassivate, and setSessionContext methods.
-
The
Bean
class, but it must implement them because
they're declared in the SessionBean interface.
The ejbCreate
Methods
-
Because an enterprise bean runs inside an EJB
container, a client cannot directly instantiate the bean.
-
Only the EJB container can instantiate an
enterprise bean.
-
During instantiation, the example program
performs these steps:
-
The client invokes a
create method on the home
object:
-
The EJB container
instantiates the enterprise bean.
-
The EJB container
invokes the appropriate
ejbCreate method Typically, an
ejbCreate method initializes the state of the enterprise bean.
-
An enterprise bean may have one or more
ejbCreate
methods. The signatures of the methods meet the following requirements:
-
The access control modifier must be
public.
-
The return type must be
void.
-
The arguments must be legal types for Java
RMI.
-
The modifier cannot be
static or final.
-
The throws clause may include the
javax.ejb.CreateException and
other exceptions that are specific to your application. The ejbCreate method
usually throws a CreateException if an input parameter is invalid.
Business
Methods
·
The primary purpose of a
session bean is to run business tasks for the client.
·
The client invokes business
methods on the remote object reference that is returned by the create method.
·
From the client's
perspective, the business methods appear to run locally, but they actually run
remotely in the session bean.
·
The signature of a business
method must conform to these rules:
·
The method name must not
conflict with one defined by the EJB architecture. For example, you cannot
call a business method ejbCreate or ejbActivate.
·
The access control modifier
must be public.
·
The arguments and return
types must be legal types for Java RMI.
·
The modifier must not be
static or final.
·
The throws clause may
include exceptions that you define for your application. The removeBook method, for
example, throws the BookException if the book is not in the cart.
·
To indicate a system-level
problem, such as the inability to connect to a database, a business method
should throw the javax.ejb.EJBException. When a business method throws an EJBException, the container
wraps it in a RemoteException, which is caught by the client.
·
The container will not wrap
application exceptions.
·
Because
EJBException is a subclass of RuntimeException, you do not need to include it in the throws
clause of the business method.
Home Interface
-
A home interface extends
the
EJBHome interface.
-
The purpose of the home interface is to
define the
create methods that a client may invoke.
-
Every
create method in the home interface
corresponds to an ejbCreate method in the bean class.
-
The signatures of the
ejbCreate and create methods
are similar, but differ in important ways. The rules for defining the
signatures of the create methods of a home interface follow:
-
The number and types of argments in a
create
method must match those of its corresponding ejbCreate
method.
-
The arguments and return type of the
create
method must be valid RMI types.
-
A
create method returns the remote interface
type of the enterprise bean. (But an ejbCreate method returns void.)
-
The throws clause of the
create method must
include the java.rmi.RemoteException and the javax.ejb.CreateException.
Remote Interface
· The remote interface, which extends javax.ejb.EJBObject, defines the business methods that a client may invoke.
· The method definitions in a remote interface must follow these rules:
o Each method in the remote interface must match a method implemented in the enterprise bean class.
o The signatures of the methods in the remote interface must be identical to the signatures of the corresponding methods in the enterprise bean class.
o The arguments and return values must be valid RMI types.
o The throws clause must include the java.rmi.RemoteException.
State
Management Modes
When you specify the
deployment descriptor of a session bean, you must choose between two state
management modes: stateful or stateless.
Stateful Session Beans
·
The state is retained for
the duration of the client-bean session.
·
When the client removes the
bean, the session ends and the state disappears.
·
This transient nature of the
state is not a problem, however, because when the conversation between the
client and the bean is over there is no need to retain the state.
Stateless Session Beans
-
A stateless session bean
does not maintain a conversational state for a particular client.
-
When a client invokes the method of a stateless
bean, the beans's instance variables may contain a state, but only for the
duration of the invocation.
-
When the method is finished, the state is no
longer retained.
-
Except during method invocation, all
instances of a stateless bean are
equivalent, allowing the EJB
container to assign an instance to any client.
·
Because stateless session
beans can support multiple clients, they can offer better
scalability for applications that require large numbers of clients.
·
Typically, an application
requires fewer stateless session beans than stateful session
beans to support the same number of clients.
·
At times, the EJB container
may write a stateful session bean out to secondary storage. However, stateless
session beans are never written out to secondary storage. Therefore, stateless
beans may offer better performance than stateful beans.
·
The home interface of a
stateless session bean must have a single create method with no
arguments.
·
The session bean class must
contain one ejbCreate method, also without arguments. (The arguments are only
needed by stateful session beans, which use them to initialize their states.)
Choosing Between Stateful and
Stateless Session Beans
consider using a stateful
session bean if any of the following conditions are true:
·
The bean's state must be
initialized when it is created.
·
The bean needs to hold
information about the client across method
invocations.
·
The
client is an interactive application.
use stateless session beans:
·
The bean performs a task
that is not tailored to the needs of a particular client. For example, you
might use a stateless session bean to fetch from a database a commonly used
set of data.
·
The bean doesn't need to
hold information about the client across method invocations.
The Life Cycle of a Session Bean
-
The life cycle is managed by
the EJB container, not by your applications.
The Stateful Session Bean Life
Cycle
-
The client initiates the
life cycle by invoking the
create method.
-
The EJB container instantiates the bean and
then invokes the
setSessionContext and ejbCreate methods in the session bean. The bean is
now ready to have its business methods invoked.
-
While in the ready stage, the EJB container may
decide to deactivate, or passivate, the bean by moving it from
memory to secondary storage. (Typically, the EJB container uses a
least-recently-used algorithm to select a bean for
passivation.)
-
The EJB container invokes the bean's
ejbPassivate method immediately before passivating it.
-
If a client invokes
a business method on the bean while it is in the passive stage, the EJB
container activates the bean, moving it back to the ready stage, and
then calls the bean's
ejbActivate method.
-
At the end of the life cycle, the client
invokes the
remove method and the EJB container calls the bean's ejbRemove
method. The bean's instance is ready for garbage collection.
-
Your code controls the invocation of only two
life cycle methods-- the
create and remove methods in the client. All other
methods are invoked by the EJB container. The ejbCreate method, for example, is
inside the bean class, allowing you to perform certain operations right
after the bean is instantiated. For instance, you may wish to connect to a
database in the ejbCreate method.
The
Stateless Session Bean Life Cycle
-
Because a stateless session
bean is never passivated, its life cycle has just two stages: non-existent
and ready for the invocation of business methods.
FIGURE 3-2 Life Cycle of a
Stateless Session Bean
Comparing Session Beans
-
A client can determine if
the object references of two stateful session beans are identical by
invoking the
isIdentical method:
bookCart = home.create("Bill Shakespeare");
videoCart = home.create("Lefty Lee");
. . .
if (bookCart.isIdentical(bookCart)) {
// true . . . }
if (bookCart.isIdentical(videoCart)) {
// false . . . }
· Because stateless session beans have the same object identity, the isIdentical method always returns true when used to compare two such beans.
Passing a Session Bean's Object Reference
-
You can't pass the
this
reference, to pass a reference to itself, to another bean because the
session bean is not a remote object.
-
Instead, your bean
must pass an object reference for the instance. It gets the reference to
itself by calling the
getEJBObject method of the SessionContext interface
Accessing Environment Entries
-
Note: The material
described in this section applies to both session and entity beans.
-
Stored in an enterprise bean's deployment
descriptor, an environment entry is a name-value
pair that allows you to customize the bean's business logic without
changing its source code. An enterprise bean that calculates discounts, for
example, might have an environment entry named "Discount Percent." Before
deploying the bean's application, you could assign "Discount Percent" a
value of .05 on the Environment tabbed pane of the Application Deployment
Tool. When you run the application, the enterprise bean fetches the .05
value from its environment.
-
First, the method locates the environment
naming context by invoking
lookup with the "java:comp/env"
parameter. Then it calls lookup on the environment to get the values for the
"Discount Level" ..
Entity Beans
·
An entity bean represents an
entity kept in a persistent storage mechanism, usually a database.
·
Inside the J2EE server, this
application would represent the business entity objects with entity beans.
Characteristics of Entity Beans
-
Entity beans differ from
session beans in several ways. Entity beans are persistent, allow shared
access, and have primary keys.
Persistence
-
Because the state of an
entity bean is saved in a storage mechanism, it is persistent.
-
Persistence means that the entity bean exists
beyond the lifetime of the application or the J2EE server process.
-
There are two types of persistence:
bean-managed and container-managed. You declare the persistence type with
the Application Deployment Tool, which stores the information in the entity
bean's deployment descriptor.
-
With bean-managed persistence, the entity bean
code that you write contains the calls that access the database. The
ejbCreate
method, for example, will issue the SQL insert statement. You are responsible
for coding the insert statement and any other necessary SQL calls.
-
If the container manages an entity bean's
persistence, it automatically generates the necessary database access calls.
For example, when a client creates an entity bean, the container generates a
SQL insert statement. The code that you write for the entity bean does not
include any SQL calls. The container also synchronizes the entity bean's
instance variables with the data in the underlying database. These instance
variables are often referred to as container-mananged
fields.
-
You declare the container-managed fields with
the Application Deployment Tool, which enters the list of fields in the
deployment descriptor.
-
Container-managed persistence has two
advantages over bean-managed persistence.
-
First, entity
beans with container-managed persistence require less code.
-
Second, because the beans don't contain the
database access calls, the code is independent of any particular
data store, such as a relational database. However,
container-managed persistence has several limitations.
-
Container-Managed
Persistence limitations
-
The implementation of container-managed
persistence for entity beans does not provide a full set of features for
mapping objects to relational databases:
-
The entity bean class may
be mapped to only one table in the
database.
-
A container-managed field may be mapped
to only one column in the table.
-
When the container loads the
container-managed fields from the underlying database, it
loads all of them. If the amount of data loaded is large,
this approach may be inefficient because a business method may not need
all of the container-managed fields.
-
If the container-managed fields of
multiple entity beans map to the same data item in a database, and if
these beans are invoked in the same transaction, they may see an
inconsistent view of the data item.
-
The Application Deployment Tool generates SQL
statements for the ejbCreate, ejbRemove, ejbLoad, and ejbStore methods.
You may modify only the table and column names of these SQL statements.
You may not modify the number and order of the question marks, which are
place holders for the input parameters.
-
You cannot call stored
procedures in the generated SQL
statements.
-
In the "Create Table" SQL statement, you may
change the SQL type of a table column provided that the SQL type is
compatible with its corresponding instance
variable.
-
The table and column names in all of the SQL
statements must be consistent.
-
The generated SQL statements have been tested
with these types of databases: Cloudscape, Oracle, and Microsoft SQL
Server. You may need to edit the generated SQL statements to satisify the
requirements of your database
Shared Access
-
Entity beans may be shared by multiple clients.
Because the clients might want to change the same data, it's important that
entity beans work within transactions.
-
Typically, the EJB container provides
transaction management. You specify the transaction attributes in the bean's
deployment descriptor. You do not have to code the transaction boundaries in
the bean-- the container marks the boundaries for you.
Primary Key
-
Each entity bean has a
unique object identifier. The unique identifier, or primary key, enables the
client to locate a particular entity bean.
A Bean-Managed Persistence Example
Entity
Bean Class
The entity bean class meets
the requirements of every entity bean:
-
It implements the
EntityBean
interface.
-
The class is defined as
public.
-
The class cannot be defined as
abstract or final.
-
It implements zero or more
ejbCreate and ejbPostCreate
methods.
-
It implements the finder methods (only for
bean-managed persistence).
-
It implements the business
methods.
-
It contains an empty
constructor.
-
It does not implement the
finalize method.
The
EntityBean Interface
-
The
EntityBean
interface extends the
EnterpriseBean interface, which extends the Serializable interface.
-
The
EntityBean interface declares a number of
methods, such as ejbActivate and ejbLoad, which you must implement in your entity
bean class.
The
ejbCreate Method
-
When the client invokes a
create method, the EJB container invokes the corresponding ejbCreate method.
-
Typically, an
ejbCreate method in an entity bean
performs the following tasks:
-
Inserts the entity state into the
database.
-
Initializes the instance
variables.
-
Returns the primary
key.
-
an enterprise bean may contain multiple
ejbCreate
methods
-
When writing an
ejbCreate method for an entity
bean, be sure to follow these rules:
-
The access control modifier must be
public.
-
The return type must be the primary key (only
for bean-managed persistence).
-
The arguments must be legal types for Java
RMI.
-
The method modifier cannot be
final or static.
-
The
throws clause may include the javax.ejb.CreateException and
other exceptions that are specific to your application.
-
An
ejbCreate method usually throws a CreateException if an
input parameter is invalid.
-
If an
ejbCreate method cannnot create an entity
because another entity with the same primary key already exists, it should
throw a javax.ejb.DuplicateKeyException (a subclass of CreateException).
-
If a client
receives a
CreateException or a DuplicateKeyException, it should assume that the entity was not
created.
-
The state of an entity bean may be directly
inserted into the database by a non-J2EE application. Although the entity
bean for this row was not created by an
ejbCreate method, the bean can be
located by a client program.
The
ejbPostCreate Method
-
For each
ejbCreate method, you
must write an ejbPostCreate method in the entity bean class.
-
The EJB container invokes
ejbPostCreate immediately
after it calls ejbCreate. Unlike the ejbCreate method, the ejbPostCreate method can invoke
the getPrimaryKey and getEJBObject methods of the EntityContext interface
-
Often, your
ejbPostCreate
methods will be empty.
-
The signature of an
ejbPostCreate must meet the
following requirements:
-
The number and types of arguments must match
a corresponding
ejbCreate method.
-
The access control modifier must be
public.
-
The method modifier cannot be
final or static.
-
The return type must be
void.
-
The
throws clause may include the javax.ejb.CreateException, and
other exceptions that are specific to your application.
The
ejbRemove Method
-
A client removes an entity
bean by invoking the
remove method.
-
This invocation causes the EJB client to call
the
ejbRemove method, which deletes the entity state from the database.
-
If the
ejbRemove method encounters a system
problem, it should throw the javax.ejb.EJBException. If it encounters an application error,
it should throw a javax.ejb.RemoveException.
-
An entity bean may also be removed directly by
a database deletion.
The
ejbLoad Method and ejbStore Methods
-
If the EJB container needs
to synchronize the instance variables of an entity bean with
the corresponding values stored in a database, it invokes the
ejbLoad and
ejbStore methods.
-
The
ejbLoad method refreshes the instance
variables from the database, and the ejbStore method writes the variables to
the database.
-
The client may not call
ejbLoad and ejbStore.
-
If a business method is associated with a
transaction, the container invokes
ejbLoad before the business method
executes.
-
Immediately after the business method executes,
the container calls
ejbStore.
-
Because the
container invokes
ejbLoad and ejbStore, you do not have to refresh and store the
instance variables in your business methods-- the container performs these
functions for you.
-
If the
ejbLoad and ejbStore methods cannot locate an
entity in the underlying database, they should throw the javax.ejb.NoSuchEntityException. This
exception is a subclass of EJBException. Because EJBException is a subclass of RuntimeException, you
do not have to include it in the throws clause. When NoSuchEntityException is thrown, the
EJB container wraps it in a RemoteException before returning it to the client.
The
Finder Methods
· The finder methods allow clients to locate entity beans.
· For every finder method available to a client, the entity bean class must implement a corresponding method that begins with the prefix ejbFind.
· The finder methods specific to your application, such as ejbFindByLastName and ejbFindInRange, are optional, but the ejbFindByPrimaryKey method is required. As its name infers, the ejbFindByPrimaryKey method accepts as an argument the primary key, which it uses to locate an entity bean.
· The ejbFindByPrimaryKey method may look strange to you, because it uses a primaryKey for both the method argument and return value. However, remember that the client does not call ejbFindByPrimaryKey directly. It is the EJB container that calls the ejbFindByPrimaryKey method. The client invokes the findByPrimaryKey method, which is defined in the home interface.
· The following list summarizes the rules for the finder methods that you implement in an entity bean class with bean-managed persistence:
o The ejbFindByPrimaryKey method must be implemented.
o A finder method name must start with the prefix ejbFind.
o The access control modifier must be public.
o The method modifier cannot be final or static.
o The arguments and return type must be legal types for Java RMI.
o The return type must be the primary key or a collection of primary keys.
o The throws clause may include the javax.ejb.FinderException, and other exceptions that are specific to your application.
o If a finder method returns a single primary key, it should throw the javax.ejb.ObjectNotFoundException if the requested entity does not exist. The ObjectNotFoundException is a subclass of FinderException.
o If a finder method returns a collection of primary keys, it should throw a FinderException.
The
Business Methods
-
The business methods
contain the business logic that you want to encapsulate within the entity
bean.
-
Usually, the business methods do not access the
database, allowing you to separate business logic from the database access
code.
-
The requirements for the signature of a
business method are the same for both session and entity beans:
-
The method name must not conflict with a
method name defined by the EJB architecture. For example, you cannot call
a business method
ejbCreate or ejbActivate.
-
The access control modifier must be
public.
-
The method modifier cannot be
final or static.
-
The arguments and return types must be legal
types for Java RMI.
-
The
throws clause may include the the
exceptions that you define for your application. The debit method, for
example, throws the InsufficientBalanceException. To indicate a system-level problem, a business
method should throw the javax.ejb.EJBException.
Database
Calls
|
SQL
Statement in AccountEJB
|
|
Method
|
Resulting SQL
Statement
|
|
ejbCreate
|
insert
|
|
ejbFindByPrimaryKey
|
select
|
|
ejbFindByLastName
|
select
|
|
ejbFindInRange
|
select
|
|
ejbLoad
|
select
|
|
ejbRemove
|
delete
|
|
ejbStore
|
update
|
Home
Interface
-
The
create methods in the home interface must conform to these requirements:
-
It has the same number and types of arguments
as its matching
ejbCreate method in the enterprise bean
class.
-
It returns the remote interface type of the
enterprise bean.
-
The
throws clause includes the exceptions
specified by the throws clause of the corresponding ejbCreate and ejbPostCreate
methods.
-
The
throws clause contains the java.rmi.RemoteException and the
javax.ejb.CreateException.
·
Every finder method in the
home interface corresponds to a finder method in the entity bean class.
·
The name of a finder method
in the home interface begins with find, whereas the name of one in the entity
bean class begins with ejbFind.
·
The rules for defining the
signatures of the finder methods of a home interface follow:
o
The number and types of
arguments must match those of the corresponding method in the entity bean
class.
o
The return type is the
entity bean's remote interface type, or a collection of those
types.
o
The exceptions in the throws
clause include those of the corresponding method in the entity bean
class.
o
The throws clause contains
the javax.ejb.FinderException and the javax.ejb.RemoteException.
Remote Interface
o The remote interface extends javax.ejb.EJBObject and defines the business methods that a client may invoke.
o The requirements for the method definitions in a remote interface are the same for both session and entity beans:
o Each method in the remote interface must match a method in the enterprise bean class.
o The signatures of the methods in the remote interface must be identical to the signatures of the corresponding methods in the enterprise bean class.
o The arguments and return values must be valid RMI types.
o The throws clause must include java.rmi.RemoteException
A Container-Managed Persistence Example
-
The
code in the home and remote interfaces is the same whether or not an entity
bean uses container-managed persistence.
-
However, the code in the entity bean class is
different for container-managed and bean-managed persistence. With
container-managed persistence, the entity bean class contains no database
access code. The Application Deployment Tool generates the SQL statements
needed by the entity bean class. In order to generate the SQL statements,
the tool needs to know which instance variables must be stored in the
database. These instance variables are called container-managed fields.
Container-Managed
Fields
-
These
fields represent the state of an
ProductEJB instance.
-
You specify the container-managed fields with
the Application Deployment Tool
-
A container-managed field must be one of the
following types:
-
Java serializable
class
-
Java primitive
-
Reference of a home
interface
-
Reference of a remote
interface
-
A container-managed field must be
public and
may not be defined as transient.
The
ejbCreate Method
-
The
ejbCreate method
initializes the container-managed fields from the input parameters.
-
The method returns null because with
container-managed persistence the container ignores its return value.
-
After the
ejbCreate method executes, the container
inserts the container-manged fields into the database.
The
ejbRemove Method
-
When the client invokes the
remove method, the container calls the ejbRemove method.
-
After the
ejbRemove method returns, the container
deletes the row from the database.
-
If the container
fails to delete the row, it throws an exception.
-
If an entity bean needs to perform some
operation immediately before removal, it should do so in the
ejbRemove method.
The
ejbLoad Method
When the container needs to
refresh the entity bean's state from the database, it performs these steps:
-
Selects the row from the
database
-
Assigns the row's column values to the
container-manged fields
-
Invokes the
ejbLoad
method
-
Usually, the
ejbLoad method is empty. The entity
bean may use the ejbLoad method, however, to transform the values read from
the database. For example, the ejbLoad method might uncompress text data so
that it can be manipulated by the business methods.
The
ejbStore Method
When the container needs to
save the entity bean's state in the database, it performs these steps:
-
Invokes the
ejbStore
method
-
Gets the values of the container-managed
fields
-
Updates the row in the database with the values
of the container-managed fields
-
Like the
ejbLoad method, the ejbStore method is
typically empty. But if you need to transform container-managed fields
before the container stores them in the database, you should do so in the
ejbStore method. For example, the ejbStore method might compress text data before
the container stores it in the database.
Handling Exceptions
The exceptions thrown by
enterprise beans fall into two categories: system and application.
·
A system
exception indicates a problem with the services that
support an application.
o
Examples of these problems
include the following: a database connection cannot be obtained, a SQL insert
fails because the database is full, a lookup method cannot find the desired
object.
o
If your enterprise bean
encounters a sytem-level problem, it should throw a javax.ejb.EJBException. The container will
wrap the EJBException in a RemoteException, which it passes back to the client.
o
Because
the EJBException is a subclass of the RuntimeException, you do not have to specify it in the
throws clause of the method declaration.
o
If
a system exception is thrown, the EJB container might destroy the bean
instance. Therefore, a system exception cannot be handled by the bean's client
program; it requires intervention by a system administrator.
·
An application exception
signals an error in the business logic of an enterprise bean.
o
There are two types of
application exceptions: customized and predefined.
o
A customized exception is
one that you've coded yourself, such as the InsufficentBalanceException thrown by the debit business
method of the AccountEJB example.
o
The javax.ejb package includes
several predefined exceptions that are designed to handle common problems. For
example, an ejbCreate method should throw a CreateException to indicate an invalid input
parameter.
o
When an enterprise bean
throws an application exception, the container does not wrap it in another
exception. The client should be able to handle any application exception it
receives.
o
If a system exception occurs
within a transaction, the EJB container rolls back the transaction. However,
if an application exception is thrown within a transaction, the container does
not roll back the transaction.
The following table
summarizes the exceptions of the javax.ejb package. All of these exceptions are
application exceptions, except for the NoSuchEntityException and the EJBException, which are system
exceptions.
|
Exceptions
|
|
Method Name
|
Exception It Throws
|
Reason for Throwing
|
|
ejbCreate
|
CreateException
|
An input parameter is
invalid.
|
|
ejbFindByPrimaryKey
(and other finder methods)
|
ObjectNotFoundException
(subclass of FinderException)
|
The database row for
the requested entity bean is cannot be found.
|
|
ejbRemove
|
RemoveException
|
The entity bean's row
cannot be deleted from the database.
|
|
ejbLoad
|
NoSuchEntityException
|
The database row to be
loaded cannot be found.
|
|
ejbStore
|
NoSuchEntityException
|
The database row to be
updated cannot be found.
|
|
(all methods)
|
EJBException
|
A system problem has
been encountered.
|
Primary Key Class
-
You specify the primary key class with the
Application Deployment Tool.
-
When deploying the
ProductEJB bean, for example, you
would specify a java.lang.String as the primary key class.
-
In most cases, your
primary key class will be a
String or some other class that belongs to the
java package.
Creating a Primary Key
Class
-
For some entity beans, you
will need to define your own primary key class.
-
if a primary key is composed of multiple fields
then you must create a primary key class
-
Primary Class
Requirements
-
The access control modifier of the class is
public.
-
All fields are declared as
public.
-
For container-managed persistence, the field
names in the primary key clsss must match the corresponding
container-managed fields in the entity bean
class.
-
The class has a
public default
constructor.
-
The class implements the
hashCode() and equals(Object other)
methods.
-
The class is serializable.
Bean-Managed
Persistence and the Primary Key Class
-
With bean-managed
persistence, the
ejbCreate method returns the primary key class:
Container-Managed
Persistence and the Primary Key Class
-
For an entity bean with
container-managed persistence, the
ejbCreate method returns null. (With
bean-managed persistence, it returns an instance of the primary key class.)
-
With container-managed persistence, you do not
have to write the code for the
ejbFindByPrimaryKey method.
Getting the Primary
Key
· A client can fetch the primary key of an entity bean by invoking the getPrimaryKey method of the EJBObject class: account.getPrimaryKey();
· The entity bean retrieves its own primary key by calling the getPrimaryKey method of the context.getPrimaryKey();
The Life Cycle of an Entity Bean
-
The life cycle of an entity
bean is controlled by the EJB container, not by your application
-
After the EJB container creates the instance,
it calls the
setEntityContext method of the entity bean class. The setEntityContext method passes
the entity context to the bean.
-
After instantiation, the entity bean moves to a
pool of available instances. While in the pooled stage, the instance is not
associated with any particular EJB object identity. All instances in the
pool are identical. The EJB container assigns an identity to an instance
when moving it to the ready stage.
-
There are two paths from the pooled stage to
the ready stage. On the first path, the client invokes the
create method,
causing the EJB container to call the ejbCreate and ejbPostCreate methods. On the second
path, the EJB container invokes the ejbActivate method. While in the ready stage,
an entity bean's business methods may be invoked.
-
There are also two paths from the ready stage
to the pooled stage. First, a client may invoke the
remove method, which
causes the EJB container to call the ejbRemove method. Second, the EJB container
may invoke the ejbPassivate method.
-
At the end of the life cycle, the EJB container
removes the instance from the pool and invokes the
unsetEntityContext method.
FIGURE 4-1 Life Cycle of an
Entity Bean
·
In the pooled state, an
instance is not associated with any particular EJB object identity.
·
With bean-managed
persistence, when the EJB container moves an instance from the pooled state to
the ready state, it does not automatically set the primary key. Therefore, the
ejbCreate and ejbActivate methods must set the primary key.
·
If the primary key is
incorrect, the ejbLoad and ejbStore methods cannot synchronize the instance
variables with the database.
·
In the pooled state, the
values of the instance variables are not needed. You can make these instance
variables eligible for garbage collection by setting them to null in the ejbPasssivate
method.
Comparing Entity Beans
-
A client can determine if
the object references of two entity beans are identical by invoking the
isIdentical method:
Account accta, acctb;
. . .
if (accta.isIdentical(acctb))
System.out.println("identical");
Or, the client can fetch and
compare the primary keys of two entity beans:
String key1 = (String)accta.getPrimaryKey();
String key2 = (String)acctb.getPrimaryKey();
if (key1.compareTo(key2) == 0)
System.out.println("equal");
Passing an Entity Bean's Object Reference
-
If you want to pass an
entity bean to another bean, you can't pass the
this reference. Instead,
you must pass the entity bean's object reference by
retrieve the object reference by calling getEJBObject
on the EntityContext of an entity bean.
Transactions
-
Because the steps within a
transaction are a unified whole, a transaction is often
defined as an indivisible unit of work.
-
A transaction can end in two ways: with a
commit or a rollback. When a transaction commits, the data modifications
made by its statements are saved. If a statement within a transaction fails,
the transaction rolls back, undoing the effects of all statements in the
transaction.
-
the begin and commit statments mark the
boundaries of the transaction. When deploying an enterprise bean, you
determine how the boundaries are set by specifying either container-managed
or bean-managed transactions.
## Container-Managed Transactions
##
-
In an enterprise bean with
container-managed transactions, the EJB container sets the
boundaries of the transactions.
-
You can use container-managed transactions with
both session and entity beans.
-
Container-managed transactions simplify
development because the enterprise bean code does not explicitly mark the
transaction's boundaries.
-
The code does not include statements that begin
and end the transaction.
-
Typically, the container begins a transaction
immediately before an enterprise bean method starts. It commits the
transaction just before the method exits. Each method can be associated with
a single transaction.
-
Nested or multiple transactions are not allowed
within a method.
-
Container-managed transactions do not require
all methods to be associated with transactions. When deploying a bean, you
specify which of the bean's methods are associated with transactions by
setting the transaction attributes.
Transaction Attributes
-
A transaction attribute
controls the scope of a transaction. Method-A of Bean 1 begins a transaction
and then invokes method-B of Bean-2. When method-B executes, does it run
within the scope of the transaction started by method-A or does it execute
with a new transaction? The answer depends on the transaction attribute of
method-B.
Transaction
Attribute Values
A transaction attribute may
have one of the following values:
-
Required
-
RequiresNew
-
Mandatory
-
NotSupported
-
Supports
-
Never
Required
-
If the client is running
within a transaction and it invokes the enterprise bean's method, the
method executes within the client's transaction.
-
If the client is not associated with a
transaction, the container starts a new transaction before running the
method.
-
The Required attribute will work for most
transactions. Therefore, you may want to use it as a default, at least in
the early phases of development. Because transaction attributes are
declarative, you can easily change them at a later time.
RequiresNew
-
If the client is running
within a transaction and it invokes the enterprise bean's method, the
container takes the following steps:
-
suspends the client's
transaction
-
starts a new transaction
-
delegates the call to the
method
-
resumes the client's transaction after the
method completes
-
If the client is not associated with a
transaction, the container starts a new transaction before running the
method.
-
You should use the RequiresNew attribute when
you want to ensure that the method always runs within a new transaction.
Mandatory
-
If the client is running
within a transaction and it invokes the enterprise bean's method, the method
executes within the client's transaction.
-
If the client is
not associated with a transaction, the container throws the
TransactionRequiredException.
-
Use the Mandatory attribute if the enterprise
bean's method must use the transaction of the client.
NotSupported
-
If the client is running
within a transaction and it invokes the enterprise bean's method, the
container suspends the client's transaction before invoking the method.
After the method has completed, the container resumes the client's
transaction.
-
If the client is not associated with a
transaction, the container does not start a new transaction before running
the method.
-
Use the NotSupported attribute when you want to
ensure that the method will never run within a transaction generated by the
container.
Supports
-
If the client is running
within a transaction and it invokes the enterprise bean's method, the method
executes within the client's transaction.
-
If the client is not associated with a
transaction, the container does not start a new transaction before running
the method.
-
Because the transactional behavior of the
method may vary, you should use the Supports attribute with caution.
Never
-
If the client is running
within a transaction and it invokes the enterprise bean's method, the
container throws a
RemoteException.
-
If the client is
not associated with a transaction, the container does not start a new
transaction before running the method.
Summary of Transaction
Attributes
Table 6-1 summarizes the
effects of the transaction attributes. Both the T1 and T2 transactions are
controlled by the container. A T1 transaction is associated with the client
that calls a method in the enterprise bean. In most cases, the client is
another enterprise bean. A T2 transaction is started by the container just
before the method executes.
In the last column, the word
"none" means that the business method does not execute within a transaction
controlled by the container. However, the database calls in such a business
method might be controlled by the transaction manager of the DBMS.
|
Transaction
Attributes and Scope
|
|
Transaction
Attribute
|
Client's
Transaction
|
Business Method's
Transaction
|
|
Required
|
none
|
T2
|
|
T1
|
T1
|
|
RequiresNew
|
none
|
T2
|
|
T1
|
T2
|
|
Mandatory
|
none
|
error
|
|
T1
|
T1
|
|
NotSupported
|
none
|
none
|
|
T1
|
none
|
|
Supports
|
none
|
none
|
|
T1
|
T1
|
|
Never
|
none
|
none
|
|
T1
|
error
|
Setting
Transaction Attributes
-
Because transaction
attributes are stored in the deployment descriptor, they can be changed
during several phases of J2EE application development: enterprise bean
creation, application assembly, and deployment.
-
However, as an enterprise bean developer, it is
your responsibility to specify the attributes when creating the bean.
-
The attributes should be modified only by an
application developer who is assembling components into larger applications.
-
Do not expect the person who is deploying the
J2EE application to specify the transaction attributes.
-
You can specify the transaction attributes for
the entire enterprise bean or for individual methods.
-
If you've specified one attribute for a method
and another for the bean, the attribute for the method takes precedence.
-
When specifying attributes for individual
methods, the requirements for session and entity beans vary. Session beans
need the attributes defined for business methods, but do not allow them for
the
create methods. Entity beans require transaction attributes for the
business, create, remove, and finder methods.
Rolling Back a
Container-Managed Transaction
-
There are two ways to roll
back a container-managed transaction.
-
First, if a system exception is
thrown, the container will automatically roll back the
transaction.
-
Second, by invoking the
setRollbackOnly method of the
EJBContext interface, the bean method instructs the container to roll back the
transaction. If the bean throws an application exception,
the roll back is not automatic, but may be initiated by a call to setRollbackOnly.
-
When the container rolls back a transaction,
it always undoes the changes to data made by SQL calls within the
transaction. However, only in entity beans will the container undo changes
made to instance variables. (It does so by automatically invoking the
entity bean's
ejbLoad method, which loads the instance variables from the
database.)
-
When a rollback occurs, a session bean must
explicitly reset any instance variables changed within the transaction.
The easiest way to reset a session bean's instance variables is by
implementing the
SessionSynchonization interface.
Synchronizing a Session Bean's Instance
Variables
-
The
SessionSynchonization interface, which
is optional, allows you to synchronize the instance variables
with their corresponding values in the database.
-
The container invokes the
SessionSynchonization methods-- afterBegin,
beforeCompletion, and afterCompletion-- at each of the main stages of a transaction.
-
The
afterBegin method informs the instance that a
new transaction has begun. The container invokes afterBegin immediately before it
invokes the business method. The afterBegin method is a good place to load the
instance variables from the database.
-
The container invokes the
beforeCompletion method after
the business method has finished, but just before the transaction commits.
The beforeCompletion method is the last opportunity for the session bean to roll back
the transaction (by calling setRollbackOnly). If it hasn't already updated the
database with the values of the instance variables, the session bean may do
so in the beforeCompletion method.
-
The
afterCompletion method indicates that the transaction
has completed. It has a single boolean parameter, whose value is true if the
transaction was committed and false if it was rolled back. If a rollback
occurred, the session bean can refresh its instance variables from the
database in the afterCompletion method
Methods Not Allowed in
Container-Managed Transactions
You should not invoke any
method that might interfere with the transaction boundaries set by the
container. The list of prohibited methods follows:
-
commit, setAutoCommit, and rollback methods of java.sql.Connection
-
getUserTransaction method of javax.ejb.EJBContext
-
any method of
javax.transaction.UserTransaction
You may, however, use these
methods to set boundaries in bean-managed transactions.
Bean-Managed Transactions
-
In a bean-managed
transaction, the session bean code invokes methods that mark the boundaries
of the transaction.
-
An entity bean may not have bean-managed
transactions; it must use container-managed transactions instead.
-
Although beans with container-managed
transactions require less coding, they have one limitation: When a method is
executing, it can be associated with either a single transaction or no
transaction at all. If this limitation will make coding your session bean
difficult, you should consider using bean-managed transactions.
The following pseudo-code
illustrates the kind of fine-grained control you can obtain with bean-managed
transactions. By checking various conditions, the pseudo-code decides whether
to start and stop different transactions within the business method.
begin transaction
...
update table-a
...
if (condition-x)
commit transaction
else if (condition-y)
update table-b
commit transaction
else
rollback transaction
begin transaction
update table-c
commit transaction
When coding a bean-managed
transaction, you must decide whether to use JDBC or JTA transactions. The
sections that follow discuss the techniques and merits of both approaches.
JDBC Transactions
-
A JDBC transaction is
controlled by the transaction manager of the DBMS.
-
You may want to use JDBC transactions when
wrapping legacy code inside a session bean.
-
To code a JDBC
transaction, you invoke the
commit and rollback methods of the javax.sql.Connection interface.
-
The beginning of a transaction is implicit. A
transaction begins with the first SQL statement that follows the most recent
commit, rollback, or connect statement. (This rule is generally true, but may vary
with DBMS vendor.)
The following code is from
the
WarehouseEJBexample,
a session bean that uses the Connection interface's methods to delimit bean-managed
transactions. The ship method starts by invoking setAutoCommit on the Connection object
con. This invocation tells the DBMS not to automatically commit every SQL
statement. Next, the ship method calls routines that update the order_item and
inventory database tables. If the updates succeed, the transaction is committed.
But if an exception is thrown, the transaction is rolled back.
public void ship (String productId, String orderId, int quantity) {
try {
con.setAutoCommit(false);
updateOrderItem(productId, orderId);
updateInventory(productId, quantity);
con.commit();
} catch (Exception ex) {
try {
con.rollback();
throw new EJBException("Transaction failed: " +
ex.getMessage());
} catch (SQLException sqx) {
throw new EJBException("Rollback failed: " +
sqx.getMessage());
}
}
}
JTA Transactions
-
JTA is the abbreviation for
the Java Transaction API. This API allows you to demarcate transactions in a
manner that is independent of the transaction manager implementation.
-
The J2EE SDK implements the transaction manager
with the Java Transaction Service (JTS). But your code doesn't call the JTS
methods directly. Instead, it invokes the JTA methods, which then call the
lower-level JTS routines.
-
A JTA transaction is controlled by the J2EE
transaction manager. You may want to use a JTA transaction because it can
span updates to multiple databases from different vendors. A particular
DBMS's transaction manager may not work with heterogenous databases.
However, the J2EE transaction manager does have one limitation-- it does not
support nested transactions. (It cannot start a transaction for an instance
until the previous transaction has ended.)
-
To demarcate a JTA transaction, you invoke the
begin, commit, and rollback methods of the UserTransaction interface.
-
The following code, taken from the
TellerEJB
example program, demonstrates the
UserTransaction methods. The begin and commit
invocations delimit the updates to the database. If the updates fail, the
code invokes the rollback method and throws an EJBException.
public void withdrawCash(double amount) {
UserTransaction ut = context.getUserTransaction();
try {
ut.begin();
updateChecking(amount);
machineBalance -= amount;
insertMachine(machineBalance);
ut.commit();
} catch (Exception ex) {
try {
ut.rollback();
} catch (SystemException syex) {
throw new EJBException
("Rollback failed: " + syex.getMessage());
}
throw new EJBException
("Transaction failed: " + ex.getMessage());
}
}
Returning Without
Committing
-
In a stateless session bean
with bean-managed transactions, a business method must commit or roll back a
transaction before returning. However, a stateful session bean does not have
this restriction.
-
In a stateful session bean with a JTA
transaction, the association between the bean instance and the transaction
is retained across multiple client calls. Even if each business method
called by the client opens and closes the database connection, the
association is retained until the instance completes the transaction.
-
In a stateful session bean with a JDBC
transaction, the JDBC connection retains the association between the bean
instance and the transaction across multiple calls. If the connection is
closed, the association is not retained.
Methods Not Allowed in
Bean-Managed Transactions
-
Do not invoke the
getRollbackOnly and
setRollbackOnly methods of the EJBContext interface. These methods should be used only in
container-managed transactions.
-
For bean-managed
transactions you invoke the the
getStatus and rollback methods of the UserTransaction
interface.
Summary of Transaction Options
The decision tree in figure
6-2 shows the different approaches to transaction management that you may
take.
-
Your first choice depends on whether the
enterprise bean is an entity or a session bean. An entity bean must use
container-managed transactions.
-
With container-managed transactions, you
specify the transaction attributes in the deployment descriptor and you roll
back a transaction with the
setRollbackOnly method of the EJBContext interface.
-
A session bean may have either
container-managed or bean-managed transactions. There are two types of
bean-managed transactions: JDBC and JTA transactions. You delimit JDBC
transactions with the
commit and rollback methods of the Connection interface. To
demarcate JTA transactions, you invoke the begin, commit, and rollback methods
of the UserTransaction interface.
-
In a session bean with bean-managed
transactions, it is possible to mix JDBC and JTA transactions. This practice
is not recommended, however, because it could make your code difficult to
debug and maintain.
-
If you're unsure about how to set up
transactions in an enterprise bean, here's a tip: In the deployment
descriptor specify container-managed transactions. Then, set the Required
transaction attribute for the entire bean. This approach will work most of
the time.
FIGURE
; Options in Specifying Transactions
Transaction Timeouts
-
For container-managed transactions, you control
the transaction timeout interval by setting the value of the
transaction.timeout property
in the config/default.properties file. For example, you would set the timeout
value to 5 seconds as follows:
transaction.timeout=5
With this setting, if the transaction has not completed within 5
seconds, the EJB container manager rolls it back.
-
When J2EE is first installed, the timeout value
is set to 0:
transaction.timeout=0
If the value is 0, the transaction will not time out.
-
Only enterprise beans with container-managed
transactions are affected by the
transaction.timeout property. For enterprise beans with
bean-managed, JTA transactions, you invoke the setTransactionTimeout method of the UserTransaction
interface.
Isolation Levels
-
Transactions not only
ensure the full completion (or rollback) of the statements that they
enclose, they also isolate the data modified by the statements.
-
The isolation level describes the degree to
which the data being updated is visible to other transactions.
-
If the transaction allows other programs to
read uncommitted data, performance may improve because the other programs
don't have to wait until the transaction ends. But there's a tradeoff-- if
the transaction rolls back, another program might read the wrong data.
-
You cannot modify the isolation level of a
entity beans with container-managed persistence. These beans use the default
isolation level of the DBMS, which is usually READ_COMMITTED.
-
For entity beans with bean-managed persistence
and for all session beans, you can set the isolation level programmatically
with the API provided by the underlying DBMS. A DBMS, for example, might
allow you to permit uncommitted reads by invoking the
setTransactionIsolation method:
Connection con; ...
con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);
-
Do not change the isolation level in the middle
of a transaction. Usually, such a change causes the DBMS software to issue
an implicit commit. Because the isolation levels offered by DBMS vendors may
vary, you should check the DBMS documentation for more information.
Updating Multiple Databases
-
The J2EE transaction
manager controls all enterprise bean transactions except for bean-managed
JDBC transactions.
-
The J2EE transaction manager allows an
enterprise bean to update multiple databases within a transaction. The
figures that follow show two scenarios for updating multiple databases in a
single transaction.
In figure 6-3, the client
invokes a business method in Bean-A. The business method begins a transaction,
updates Database-X, updates Database-Y, and invokes a business method in
Bean-B. The second business method updates Database-Z and returns control to
the the business method in Bean-A, which commits the transaction. All three
database updates occur in the same transaction.
FIGURE 6-3 Updating Multiple
Databases
In figure 6-4, the client
calls a business method in Bean-A, which begins a transaction and updates
Database-X. Then, Bean-A invokes a method in Bean-B, which resides in a remote
J2EE server. The method in Bean-B updates Database-Y. The transaction managers
of the J2EE servers ensure that both databases are updated in the same
transaction.
FIGURE 6-4 Updating Multiple
Databases Across J2EE Servers
Security
·
You declare the security
attributes of an enterprise bean in with the Application Deployment
Tool.
·
This declarative
approach to security enforcement has two major advantages.
o
First, you save time
because you don't have to code and debug security routines in your
enterprise beans or their clients.
o
Second, the administrator of
the J2EE server can customize the security attributes for a
particular production environment at deployment time.
·
The J2EE server enforces
security at two levels:
Authentication
and
Authorization.
Authentication
·
Authentication
is the process by which a user proves his or her identity to a system.
·
The J2EE server controls
client access with a distributed authentication service.
·
This service controls
whether or not a J2EE user can access the components within a J2EE
application.
·
In a commercial
implementation of J2EE, for example, a J2EE user and an operating system user
might be the same, but in the J2EE SDK they are not.
J2EE Users, Realms, and
Groups
·
A J2EE user is
similar to an operating system user. Typically, both types of
users represent people. However, these two types of users are not the same.
·
The J2EE authentication
service has no knowledge of the user and password you provide when logging on
to the operating system.
·
The J2EE authentication
service is not connected to the security mechanism of the operating system.
The two security services manage users that belong to different realms.
·
A realm is a
collection of users that are controlled by the same authentication
policy. The J2EE authentication service governs users in two realms:
certificate and default.
·
Certificates are used with
the HTTPS protocol to authenticate Web browser clients
·
To verify the identity of a
user in the certificate realm, the authentication service verifies a
X509 certificate. The common name field of the X509 certificate
is used as the principal name.
·
In most cases, the J2EE
authentication service verifies user identity by checking the default realm.
This realm is used for the authentication of all clients except for Web
browser clients that use the HTTPS protocol and certificates.
·
A J2EE user of the
default realm may belong to J2EE group. (A user in
the certificate realm may not.)
·
A group is a
category of users, classified by common traits such as job title
or customer profile. For example, most customers of an e-commerce application
might belong to the CUSTOMER group, but the big spenders would belong to the
PREFERRED group.
·
Categorizing users into
groups makes it easier to control the access of large numbers of
users. A later section,
Authorization,
discusses controlling user access to enterprise beans.
Client Authentication
-
The J2EE authentication
service controls access from all types of bean clients:
-
J2EE application clients,
-
stand-alone Java applications, and
-
web components.
-
When a J2EE application client
starts running, its container pops open a window that requests the
J2EE user name and password. The authentication service
verifies that the user name and password from the log-on window exist in the
default realm. After authentication, the user's security
context is associated with any call that the client makes to
enterprise beans deployed in the J2EE server.
-
Most of the examples in this book feature
clients that are stand-alone Java applications. Because these clients do not
log on, they are assigned the unauthenticated and anonymous user named
guest.
(The password is guest123.)
-
Other types of clients, including Web browsers,
may also access the J2EE server without authentication. Such clients are
always assigned the user
guest, indicating that their access in
unauthenticated.
-
Many applications do not require
authentication. For example, an online product catalog would not force
customers to log on if they are merely browsing. Also, when you first start
developing an application, you may find it convenient to allow anyone (
guest)
to access the application's components.
-
During deployment, you specify whether or not a
web component is a protected resource. If the web component is unprotected,
anyone may access it from their browser. If an unprotected web component
accesses an enterprise bean, the authentication service assigns it a
certificate for the
guest user. Any subsequent calls to enterprise beans are
associated with the guest user.
-
If a web component is protected,
you may specify three types of authentication: basic, form,
and certificate. With basic authentication, the server
instructs the Web browser to prompt for the user name and password. With
form authentication, you can specify the .html form or .jsp
file that prompts for the user name and security:passwordspassword. With
certificate authentication, the server requests a certificate
from the browser. In all types of authentication, if the web component calls
as enterprise bean, the call is associated with the authenticated user.
## Authorization
-
Authorization
is the process by which the J2EE server grants or denies permission to
invoke the methods of an enterprise bean.
-
You define authorization in the enterprise
bean's security attributes in three steps:
Declaring Roles
-
When you design an
enterprise bean, you should keep in mind what types of users will access the
bean. For example, an Account enterprise bean might be accessed by
customers, bank tellers, and branch managers. Each of these user categories
is called a role.
-
A J2EE group also represents a category of
users, but it has a different scope than a role.
-
A J2EE group is designated for
the entire J2EE server, whereas a role covers only a specific
application in a J2EE server.
-
To create a role for an application, you
declare it for the EJB .jar or web component (.war) files contained in the
application.
Declaring Method
Permissions
-
After you've defined the
roles, you're ready to define the method permissions of an enterprise bean.
-
Method permissions indicate which roles are
allowed to invoke which methods.
-
You specify method permissions by mapping roles
to methods with the Application Deployment Tool
Mapping
Roles to J2EE Users and Groups
-
When you are developing an
enterprise bean, you should know the roles of your users, but you probably
won't know exactly who the users will be. That's okay, because after your
bean has been deployed the administrator of the J2EE server will map the
roles to the J2EE users (or groups) of the default realm.
-
Using the Application Deployment Tool, the
administrator maps roles to J2EE users and groups
-
By default, the Role Name table assigns the
ANYONE role to a method. The
guest user, which is anonymous and
unauthenticated, belongs to the ANYONE role. Therefore, if you do not map
the roles, any user may invoke the methods of an enterprise bean.
Scenarios
The scenarios in this section
show how authentication and authorization work together to manage security for
J2EE applications.
J2EE Application
Client
In this scenario, an employee
named Bob has moved and he wishes to update his home address for his company's
records. The company that Bob works for has a J2EE application that allows
employees to update their personal information. Figure 8-1 illustrates this
application. To change his address, Bob runs a J2EE application client that
invokes the update method in the Employee enterprise bean.
Before Bob runs the client,
the J2EE administrator sets up the security as follows:
·
Only the Administrator and
RegularEmployee roles may invoke the update method of the Employee enterprise
bean.
·
The J2EE group named
FullEmployee belongs to the RegularEmployee role.
·
The J2EE user Bob belongs to
the FullEmployee group in the default realm.
The J2EE server performs the
following security checks at run time:
1. When the J2EE application client starts
running it opens a dialog that prompts for the J2EE user name and password,
which Bob enters.
2. The authentication service
verifies that Bob's user name and password exist in the default realm.
3. Bob clicks the update
button in the client, which attempts to invoke the update method of the Employee
enterprise bean.
4. The EJB container performs
authorization. It verifies that the RegularEmployee role, to which Bob's group
(FullEmployee) belongs, has permission to invoke the update method.
FIGURE 8-1 Authenticated
Access to an Enteprise Bean
Web Browser Client
In the next scenario,
illustrated in figure 8-2, Mary transfers money between her savings and
checking accounts from her Web browser. To transfer the funds, Mary enters a
URL that accesses a JSP component. This component calls a
JavaBeansTM component, which invokes the transfer method of the Account
enterprise bean.
The J2EE administrator
enforces security with these rules:
·
The JSP component is a
protected resource.
·
Only the Customer role may
invoke the transfer method of the Account enterprise
bean.
·
The J2EE group named
CurrentCustomer belongs to the Customer role.
·
Mary's J2EE user belongs to
the CurrentCustomer group in the default realm.
When Mary transfers the
funds, the J2EE server enforces security as follows:
1. Mary's browser attempts to
access the JSP component.
2. Because the component is a
protected resource, authentication is required. The Web service requests the
Web browser to prompt for the J2EE user name and password.
3. Mary enters her J2EE user
name and password, which are passed back to the J2EE server.
4. The authentication service verifies that the
user name and password exist in the default realm.
5. The Web browser is allowed
to access the JSP component.
6. Mary clicks the Transfer
button on the form generated by the JSP component, which calls a JavaBeans
component.
7. The JavaBeans component
attempts to invoke the transfer method of the Account enterprise bean.
8. Mary's J2EE group
(CurrentCustomer) belongs to the Customer role, which is allowed to invoke the
transfer method. Therefore, the EJB container authorizes the invocation.
FIGURE 8-2 Authenticated
Access to a JSP Component and an
Enterprise
Bean
Bean-Managed Security
-
The security mechanisms
described in the
Authentication
and
Authorization
sections are sufficient for most J2EE applications.
-
You control these mechanisms by declaring
certain parameters with the Application Deployment Tool. Because this
approach is declarative, you don't have to code your own security routines.
-
Some applications have special security
requirements. For example, an application might make authorization decisions
based on the time of day, the parameters of a call, or the internal state of
an enterprise bean. Another application might restrict access based on user
information stored in a database.
-
If your application has special security
requirements, you may want to take advantage of the APIs described in the
following sections.
Getting the Caller's J2EE
User
·
The getCallerPrincipal method of the
EJBContext interface returns the java.security.Principal object that identifies the caller of the
enterprise bean. (In this case, a principal is the same as a user.) In the
following example, the getUser method of an enterprise bean returns the name of
the J2EE user that invoked it:
public String getUser() { return sessioncontext.getCallerPrincipal ().getName(); }
·
To determine the caller of a
servlet, you invoke the getUserPrincipal method.
Determining the Caller's
Role
·
You can determine whether an
enterprise bean's caller belongs to a particular role by invoking the isCallerInRole
method: boolean result =
context.isCallerInRole("Customer");
·
To determine the caller's
role for a servlet, you invoke the isUserInRole method.
Security Policy Files
-
The J2EE server
policy file is named
server.policy. It resides in the $J2EE_HOME/lib/security directory.
-
The J2EE application client policy file,
client.policy ,
resides in the same directory.
Database Connections
·
The EJB container maintains
the pool of database connections.
·
This pool is transparent to
the enterprise beans.
·
When an enterprise bean
requests a connection, the container fetches one from the pool and assigns it
to the bean. Because the time-consuming connection has already been made, the
bean quickly gets a connection. The bean may release the connection after each
database call, since it can rapidly get another connection.
·
And because such a bean
holds the connection for a short time, the same connection may be shared
sequentially by many beans.
·
The persistence type of the
enterprise bean determines whether or not you code the connection routine.
·
You must code the connection
for enterprise beans that access a database and do not have container-managed
persistence. Such beans include entity beans with bean-managed persistence and
session beans.
·
For entity beans with
container-managed persistence, the Application Deployment Tool generates the
connect routines for you.
Coded Connections
-
The bean routine that connects to the database
should not hardcode the actual name (URL) of the database.
Instead, it should refer to the database with a logical name
and use a JNDI
lookup when obtaining the database connection.
This level of indirection provides several benefits:
-
You can deploy the same enterprise bean in
different environments that have databases with different
names.
-
You can re-use the enterprise bean in
multiple applications.
-
You can assemble the enterprise beans into
applications that run in a distributed environment. (The enterprise beans
and the databases they access may run on different machines.)
-
A resource
manager is a storage mechanism such as a DBMS.
-
A resource manager connection
is an object, such as
java.sql.Connection, that represents a session with the resource
manager (DBMS).
-
A resource manager connection
factory is an object that creates resource manager connections. For
example, a
javax.sql.DataSource object is a connection factory because it
creates a java.sql.Connection object.
How to Connect
The code examples in this
section are from the the
AccountEJB
class, which was described in the the
Entity
Beans chapter. Because the AccountEJB class uses bean-managed persistence, it
connects to the database with the following steps:
1. Specify the logical
database name.
· private String dbName = "java:comp/env/jdbc/AccountDB";
·
The java:comp/env/ prefix is the
JNDI context for the component.
·
The jdbc/AccountDB string is the
logical database name.
2. Obtain the DataSource
associated with the logical name.
· InitialContext ic = new InitialContext();
· DataSource ds = (DataSource) ic.lookup(dbName);
3. Get the Connection from the DataSource.
o Connection con = ds.getConnection();
When To Connect
-
When coding an enterprise
bean, you must decide how long the bean will retain the connection.
-
Generally you have two choices: either hold the
connection for the lifetime of the bean, or only during each database call.
-
Your choice determines the method (or methods)
in which your bean connects to a database.
Longterm
Connections
-
You can design an
enterprise bean that holds a database connection for its entire lifetime.
-
Because the bean connects and disconnects just
once, its code is slightly easier to write.
-
But there's a tradeoff-- other enterprise beans
may not acquire the connection. Session and entity beans issue the lifelong
connections in different methods.
Session Beans
-
The EJB container invokes the
ejbCreate method at
the beginning of a session bean's life cycle, and invokes the ejbRemove method
at the end. To retain a connection for the lifetime of a session bean, you
connect to the database in ejbCreate and disconnect in ejbRemove.
-
If the session bean
is stateful, you must also connect in
ejbActivate and disconnect in
ejbPassivate. A stateful session bean requires these additional calls because the
EJB container may passivate the bean during its lifetime. During
passivation, a stateful session bean is saved in secondary storage, but a
database connection may not be saved in this manner.
-
Because a stateless session bean cannot be
passivated, it does not require the additional calls in
ejbActivate and ejbPassivate.
Entity Beans
-
After instantiating an
entity bean and moving it to the pooled stage, the EJB container invokes the
setEntityContext method. Conversely, the EJB container invokes the unsetEntityContext method when
the entity bean leaves the pooled stage and becomes eligible for garbage
collection.
-
To retain a database connection for its entire
lifespan, an entity bean connects in the
setEntityContext method and disconnects in the
unsetEntityContext method.
Short-term
Connections
-
Briefly held connections
allow many enterprise beans to share the same
connection.
-
Because the EJB
container manages a pool of database connections, enterprise beans can
quickly obtain and release the connections.
-
For example, a business method might connect to
a database, insert a row, and then disconnect.
-
In a session bean, a business method that
connects to a database should be transactional. The transaction will help
maintain data integrity.
Container-Managed Connections
-
With container-managed
persistence, the entity bean class does not contain the code that connects
to a database. Instead, this code is generated by the Application Deployment
Tool. Using the tool, you specify the JNDI name of the database in the JNDI
Name field of the Deployment Settings dialog box.
|