You are on page 1of 86

1/86 2/9/2008

SCBCD FOR J2EE 1.3 (CX-310-090) - CONTENTS


INTRODUCTION..........................................................................................................................................3
SOA and Web Services............................................................................................................................3
EJB Ecosystem........................................................................................................................................3
J2EE Technologies..................................................................................................................................4
Java RMI-IIOP.......................................................................................................................................5
JNDI........................................................................................................................................................6
Integrating RMI-IIOP and JNDI............................................................................................................8
EJB Fundamentals..................................................................................................................................8
Middleware.............................................................................................................................................8
EJB Object..............................................................................................................................................9
Remote Interface.....................................................................................................................................9
Home Interface and Object.....................................................................................................................9
Local Interface......................................................................................................................................10
Deployement Descriptor.......................................................................................................................11
SESSION BEANS.........................................................................................................................................11
Lifecycle................................................................................................................................................11
Stateful Session Beans..........................................................................................................................13
Stateless Session Beans.........................................................................................................................13
Comparing Stateful and Stateless Session Beans.................................................................................13
Remote Interface:..................................................................................................................................14
Local Interface:....................................................................................................................................14
Home Interface:....................................................................................................................................15
Local Home Interface ..........................................................................................................................16
Session Bean Class...............................................................................................................................16
EJB Context..........................................................................................................................................17
Deployement Descriptor.......................................................................................................................17
EJB Jar file...........................................................................................................................................18
Client code............................................................................................................................................19
To Remember….....................................................................................................................................20
WEBSERVICES USING STATELESS SESSION BEANS......................................................................20
WSDL....................................................................................................................................................21
ENTITY BEANS...........................................................................................................................................24
Load and Store......................................................................................................................................25
Types ....................................................................................................................................................25
Create and Remove...............................................................................................................................25
Entity Context ......................................................................................................................................26
getPrimaryKey() : ................................................................................................................................26
Finder methods:....................................................................................................................................26
BEAN MANAGED PERSISTENT (BMP) ENTITY BEANS..................................................................27
BMP ENTITY BEAN WITH LOCAL INTERFACE.......................................................................................................28
Local interface......................................................................................................................................28
Local Home Interface...........................................................................................................................29
Primary Key class.................................................................................................................................29
Custom Exception (Application Level).................................................................................................30
Entity Bean Class..................................................................................................................................30
Deployment Descriptor.........................................................................................................................36
Client Code...........................................................................................................................................38
CONTAINER MANAGED PERSISTENT (CMP) ENTITY BEANS.....................................................41

© 2006, Watsh Rajneesh. All Rights Reserved.


2/86 2/9/2008

Abstract Persistence Schema................................................................................................................42


EJB QL .................................................................................................................................................42
ejbSelect() – only in CMP.....................................................................................................................42
Bean Class Code...................................................................................................................................44
Deployment Descriptor.........................................................................................................................47
MESSAGE DRIVEN BEAN........................................................................................................................48
Java Messaging Service (JMS).............................................................................................................49
Messaging Domains..............................................................................................................................49
JMS Programming Model.....................................................................................................................50
Bean class.............................................................................................................................................52
Client (Message Producer)...................................................................................................................53
Deployment Descriptor.........................................................................................................................55
EJB ENVIRONMENT & BEST PRACTICES..........................................................................................60
EJB References.....................................................................................................................................61
Resource Factories...............................................................................................................................62
Environment Properties........................................................................................................................63
EJB Object Handles..............................................................................................................................63
Home Handles......................................................................................................................................64
TRANSACTIONS.........................................................................................................................................66
Transaction Jargons.............................................................................................................................67
Transactional Models...........................................................................................................................67
Transaction Attributes...........................................................................................................................69
Java Transaction API (JTA)..................................................................................................................72
Transaction Isolation............................................................................................................................74
Durability and Two phase commit protocol..........................................................................................75
SECURITY....................................................................................................................................................76
EJB TIMER SERVICE................................................................................................................................77
RELATIONSHIP BETWEEN ENTITY BEANS......................................................................................77
Cardinality............................................................................................................................................77
Directionality........................................................................................................................................83
Aggregation vs Composition and Cascading Deletes...........................................................................84
EJB INTEGRATION (JCA)........................................................................................................................85
EJB PERFORMANCE TUNING...............................................................................................................85
CLUSTERING..............................................................................................................................................86
SAMPLE APPLICATION...........................................................................................................................86

Revision # Date Changes


0.1 16th May, 2006 Initial Version.

Disclaimer: This document is my notes taken from the book Mastering EJB 3rd Edn. by Ed Roman et al and
Head First EJB by Kathy Sierra and Bert Bates. This document covers more than the syllabus for the
SCBDC exam and is well suited for revising the concepts of EJB 2.0 and 2.1.

© 2006, Watsh Rajneesh. All Rights Reserved.


3/86 2/9/2008

Introduction
EJB is about rapid application development for the server side; you can quickly
and easily construct server-side components in Java by leveraging a prewritten
distributed infrastructure provided by the industry. EJB is designed to support
application portability and reusability across any vendor’s enterprise
middleware services.

SOA and Web Services


A service-oriented architecture (SOA) thus is a paradigm focusing on development of
services rather than piecemeal components such that these services provide a higher
level of abstraction from a
functional standpoint. Of course, there are more properties to SOA than mere coarse-
granularity. One such characteristic property of SOA is that they are autonomous in
nature. These independent entities can interact with others in spite of differences in
the way they have been implemented or the platform
they have been deployed on. The notion of putting together (integrating) such
autonomous and loosely coupled services to address the changing business needs
has a huge value proposition and it is well on its way to realization with the
emergence of various choreography, orchestration and collaboration technologies
such as WS-BPEL, EbXML BPSS, and WS Choreography.

SOA is a paradigm. There are many possible ways of building software so that it
implements salient features of SOA, mainly coarse granularity and loose coupling.
One such way is Web services.

Simple Object Access Protocol (SOAP) is an XML-based application-level protocol


intended for exchanging information in a distributed network. SOAP supports both the
models of distributed computing: RPC as well as document style messaging. RPC
style SOAP allows remote invocation of operations. Parameters and return in/out
values of these operations are serialized in XML. Whereas, in document-style SOAP
because an operation’s input and output are XML, serialization of parameters and
return value to XML is not needed.

Web Service Description Language (WSDL) is an XML-based metadata standard that


is used to describe the service interface—in terms of the operations it supports, the
parameters that the operations accept, and their return values in case of SOAP RPC,
the XML schema that the input and output messages to the operations in case of
document-style SOAP—as well as service binding information— in terms of the
communication protocols, ports, service URL, and so on.

SOA is not a replacement for component architecture; rather it neatly


complements the component architecture. While component architectures
enhance reusability at a finer grain level, SOA can enhance reusability at a
coarser grained level. Hence, from an implementation standpoint, a given
service might very well be developed using well-defined component
frameworks such as EJB. The latest EJB standard, therefore, has in-built support for
Web Services, the most popular stack for building SOA.

EJB Ecosystem
Bean Provider (Internal department Developers writing the EJBs.
providing EJBs to other departments

© 2006, Watsh Rajneesh. All Rights Reserved.


4/86 2/9/2008

or third party vendor).


Application Assembler (System  Assemble the beans to make an application.
integrators, a consulting firm or in-  Supply a UI (standalone or web based) or webservice.
house programmer.)  Write new EJB to solve application specific problem.
 Code that conncets the EJBs provided by bean providers
with the application code.

EJB Deployer (a staff person, a  Securing deployement within h/w or s/w firewall.
vendor or consultant).  Integrating with enterprise security and policy
repositories, which oftentimes is an LDAP server
 Choosing h/w to host the application.
 Providing redundant h/w for clustering.
 Performance tuning the system (by modifying the
deployement descriptors).
System Administrator  Oversee the stability of operational system.
 Upkeep and monitoring of deployed system making use
of management tools that the EJB server provides (JMX
console of JBoss) or Weblogic AS provides SNMP
manageability.
Server Provider (BEA, IBM, Provides EJB container (Application Server).
JBoss(now Redhat)).
Tools Vendor (BEA Weblogic Provide IDEs to build/debug EJBs.
Workshop, IBM Websphere
Application Studio, Eclipse, Netbeans,
IntelliJ IDEA).
Bean provider, application assembler and deployer could be the same person for small companies.

J2EE Technologies
EJB 2.1 Defines how server side components are written and provides a
standard contract between components and application server
(container).
JAX-RPC Support for developing Webservices. Defines two webservices
endpoint models: one based on servlet and other based on
stateless session EJB.
RMI-IIOP Extension of RMI for CORBA integration.
JNDI Used to access naming and directory systems such as Microsoft
Exchange or Lotus Notes.
JTA & JTS Allow for components to be bolstered with transaction support.
JMS Allows for J2EE deployement to communicate using messaging
within and outside the J2EE system. You can connect to existing
MOM (message oriented middleware – IBM MQSeries or MS
MQ). Messaging is an alternative to RMI-IIOP.
JCA Enable J2EE systems to access existing EIS such as mainframe
systems running high-end transactions (like IBM CICS, BEA
TUXEDO), ERP systems or prorietary systems. ISVs such as
SAP, Siebel, PeopleSoft (now Oracle) who want their software to
be accessible from within J2EE application servers can write
standard J2EE connectors which will act similar to JDBC service
provider jars.
JAXP API for parsing XML documents. Is implementation neutral
interface to XMP parsing technologies such as DOM and SAX.
So you can plugin a DOM/SAX parser implementation like
Xerces for Java and use Xerces from JAXP APIs.

© 2006, Watsh Rajneesh. All Rights Reserved.


5/86 2/9/2008

JAAS Standard API for performing security related operations.

Java RMI-IIOP
RMI-IIOP is special version of RMI that is compliant with CORBA and uses both java.rmi and javax.rmi.
RMI-IIOP lacks some features present in RMI like:
 Distributed garbage collection.
 Object activation.
 Downloadable class files.

RMI-IIOP supports both pass-by-reference and pass-by-value models. Following are the steps to build an
RMI-IIOP application:

1. When using RMI-IIOP you must build a custom interface called Remote Interface which extends
java.rmi.Remote.

import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* The remote interface for the remote object. Clients use this
* remote interface to perform any operations on the remote object.
*/
public interface IPKGenerator extends Remote {
public long generate() throws RemoteException;
}

2. To make your object available as a remote object and allow remote hosts to invoke its methods,
your remote class must either
a. extend the javax.rmi.PortableRemoteObject class or
b. in case your class already extends some other class then you can manually export your
object so that it is available to be invoked on by remote hosts by calling
javax.rmi.PortalRemoteObject.exportObject().

import java.rmi.RemoteException;
import javax.rmi.PortableRemoteObject;
/**
* The remote object which generates primary keys
*/
public class PKGenerator extends PortableRemoteObject implements IPKGenerator {
/*
* Our remote object’s constructor
*/
public PKGenerator() throws Exception, RemoteException {
/*
* Since we extend PortableRemoteObject, the super
* class will export our remote object here.
*/
super();
}

/*
* Generates a unique primary key
*/
public synchronized long generate() throws RemoteException {
return i++;
}
private static long i = System.currentTimeMillis();
}
The remote object can be made unavailable for remote method invocation by calling
javax.rmi.PortableRemoteObject.unexportObject().

© 2006, Watsh Rajneesh. All Rights Reserved.


6/86 2/9/2008

2. rmic compiler can be used to generate the stub and skeleton which are proxy’s responsible for
delegating the calls made to remote methods to their implementations.
3. Passing parameters by value for object type requires the object type to be serializable.
4. Passing object type parameters by reference is achieved when parameter object is itself a remote
object. So when the client makes a remote method call on the server and passes a remote object
reference of a remote object living on the client machine then the stub to that remote object
reference is serialized (and not the whole object). So the server can connect to the remote object
living on client machine and invoke methods on that. Java RMI-IIOP thus simulates the pass-by-
reference by passing serializable stub, rather than serializing the original object. So, by making
your parameters remote objects, you can effectively avoid the network lag in passing large objects.

Note: the Java RMI-IIOP stubs are serializable always.


In summary, following are the rules for passing objects using Java RMI-IIOP:

1. All Java primitives are passed by value when calling methods remotely.
2. If you want to pass an object by value, it must implement java.lang.Serializable interface.
Anything referenced from within the object must also be serializable.
3. If you want to pass an object by reference, it must be a remote object, and it must
implement java.rmi.Remote interface. A stub for the remote object is serialized and
passed to the remote host.
 A way to publish the server and have client locate the server is called bootstrapping and is
achieved by JNDI.

JNDI
JNDI provides standard inteface for locating users, machines, networks, objects and services by name.
Example, locating a printer on the network by name, locating java object or locating a datasource to
connect to a database. In J2EE the uses of JNDI are:
1. acquire a reference to the Java Transaction API (JTA) UserTransaction interface
2. connect to resource factories such as, JDBC drivers or JMS drivers.
3. for beans to lookup other beans.

Naming service:
 Associates names with objects (binding names to objects).
 Provides a facility to find an object by name (resolving a name to an object reference).
Example, filesystem (file name to file handle), DNS (machine name to IP address).

A directory object is a special type of object stored with the naming service which can be used to store
attributes. Eg. You can use a directory object to represent a user storing information about user, like user
loginid, password, email, phone etc as its attributes. So your application can lookup the user credentials
stored in the directory object of the naming service to authenticate the user.

A directory service is a naming service enhanced to provide directory object operations for manipulating
attributes. Eg, (MS Active Directory Service, Netscape Directory Server).

Directory is a system of directory objects that are all connected in a hierarchical tree structure with a root
representing your company as shown below:

© 2006, Watsh Rajneesh. All Rights Reserved.


7/86 2/9/2008

Most directories are implemented by a database behind the scene to store the hierarchical directory objects.

There are several directory protocols for accessing a directory service eg. LDAP (Light weight directory
access protocol) or Novell’s Network Directory System (NDS) or Network Information System (NIS).

IBM’s Lotus Notes and Microsoft Active Directory are both LDAP based. But not all directory services are
LDAP based. JNDI is a bridge over naming and directory services providing common interface to disparate
directories.

Similar to JDBC, JNDI has two halves:


1. API – allows clients to code to a single unified interface
2. SPI – allows naming and directory service vendors to fit their particular proprietary protocols into
the system.

Like the database vendors provide JDBC drivers, directory service vendors provide JNDI service
providers to access their specific directories. The providers are aware of specific directory protocols and
they plugin to the JNDI SPI.

LDAP service provider would know how to map JNDI client API to an LDAP operation. Service providers
exist for LDAP, NIS, NDS, SLP, CORBA NS, File System, RMI-IIOP tnameserv, and many more.

Application servers also ship JNDI naming service implementation.

 Binding: associating name with an object.


 Context: set of zero or more bindings.
 Subcontext: is a full fledged context in its own right and can contain more name bindings.
 Naming system: is a connected set of contexts that use the same name syntax. (eg branch of
LDAP tree or a folder tree in file system).
 Namespace: set of names contained within a naming system.

© 2006, Watsh Rajneesh. All Rights Reserved.


8/86 2/9/2008

 Composite name: name that spans multiple naming systems. Eg.


http://java.sun.com/products/ejb/index.jsp is composed of namespaces:
o http: url scheme id namespace.
o java.sun.com – uses DNS to resolve to ip address
o products/ejb/index.jsp: are from filesystem namespace on webserver.
 Initial Context: is starting point of exploring a namespace. (root node of the naming system).

To acquire an initial context in JNDI, we use an initial context factory (implemented by JNDI service
provider) which returns the initial context for the naming system. To get an initial context for a certain
naming system you need to provide the following information about the naming system:
o IP address of the naming system
o Port number at which the naming service is listening
o Starting location within the JNDI tree
o User name and passwd for authenticating to the naming service (if applicable).

Note: Naming graphs needed not be trees. They may have more than one root. Subcontexts can be bound in
more than one context, so a single subcontext may be known under more than one name.

Integrating RMI-IIOP and JNDI


1. Binding RMI-IIOP Server to JNDI

2. Looking up an RMI-IIOP server with JNDI

EJB Fundamentals
Session Beans Model business processes.
Entity Beans Model business data.
Message driven Beans Can be called only implicitly by sending messages to those beans. Eg. Stock
trade messages, credit card authorization messages, workflow messages.

Middleware
When distributed system grows larger, we need to employ middleware services for transaction, security,
persistence, etc.

Explicit Middleware: involves purchasing a middleware off the shelf and writing code that calls the
middleware’s API. More like Bean managed transaction/persistence/security. Business logic gets intwined
with the logic to call these middleware APIs. Example of such systems are: traditional CICS or TUXEDO
based mainframe systems, CORBA, DCOM or RMI.

Implicit/Declarative Middleware: New component based technologies like EJB, .NET and CORBA
Component Model enable you to harness the complex middleware in enterprise applications without
writing to the middleware APIs. More like Container Managed transaction/persistence/security. You just do
the following:
1. Write distributed object business logic only.
2. Declare middleware services that your distributed object needs in separate descriptor files.
3. The application server will generate the request interceptor from the configuration obtained from
the descriptor files.
4. Request interceptor will intercept requests from client, perform middleware services that your
distributed object needs and then delegates the call to the distributed object.

© 2006, Watsh Rajneesh. All Rights Reserved.


9/86 2/9/2008

EJB Object
EJB is not full fledged remote object. Clients never invoke the business method directly on actual bean
instance. Rather, the EJB container intercepts the request, performs the implicit middleware and delegates
to the bean instance. EJB container handles networking for you by wrapping your bean in a network
enabled object. Middleware services at the point of interception include:
1. Transaction service
2. Security service
3. Resource management: for resources like threads, database connections etc.
4. Lifecycle management of the beans: pooling the beans, activating/passivating etc.
5. Persistence service
6. Handle concurrent requests – either by allowing serial access to the bean instance or allowing
other bean instances in the pool to service the request.
Thus, EJB container acts as a layer of indirection between client and the bean by providing a network
aware wrapper object called EJB Object. EJB Object is the request interceptor. They have container
specific code inside them (each container handles middleware differently). EJB Object class file is
generated automatically by the container.
public interface javax.ejb.EJBObject extends java.rmi.Remote
{
public javax.ejb.EJBHome getEJBHome() throws java.rmi.RemoteException;
public java.lang.Object getPrimaryKey() throws java.rmi.RemoteException;
public void remove() throws java.rmi.RemoteException, javax.ejb.RemoveException;
public javax.ejb.Handle getHandle() throws java.rmi.RemoteException;
public boolean isIdentical(javax.ejb.EJBObject) throws java.rmi.RemoteException;
}

Remote Interface
For the container to know what business methods have to made remote you will need to provide a Remote
interface which mentions all business methods that bean class exposes. Your remote interface extends the
javax.ejb.EJBObject interface mentioning all business methods of your bean. When a client invokes any of
these business methods, the EJBObject delegates the method to its corresponding implementation, which
resides in the bean itself.

So the container provided EJBObject concrete implementation implements the Remote interface we create
and provides an implementation for the methods in the javax.ejb.EJBObject interface plus implementation
of the business methods which simply call the business method implementation in your bean class.

java.rmi.Remote
extended by javax.ejb.EJBObject
extended by <YourBean>Remote

Container generated concrete class might look like this:

class <YourBean>EJBObjectImpl implements <YourBean>Remote


{
// override all methods in javax.ejb.EJBObject

// override all methods in <YourBean>Remote


// provide middleware services based on confign. in deployement descriptor – implicit middleware
// delegate the call to <YourBean> methods.
}

Home Interface and Object


To acquire a reference to an EJB object, your client code asks for an EJB object from an EJB object factory.
This factory is resposible for instatiating and destroying EJB objects. This factory is the Home object.

© 2006, Watsh Rajneesh. All Rights Reserved.


10/86 2/9/2008

Home object is generated by the container and implements the Home interface where you provide
information to the container about how your bean instance has to be initialized while instantiating. Even
instantiation of the bean will be done via the EJB object instance.

public interface javax.ejb.EJBHome extends java.rmi.Remote


{
public EJBMetaData getEJBMetaData() throws java.rmi.RemoteException;
public javax.ejb.HomeHandle getHomeHandle() throws java.rmi.RemoteException;
public void remove(javax.ejb.Handle handle) throws java.rmi.RemoteException,
javax.ejb.RemoveException;
public void remove(Object primaryKey) throws java.rmi.RemoteException,
javax.ejb.RemoveException;
}

java.rmi.Remote
extended by javax.ejb.EJBHome
extended by <Your Bean>Home

Container generated Home object concrete implementation will be:


class <YourBean>HomeImpl implements <Your Bean>Home
{
// override methods in javax.ejb.EJBHome interface

// override methods in <Your Bean>Home interface


// delegating calls for create/find/remove to corresponding EJB object
// EJB object in turn delegates to bean instance
// if create – invokes the bean constructor or picks one bean from the instance pool
// if find – invokes the corresponding entity bean’s finder method
// if remove – reinits the state of bean and returns it to instance pool
}

Note: Most containers will have a 1:N relationship between home objects and bean instances. This
means that all clients use the same home object instance to create EJB objects. So a home object will be
implemented by container to be thread safe code as it has to service multiple clients. Your beans will
always be single threaded (ie only one thread at a time will execute methods of a certain bean instance).

Relationship between EJB objects and bean instances may be 1:N (as home objects) or M:N. In the
former case, the EJB object will be single and so will be thread safe. In the later case, there will be as many
EJB objects as there are active client connections (so EJB objects will be single threaded).

Local Interface
Local objects implement local interfaces. Avoids the networking overhead.
public interface javax.ejb.EJBLocalObject {
public javax.ejb.EJBLocalHome getEJBLocalHome() throws javax.ejb.EJBException;
public Object getPrimaryKey() throws javax.ejb.EJBException;
public boolean isIdentical(javax.ejb.EJBLocalObject) throws javax.ejb.EJBException;
public void remove() throws javax.ejb.RemoveException, javax.ejb.EJBException;
}
public interface javax.ejb.EJBLocalHome {
public void remove(java.lang.Object) throws javax.ejb.RemoveException, javax.ejb.EJBException;
}

javax.ejb.EJBLocalObject
extended by <Your Bean>Local

and

© 2006, Watsh Rajneesh. All Rights Reserved.


11/86 2/9/2008

javax.ejb.EJBLocalHome
extended by <Your Bean>LocalHome
Note: Local interface always marshall parameters by reference.

Deployement Descriptor
This is the key to implicit middleware. It is used to inform the container about your middleware needs,
you as a bean provider must declare your components’ middleware service requirements in this file.
Bean Management and How container should manage your beans.
lifecycle requirements o name of bean class
o type of bean (Session, Entity or MDB)
o home interface that generates the beans
o local or remote
Persistence requirements Whether bean or container managed persistence.
(Entity beans only)
Transaction requirements Requirements for running in transactions
Transaction must start whenever anyone calls a bean (Required New)
Transaction may start whenever there is no running transaction (Required) etc
Security requirements Access control entries
Who is allowed to use which beans
Who is allowed to use each method on a particular bean

Vendor Specific files can be used to configure load balancing, clustering, monitoring, pool sizes etc.
EJB-jar file = bean classes + home interfaces + remote interfaces + deployement descriptor.

Session Beans
Session beans are business process objects that implement business logic and workflows. Eg. Price quoting,
order entry, video compression, banking transactions, stock tradesm database operations, complex
calculations etc.

Lifecycle
Lifetime is equivalent of a client session. Session bean instances are not shared between clients. EJB
container may destroy the session bean if client times out. Session beans are non persistent (not saved to
database).

Stateless bean lifecycle:


1. Bean instance does not exist
2. container decides it wants to instantiate a new bean (depends on container’s policy for pooling
beans)
3. container instantiates your bean : container calls class.newInstance(“HelloBean.class”) on your
session bean class.
4. container calls setSessionContext() : associating a bean with context which enables it to make
callbacks to container.
5. container calls ejbCreate() : initializes your bean.
6. container can call business methods on your bean : container can dynamically reassign beans to
client requests at the per-method level.
7. container calls ejbRemove().

© 2006, Watsh Rajneesh. All Rights Reserved.


12/86 2/9/2008

Lifecycle of stateful session bean is similar to that of stateless session bean, except:
1. there is no pool of equivalent instances because each instance contains state.
2. there are transitions for passivating and activating conversational state.

© 2006, Watsh Rajneesh. All Rights Reserved.


13/86 2/9/2008

Stateful Session Beans


Designed to service business processes that span multiple method requests or transactions. They retain the
state on behalf of an individual client. Eg. E-commerce web store and shopping cart.

To limit the number of stateful session bean instances in memory, the container can swap out a stateful
bean, saving its conversational state to a hard disk (passivation). At passivation time the container uses
object serialization to save state of bean (javax.ejb.EnterpriseBean interface extends java.io.Serializable
interface – so every enterprise bean implements this interface). When the original client invokes a method,
the passivated conversational state is swapped in to a bean (activation) which then resumes conversation
with the original client. The bean that receives the activated state may not be the original bean instance that
was passivated. Containers may choose to passivate a bean that has been used least recently (LRU).
Passivation can occur anytime if the bean is not involved in a method call or is not a part of a transaction.
Beans are activated on-demand (as client request comes in). Thus, using passivation/activation, the EJB
container provides effect of instance pooling stateful session beans.

ejbPassivate() – relinquish held resources like database connections, open sockets, open files.
ejbActivate() – restore the open resources it released during ejbPassivate().

Note: in most cases you leave these methods empty. But you may implement them if you do have transient
resources which you donot want to save like socket connections, open files, database connections etc which
you have stored in private member instance variables but that does not make sense to serialize everytime
with the object state.

Stateless Session Beans


Designed to service business processes that span a single method call. The client must pass all client data
that the bean needs as parameters to business logic methods. Eg. High-performance engine that solves
complex mathematical operations in a given input, such as compression of audio/video data (client passing
the buffer of uncompressed data and a compression factor) or a credit card verification component (where
client passes the card number, expiry date, holder’s name and amount to debit as input parameters).

Note:
1. Stateless session beans can contain state that is not specific to any one client, such as database
connection factory that all clients would use.
2. Any stateless bean can service any client request because they are all exactly same. So stateless
session beans can be pooled and reused. Passivation/activation are not required as there isnt any
state to save.
3. Stateless session beans can also be webservice endpoints.

Comparing Stateful and Stateless Session Beans


Method Stateful implementation Stateless Implementation
setSessionContext() Store the context away in a member variable so that context can be queried later.
ejbCreate() Perform any initialization your bean needs Perform any initialization.
such as setting member variables to the
argument values passed in. You can only define an empty
You can define several overloaded ejbCreate() method (with no
ejbCreate() methods, each taking a different parameters). If it had params and
argument. Atleast one ejbCreate() method the bean initialized itself to those
MUST be provided. params the bean would never
remember what it initialized itself
to upon subsequent calls, since its
stateless!

© 2006, Watsh Rajneesh. All Rights Reserved.


14/86 2/9/2008

ejbPassivate() Release resource which are transient or you Not Applicable.


don’t want serialized on passivation.
ejbActivate() Acquire resources release while passivation. Not Applicable.
ejbRemove() Prepare for destruction by releasing resources if any.

Remote Interface:
/**
* This is the HelloBean remote interface.
*
* This interface is what clients operate on when
* they interact with EJB objects. The container
* vendor will implement this interface; the
* implemented object is the EJB object, which
* delegates invocations to the actual bean.
*/
public interface Hello extends javax.ejb.EJBObject
{
/**
* The one method - hello - returns a greeting to the client.
*/
public String hello() throws java.rmi.RemoteException;
}

Local Interface:
/**
* This is the HelloBean local interface.
*
* This interface is what local clients operate
* on when they interact with EJB local objects.

© 2006, Watsh Rajneesh. All Rights Reserved.


15/86 2/9/2008

* The container vendor will implement this


* interface; the implemented object is the
* EJB local object, which delegates invocations
* to the actual bean.
*/
public interface HelloLocal extends javax.ejb.EJBLocalObject
{
/**
* The one method - hello - returns a greeting to the client.
*/
public String hello();
}

Home Interface:
/**
* This is the home interface for HelloBean. This interface
* is implemented by the EJB Server’s tools - the
* implemented object is called the Home Object, and serves
* as a factory for EJB Objects.
*
* One create() method is in this Home Interface, which
* corresponds to the ejbCreate() method in HelloBean.
*/
public interface HelloHome extends javax.ejb.EJBHome
{
/*
* This method creates the EJB Object.
*
* @return The newly created EJB Object.
*/
Hello create() throws java.rmi.RemoteException, javax.ejb.CreateException;
}
create() is the factory method that clients use to get a reference to the EJB Object and it initializes the bean.
Since a remove() method is already there in the EJBHome interface so we donot need to provide that in our
home interface.

Note: create() and remove() are for creation and destruction of an EJB object. The bean instance may not
be destroyed on a remove() or may not be created on create() (rather be dequed from the pool on create()
and returned to the instance pool on remove).

Types of Exceptions thrown by bean:


A remote exception indicates a special error condition – a network failure, machine failure etc.
1. System level exception – critical failure eg database malfunction
2. Application level exception – routine exception eg bad parameter passed to remote method,
warning of an insufficient bank account balance to make withdrawl etc.
EJB container can intercept exceptions and decide whether a client should be shown the exception. If a
bean fails it may be possible to salvage the client’s invocation and redirect to another bean – transparent fail
over.
1. A system level exception is thus intercepted by container and may not be shown to the client.
2. If the failure is fatal then the container can alert the system admin via a monitoring system like
sending an snmp trap/ jmx event which system admin can observe in his monitoring application.
3. EJB object is also responsible for catching all unchecked exceptions that your bean may throw
(such as NullPointerException) which are typically not handled in the bean code. EJB object then
may throw such an unchecked exception back to the client as a remote exception.

In summary,
1. Application level exceptions are always thrown back to client. This includes any exception that
bean defines and javax.ejb.CreateException or javax.ejb.FindException.
2. For system level exceptions, EJB container can handle the exception and

© 2006, Watsh Rajneesh. All Rights Reserved.


16/86 2/9/2008

a. Inform the system admin with an alert


b. Send an email to third party
c. Throw exception back to client.
3. Your bean can throw a system level exception as either a java.rmi.RemoteException or an
unchecked RuntimeException. If container throws this exception back to client then its always
thrown as a RemoteException or a subclass of it.
4. Exceptions also impact transactions.

Local Home Interface


/**
* This is the local home interface for HelloBean.
* This interface is implemented by the EJB Server’s
* tools - the implemented object is called the
* local home object, and serves as a factory for
* EJB local objects.
*/
public interface HelloLocalHome extends javax.ejb.EJBLocalHome
{
/*
* This method creates the EJB Object.
*
* @return The newly created EJB Object.
*/
HelloLocal create() throws javax.ejb.CreateException;
}

Session Bean Class


/**
* Demonstration stateless session bean.
*/
public class HelloBean implements javax.ejb.SessionBean {
private SessionContext ctx;

//
// EJB-required methods
//
public void ejbCreate() {
System.out.println(“ejbCreate()”);
}
public void ejbRemove() {
System.out.println(“ejbRemove()”);
}
public void ejbActivate() {
System.out.println(“ejbActivate()”);
}
public void ejbPassivate() {
System.out.println(“ejbPassivate()”);
}
public void setSessionContext(javax.ejb.SessionContext ctx) {
this.ctx = ctx;
}

//
// Business methods
//
public String hello() {
System.out.println(“hello()”);
return “Hello, World!”;
}
}

© 2006, Watsh Rajneesh. All Rights Reserved.


17/86 2/9/2008

EJB Context
Inside the bean you may want to access the security credential of the user currently calling your bean’s
method. Container holds all this information in an EJB Context object. So a context represents a way for a
bean to perform callbacks to the container. EJB Context encapsulates the bean’s domain. The container is
responsible for changing the context to reflect any status change, such as bean being involved in a new
transaction. Context object state will dynamically change over time. The container associates your bean
with a context by calling your setSessionContext() (or setEntityContext(), setMessageDrivenContext()).
When you define each of these methods, you should store the context away in a member variable so that
the context can be queried later.
public interface javax.ejb.EJBContext
{
/*
* Call these from within your bean to access
* your own home object or local home object.
*
* You can use them to create, destroy, or
* find EJB objects and EJB local objects
* of your own bean class type.
*/
public javax.ejb.EJBHome getEJBHome();
public javax.ejb.EJBLocalHome getEJBLocalHome();

/*
* These are transaction methods
*/
public boolean getRollbackOnly();
public void setRollbackOnly();
public javax.transaction.UserTransaction getUserTransaction();

/*
* These are security methods
*/
public boolean isCallerInRole(java.lang.String);
public java.security.Principal getCallerPrincipal();
}

public interface javax.ejb.SessionContext extends javax.ejb.EJBContext


{
public javax.ejb.EJBLocalObject getEJBLocalObject();
public javax.ejb.EJBObject getEJBObject();
}

Deployement Descriptor
ejb-jar.xml – standard ejb deployement descriptor.
<?xml version = "1.0" encoding = "UTF-8"?>
<!--
Copyright 2004 Sun Microsystems, Inc. All rights reserved.
SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->
<ejb-jar xmlns = "http://java.sun.com/xml/ns/j2ee" version = "2.1" xmlns:xsi =
"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
<display-name>HelloWorld</display-name>
<enterprise-beans>
<session>
<display-name>HelloWorld</display-name>
<ejb-name>HelloWorld</ejb-name>
<home>examples.HelloHome</home>
<remote>examples.Hello</remote>
<ejb-class>examples.HelloBean</ejb-class>
<session-type>Stateless</session-type>

© 2006, Watsh Rajneesh. All Rights Reserved.


18/86 2/9/2008

<transaction-type>Container</transaction-type>
<security-identity>
<use-caller-identity/>
</security-identity>
</session>
</enterprise-beans>
</ejb-jar>

sun-ejb-jar.xml – vendor specific file.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.0 EJB 2.1//EN
" "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_2_1-0.dtd">

<sun-ejb-jar>
<enterprise-beans>
<unique-id>1</unique-id>
<ejb>
<ejb-name>HelloWorld</ejb-name>
<jndi-name>HelloHome</jndi-name>
</ejb>
</enterprise-beans>
</sun-ejb-jar>

EJB Jar file


jar cf HelloWorld.jar *

The contents of jar file will look like this:

* examples is the package.


You can generate the EJB Client jar file from the deploytool which includes classes that must be deployed
for any clients of a particular EJB jar file.

Start the Sun AS 8.1 PE as follows:


asadmin –start-domain domain1
Then browse to the url: http://localhost:4848 and login to the admin console.
From there you can deploy the EJB jar file in EJB Modules section.

© 2006, Watsh Rajneesh. All Rights Reserved.


19/86 2/9/2008

Client code
import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Properties;
/**
* This class is an example of client code that invokes
* methods on a simple stateless session bean.
*/
public class HelloClient {
public static void main(String[] args) throws Exception
{
/*
* Setup properties for JNDI initialization.
*
* These properties will be read-in from
* the command-line.
*/
Properties props = System.getProperties();

/*
* Obtain the JNDI initial context.
*
* The initial context is a starting point for
* connecting to a JNDI tree. We choose our JNDI
* driver, the network location of the server, etc.
* by passing in the environment properties.
*/
Context ctx = new InitialContext(props);

/*
* Get a reference to the home object - the
* factory for Hello EJB Objects
*/
Object obj = ctx.lookup(“HelloHome”);

/*
* Home objects are RMI-IIOP objects, and so
* they must be cast into RMI-IIOP objects
* using a special RMI-IIOP cast.
*
*/
HelloHome home = (HelloHome) javax.rmi.PortableRemoteObject.narrow( obj,
HelloHome.class);

/*
* Use the factory to create the Hello EJB Object
*/
Hello hello = home.create();

/*
* Call the hello() method on the EJB object. The
* EJB object will delegate the call to the bean,
* receive the result, and return it to us.
*
* We then print the result to the screen.
*/
System.out.println(hello.hello());

/*
* Done with EJB Object, so remove it.
* The container will destroy the EJB object.
*/
hello.remove();
}
}

To run the client:


$ java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory

© 2006, Watsh Rajneesh. All Rights Reserved.


20/86 2/9/2008

-Djava.naming.provider.url=corbaloc::localhost:3700/NameService examples.HelloClient

Hello, World!

We need to identify the initial context factory class in the naming service provider we use and the url for
the root of the naming service.

To Remember…

If your bean calls another bean’s method and wants to pass its referecence as a parameter, then you must
pass a reference to your bean’s EJB object, rather than a reference to your bean ie passing this wont work
rather use the context object and call sessionCtx.getEJBObject() to get a reference to your EJB object and
pass that as a reference, where sessionCtx is the priavate variable where you stored the session context
object in the body of setSessionContext().

Also to allow for compile time checks for your bean class whether it implements all the business methods
or not, pull out the business methods into a separate interface which can be extends by your remote and
local interfaces and that your bean class will implement.

// Business interface
public interface HelloBusinessMethods {
public String hello() throws java.rmi.RemoteException;
}

// EJB remote interface


public interface HelloRemote extends javax.ejb.EJBObject, HelloBusinessMethods {
}

// EJB local interface


public interface HelloLocal extends javax.ejb.EJBLocalObject, HelloBusinessMethods {
}

// Bean implementation – now checked at compile time for compliance with the business methods interface
public class HelloBean implements SessionBean, HelloBusinessMethods {
public String hello() {
return “Hello, World!”;
}
<...define other required callbacks...>
}

Webservices using Stateless Session Beans


Web Services are a way of building a Service-Oriented Architecture (SOA). SOA is an
architectural approach to structuring large-scale, distributed applications that
integrate heterogeneous applications behind service interfaces.

A service provider creates an abstract service definition that it publishes in a service


registry. With Web Services, the description is a Web Services Definition Language
(WSDL) file, and the registry follows the Universal Description, Discovery, and
Integration (UDDI) standard. A service requestor can find the service description,
possibly using a set of selection criteria to query the registry. If a suitable description
is found, the requestor can bind to the service.

SOAs emphasize modularity through standardized interfaces, flexibility through


looser coupling, and extensibility through using XML. All of this is important in the
B2B scenarios, which are the primary targets of Web Services.

© 2006, Watsh Rajneesh. All Rights Reserved.


21/86 2/9/2008

Web Services = WSDL + SOAP + UDDI

WSDL
wscompile – tool to generate WSDL from Java interface.

Webservices are managed by container. JSR921 defines the programming model for webservices. It defines
a port component for the server-side view of a web service. It is a portable java implementation of a service
interface (port) and comprises java mapping of the service interface and the implementation bean. Writing
web service using EJB requires creating one or more port components as stateless session beans. After
exposing the bean as a web service only repackaging and redeploying is required, which now contains a
port component. The EJB container will know how to dispatch incoming SOAP messages to our bean
implementation and how to map the incoming XML data types to Java. The way to implement the service
endpoint in an existing bean is to define the business methods interface separately and have the remote
intrerface and the bean class implement this interface (as described earlier to provide compile time
checking of business methods being implemented in the bean class):

package examples;

/**
* This is the Hello remote interface.
*
*/
public interface HelloInterface extends java.rmi.Remote
{

/**
* The one method - hello - returns a greeting to the client.
*/
public String hello() throws java.rmi.RemoteException;
}

The extends java.rmi.Remote is added to the new definition of Hello interface. Remember that this
interface is extended by Hello remote interface (which also extends javax.ejb.EJBObject). This interface is
also called the Service Endpoint Interface (SEI).

© 2006, Watsh Rajneesh. All Rights Reserved.


22/86 2/9/2008

Note: The bean class may not implement this interface explicitly but the business methods in the SEI must
anyhow be implemented by the bean class.
JAX/RPC defines a mapping between a set of supported Java types and WSDL/XML types. Java primitive
types are directly supported by JAX/RPC. Some non primitive types supported are: Wrappers (Boolean,
Integer, Character, etc), java.net.URI, java.util.Calendar, java.util.Date and java.lang.String.

Generate a JAX-RPC mapping file and WSDL:


$ wscompile.bat -classpath ./classes -define -d ./assemble -nd ./assemble –mapping
./assemble/mapping.xml src/config.xml

Where,
Config.xml:
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
<service
name="HelloWorldWS"
targetNamespace="urn:examples"
typeNamespace="urn:examples"
packageName="examples">
<interface name="examples.HelloInterface"/>
</service>
</configuration>

Config.xml defines the name of the service, the target namespace to use in the WSDL xml schema, the
name of the SEI.

Usage: wscompile [options] configuration_file


-classpath <path> Specifies where to find input class files.
-define Define a service
-d <directory> Specifies where to place generated output files
-nd <directory> Specifies where to place non-class generated files
-mapping <file> Write the 109 mapping file to the given file

Following is the generated mapping file:


<?xml version="1.0" encoding="UTF-8"?>
<java-wsdl-mapping xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://www.ibm.com/webservices/xsd/j2ee_jaxrpc_mapping_1_1.xsd">

<package-mapping>
<package-type>examples</package-type>
<namespaceURI>urn:examples</namespaceURI>
</package-mapping>

<service-interface-mapping>
<service-interface>examples.HelloWorldWS</service-interface>
<wsdl-service-name xmlns:serviceNS="urn:examples">serviceNS:HelloWorldWS</wsdl-service-
name>
<port-mapping>
<port-name>HelloInterfacePort</port-name>
<java-port-name>HelloInterfacePort</java-port-name>
</port-mapping>
</service-interface-mapping>

© 2006, Watsh Rajneesh. All Rights Reserved.


23/86 2/9/2008

<service-endpoint-interface-mapping>
<service-endpoint-interface>examples.HelloInterface</service-endpoint-interface>
<wsdl-port-type xmlns:portTypeNS="urn:examples">
portTypeNS:HelloInterface
</wsdl-port-type>
<wsdl-binding xmlns:bindingNS="urn:examples">
bindingNS:HelloInterfaceBinding
</wsdl-binding>
<service-endpoint-method-mapping>
<java-method-name>hello</java-method-name>
<wsdl-operation>hello</wsdl-operation>
<wsdl-return-value-mapping>
<method-return-value>java.lang.String</method-return-value>
<wsdl-message xmlns:wsdlMsgNS="urn:examples">
wsdlMsgNS:HelloInterface_helloResponse
</wsdl-message>
<wsdl-message-part-name>result</wsdl-message-part-name>
</wsdl-return-value-mapping>
</service-endpoint-method-mapping>
</service-endpoint-interface-mapping>
</java-wsdl-mapping>

Generate the client stub classes:


$ wscompile.bat -classpath ./classes -gen:client -keep -d ./src/generated -nd ./classes src/config.xml
warning: You have specified : -gen:both or -gen:client with a SEI. The use of these modes are
recommended with WSDL only.
Where,
-keep Keep generated files
-gen:client Generate client artifacts (stubs, etc).

Create a webservices.xml Deployment descriptor:


<?xml version="1.0" encoding="UTF-8"?>
<webservices xmlns="http://java.sun.com/xml/ns/j2ee" version="1.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd">
<webservice-description>
<display-name>HelloService</display-name>
<webservice-description-name>HelloWS</webservice-description-name>
<wsdl-file>META-INF/wsdl/HelloWorldWS.wsdl</wsdl-file>
<jaxrpc-mapping-file>META-INF/wsdl/mapping.xml</jaxrpc-mapping-file>
<port-component>
<display-name>HelloWS</display-name>
<port-component-name>HelloWS</port-component-name>
<wsdl-port xmlns:wsdl-port_ns__="urn:examples">wsdl-port_ns__:HelloInterfacePort</wsdl-port>
<service-endpoint-interface>examples.HelloInterface</service-endpoint-interface>
<service-impl-bean>
<ejb-link>HelloBean</ejb-link>
</service-impl-bean>
</port-component>
</webservice-description>
</webservices>

And package everything together in the ejb jar file as shown below:

© 2006, Watsh Rajneesh. All Rights Reserved.


24/86 2/9/2008

Deploy this jar in the usual way and access it at url ??. (This part will be completed after I have read the
J2EE Webservices book).

Entity Beans
Entity beans are persistent objects.
public interface javax.ejb.EntityBean extends javax.ejb.EnterpriseBean {
public void setEntityContext(javax.ejb.EntityContext);
public void unsetEntityContext();
public void ejbRemove();
public void ejbActivate();
public void ejbPassivate();
public void ejbLoad();
public void ejbStore();
}

Object-Relational Mapping : Mapping of objects to relational databases. Eg of ORM products are


Hibernate, Oracle TopLink, JDO etc.

Entity beans can persist themselves in many ways, including Java serialization, O/R mapping, or even an
object database persistence. O/R mappings are the most frequently used mechanism in practice.

Two files constitute an entity bean:


1. entity bean class: maps to the entity definition in a database schema.
2. primary key class: is an object that may contain any number of attributes (like composite
primary key). This could be any data necessary to identify uniquely an entity bean data instance. It
must be serializable.
Entity beans lifetime depends on how long the data sits in the database.

Entity beans are generally accessed by other beans that run-in process (typically with a session façade in
which case a session bean will access the entity bean). Clients (servlets/jsp/applets) invoke a method on the
session façade and the session bean in turn calls the entity bean. Since the session and entity beans will be

© 2006, Watsh Rajneesh. All Rights Reserved.


25/86 2/9/2008

colocated in the same JVM process so the entity beans only expose local interface in production (and not
remote).

Load and Store


ejbLoad() : reads the data in from the persistent storage into the entity bean’s in-memory fields.
ejbStore() : saves your bean instance’s current fields to the underlying data storage.

The container automatically synchronizes the in-memory entity bean instance with the database record they
represent by calling ejbLoad() and ejbStore() callbacks.

There can be multiple in-memory entity bean instances which represent the same underlying data. The data
corruption is prevented in such circumstances by synchronizing the beans with the underlying storage. The
frequency of such synchronizations is determined by the transaction isolation level associated with the
bean. If it is read-commited then two clients accessing the entity bean instances mapped to same data can
read the data only when the modification to it has been saved/committed to the storage. An uncommitted
data change will not be read.

The container may pool and reuse the entity bean instances to represent different instances of the same type
of data in the database (eg. Entity bean instance to represent different bank account records). Reassigning
the entity bean instance to represent a different data record requires having to let the bean know to release
any resource it held while mapping to the older data record. For this, entity bean class will need to
implement ejbActivate() and ejbPassivate(). The container invokes ejbStore() before passivating the
bean and invokes ejbLoad() after activating the bean.

Types
Bean Managed Persistent entity beans require you to write code to translate your in-memory fields into an
underlying data store. You need to provide implementations for ejbCreate(), ejbLoad(), ejbStore(),
ejbFindXXX() and ejbRemove() methods using JDBC API.

Container Managed Persistent entity beans requires you to provide the entity bean O/R mapping in the
deployment descriptor and container generates the data access code.

Create and Remove


When an entity bean is initialized in memory during ejbCreate(), a new data record is inserted to the
underlying database that correlates with the in-memory instance. ejbRemove() should then delete the data
record from the database.

Bean return a primary key to the container so that the container can identify the bean uniquely, upon
ejbCreate() being called. On ejbRemove(), the database data associated with the bean is deleted and the
bean is made inaccessible to the client. Client can call remove() method of either EJBObject or Home
object.
In bean class:
public AccountPK ejbCreate(String accountID, String owner) throws...

In home interface:
public Account create(String accountID, String owner) throws ...

Home interface exposes finder methods in addition to create and remove methods.

If you directly create/modify/delete the data by directly touching the database, the in-memory entity beans
will be created (by just calling findByPrimaryKey() method on the home object for your bean), modified
(upon automatic synchronization) and deleted. So its not necessary for an entity bean to have an
ejbCreate() method as they can be created by directly touching the database.

© 2006, Watsh Rajneesh. All Rights Reserved.


26/86 2/9/2008

Entity Context
An entity bean has a context object (which implements javax.ejb.EntityContext) via which it can query the
container for its own transaction state and security information.

public interface javax.ejb.EJBContext {


public javax.ejb.EJBHome getEJBHome();
public javax.ejb.EJBLocalHome getEJBLocalHome();
public java.security.Principal getCallerPrincipal();
public boolean isCallerInRole(java.lang.String);
public void setRollbackOnly();
public boolean getRollbackOnly();
}

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


public javax.ejb.EJBLocalObject getEJBLocalObject();
public javax.ejb.EJBObject getEJBObject();
public java.lang.Object getPrimaryKey(); // new in entity context
}

getPrimaryKey() :
You call it whenever you want to figure out with which database data your instance is associated. Your
entity bean must perform a getPrimaryKey() callback to the entity context to figure out what data it is
dealing with. (Remember: entity beans can be pooled and reused to cater to different data records). In case
of BMP, you will need to use it for the following method implementations:
1. ejbLoad() : when ejbStore() is called the bean has the knowledge of what data it holds but when
the container calls its ejbLoad() it should first use getPrimaryKey() to know what data to be
fetched from the database.
2. ejbRemove() : when ejbCreate() is called the bean knows what data to create as it has been passed
to it in parameters to ejbCreate(). But while removing the data, you must call the getPrimaryKey()
to find out what data to remove.

Finder methods:
Are defined on local/remote home interfaces and implemented by your bean implementations to find one or
more existing entity bean in storage. You must define atleast one finder method –
ejbFindByPrimaryKey().

For eg. You might perform a query as “SELECT id FROM accounts WHERE balance > 10000” and return
the primary keys for the resultset data back to the container by creating one or more primary key object
instances. Container will then create EJB objects for the client to invoke on and possibly associate some
entity bean instances with those EJB objects.

public Collection ejbFindBigAccounts() throws FinderException {


//…
}

Collection is collection of primary keys. Container then creates a collection of EJB Objects one for each
primary key in the collection, and returns those EJB Objects in its own collection to the client.
1. All finder methods must being with ejbFind.
2. Must have atleast one finder method – ejbFindByPrimaryKey().
public AccountPK ejbFindByPrimaryKey(AccountPK key) throws FinderException {
//…
}
Note: You define finder methods only in case of BMP. For CMP, these method implementations are
generated by container.

© 2006, Watsh Rajneesh. All Rights Reserved.


27/86 2/9/2008

Clients invoke finder methods on home objects.

Entity bean instance returns a primary key to the container, whereas the home object returns an EJB Object
to the client.

Bean Managed Persistent (BMP) Entity Beans


You are responsible to provide the implementation to map your entity bean instances to and from storage.
To do this you either use:
3. JDBC API or
4. ORM framework – Hibernate or Oracle TopLink.
Steps to follow:
5. setEntityContext() – store the entity context in a member varible. After this method executes,
bean does not hold a data yet but is available in pool.
6. ejbFindXXX() – as explained earlier.
7. ejbHomeXXX() – methods on an entity bean that are not specific to any data record. Eg.
Counting the total number of records in a table. They are special business methods, as they are
called from bean in pool before the bean is associated with any data. Clients call home methods
from local/remote home objects.
8. ejbCreate() – you may not write any ejbCreate if you don’t want EJB clients to be able to create
new database data. These methods are responsible for creating new data record and initializing
your bean. For BMP, you can use INSERT SQL statement to create new data and return an
instance of primary key for the data to the container.
9. ejbPostCreate() – must define one ejbPostCreate() for each ejbCreate() and both should take the
same parameters.
1. You can do any post initialization work here and/or
2. pass the reference to your bean’s EJB Object to other beans and/or
3. reset certain transaction related parameteres.
 ejbActivate() – acquire any resource (such as socket conncetions) if needed.
 ejbLoad() – Call getPrimaryKey() on entity context to know what data to load and then read the
data (SQL SELECT) into your bean.
 ejbStore() – write your member fields out to disk through SQL UPDATE.
 ejbPassivate() – release any resource if needed.
 ejbRemove() – Call getPrimaryKey() on entity context to know what data to delete from the
database then delete (SQL DELETE) the data.
 unsetEntityContext() – release any resource aquired in setEntityContext() and get ready to be
garbage collected. Called when entity bean instance is to be destroyed by container when it wants
to reduce its pool size.

© 2006, Watsh Rajneesh. All Rights Reserved.


28/86 2/9/2008

BMP Entity bean with local interface

We are not showing the code for the remote interface below but for testing we use the remote interface
itself. Though in practice, we will use a session façade to interface remotely with the client and use the
entity beans locally but to test the entity bean individually without writing a session façade we use the
remote interface.

Local interface
package examples.bmp;
import javax.ejb.*;
/**
* This is the local interface for AccountBean.
*
* Local clients interact with beans through this interface. The container will
* implement this interface; the implemented object is called the local object,
* which delegates invocations to the actual bean.
*/
public interface AccountLocal extends EJBLocalObject {
/**
* Deposits amt into account.
*/
public void deposit(double amt) throws AccountException;
/**
* Withdraws amt from bank account.
* @throw AccountException thrown if amt > available balance
*/
public void withdraw(double amt) throws AccountException;

// Getter/setter methods on Entity Bean fields


public double getBalance();
public String getOwnerName();
public void setOwnerName(String name);
public String getAccountID();
public void setAccountID(String id);

© 2006, Watsh Rajneesh. All Rights Reserved.


29/86 2/9/2008

Local Home Interface


package examples.bmp;
import javax.ejb.*;
import java.util.Collection;
/**
* This is the local home interface for Account. This
* interface is implemented by the EJB container’s tools - the
* implemented object is called the local home object, which
* is a factory for local EJB objects.
*/
public interface AccountLocalHome extends EJBLocalHome {
/**
* We define a single create() method in this home interface,
* which corresponds to the ejbCreate() method in AccountBean.
* This method creates the local EJB object.
*
* Notice that the local home interface returns a
* local interface, whereas the bean returns a PK.
*
* Notice we don’t throw RemoteExceptions because we are local not remote.
*
* @param accountID The number of the account (unique)
* @param ownerName The name of the person who owns the account
* @return The newly created local object.
*/
public AccountLocal create(String accountID, String ownerName) throws CreateException;

/**
* Finds an Account by its primary Key (Account ID)
*/
public AccountLocal findByPrimaryKey(AccountPK key) throws FinderException;

/**
* Finds all Accounts under an owner’s name
*/
public Collection findByOwnerName(String name) throws FinderException;
/**
* This home business method is independent of any particular
* account instance. It returns the total of all the bank
* accounts in the bank.
*/
public double getTotalBankValue() throws AccountException;
}

Primary Key class


package examples.bmp;
/**
* Primary Key class for Account.
*/
public class AccountPK implements java.io.Serializable {
public String accountID;
public AccountPK(String id) {
this.accountID = id;
}
public AccountPK() {
}
public String toString() {
return accountID;
}
public int hashCode() {
return accountID.hashCode();
}
public boolean equals(Object account) {

© 2006, Watsh Rajneesh. All Rights Reserved.


30/86 2/9/2008

if (!(account instanceof AccountPK))


return false;
return ((AccountPK)account).accountID.equals(accountID);
}
}
Primary key contains a simple string but its possible for an entity bean to map to more than one table in the
database and may have primary key class that have several field inside them, each representing a primary
key of a table in the database.

hashCode() and equals() should be overridden to allow the container to be able to compare two primary key
instances by value when stored in a HashMap.

Custom Exception (Application Level)


package examples.bmp;
/**
* Exceptions thrown by Accounts
*/
public class AccountException extends Exception {
public AccountException() {
super();
}
public AccountException(Exception e) {
super(e.toString());
}
public AccountException(String s) {
super(s);
}
}

Entity Bean Class


create table accounts (id varchar(64), ownername varchar(64), balance numeric(18) );
is the table schema to which the entity bean class maps.

package examples.bmp;
import java.sql.*;
import javax.naming.*;
import javax.ejb.*;
import java.util.*;
/**
* Demonstration Bean-Managed Persistent Entity Bean. This Entity Bean
* represents a Bank Account.
*/
public class AccountBean implements EntityBean {
protected EntityContext ctx;
//
// Bean-managed state fields
//
private String accountID; // PK
private String ownerName;
private double balance;
public AccountBean() {
System.out.println(“New Bank Account Entity Bean Java Object created by EJB
Container.”);
}
//
// Business Logic Methods
//
/**
* Deposits amt into account.
*/
public void deposit(double amt) throws AccountException {
System.out.println(“deposit(“ + amt + “) called.”);
balance += amt;
}

© 2006, Watsh Rajneesh. All Rights Reserved.


31/86 2/9/2008

/**
* Withdraws amt from bank account.
* @throw AccountException thrown if amt > available balance
*/
public void withdraw(double amt) throws AccountException {
System.out.println(“withdraw(“ + amt + “) called.”);
if (amt > balance) {
throw new AccountException(“Your balance is “ +
balance + “! You cannot withdraw “
+ amt + “!”);
}
balance -= amt;
}
// Getter/setter methods on Entity Bean fields
public double getBalance() {
System.out.println(“getBalance() called.”);
return balance;
}
public void setOwnerName(String name) {
System.out.println(“setOwnerName() called.”);
ownerName = name;
}
public String getOwnerName() {
System.out.println(“getOwnerName() called.”);
return ownerName;
}
public String getAccountID() {
System.out.println(“getAccountID() called.”);
return accountID;
}
public void setAccountID(String id) {
System.out.println(“setAccountID() called.”);
this.accountID = id;
}
/**
* This home business method is independent of any
* particular account instance. It returns the total
* of all the bank accounts in the bank.
*/
public double ejbHomeGetTotalBankValue() throws AccountException {
PreparedStatement pstmt = null;
Connection conn = null;
try {
System.out.println(“ejbHomeGetTotalBankValue()”);
/* Acquire DB connection */
conn = getConnection();
/* Get the total of all accounts */
pstmt = conn.prepareStatement(“select sum(balance) as total from accounts”);
ResultSet rs = pstmt.executeQuery();
/* Return the sum */
if (rs.next()) {
return rs.getDouble(“total”);
}
}
catch (Exception e) {
e.printStackTrace();
throw new AccountException(e);
}
finally {
/*
* Release DB Connection for other beans
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { }
try { if (conn != null) conn.close(); }
catch (Exception e) { }
}
throw new AccountException(“Error!”);
}

© 2006, Watsh Rajneesh. All Rights Reserved.


32/86 2/9/2008

/**
* Gets JDBC connection from the connection pool.
*
* @return The JDBC connection
*/
public Connection getConnection() throws Exception {
try {
Context ctx = new InitialContext();
javax.sql.DataSource ds =
(javax.sql.DataSource)ctx.lookup(“java:comp/env/jdbc/ejbPool”);
return ds.getConnection();
} catch (Exception e) {
System.err.println(“Couldn’t get datasource!”);
e.printStackTrace();
throw e;
}
}
//
// EJB-required methods
//
/**
* Called by Container. Implementation can acquire
* needed resources.
*/
public void ejbActivate() {
System.out.println(“ejbActivate() called.”);
}
/**
* Removes entity bean data from the database.
* Corresponds to when client calls home.remove().
*/
public void ejbRemove() throws RemoveException {
System.out.println(“ejbRemove() called.”);
/*
* Remember that an entity bean class can be used to
* represent different data instances. So how does
* this method know which instance in the database
* to delete?
*
* The answer is to query the container by calling
* the entity context object. By retrieving the
* primary key from the entity context, we know
* which data instance, keyed by the PK, that we
* should delete from the DB.
*/
AccountPK pk = (AccountPK) ctx.getPrimaryKey();
String id = pk.accountID;
PreparedStatement pstmt = null;
Connection conn = null;
try {
/*
* 1) Acquire a new JDBC Connection
*/
conn = getConnection();
/*
* 2) Remove account from the DB
*/
pstmt = conn.prepareStatement(“delete from accounts where id = ?”);
pstmt.setString(1, id);
/*
* 3) Throw a system-level exception if something
* bad happened.
*/
if (pstmt.executeUpdate() == 0) {
throw new RemoveException(
“Account “ + pk + “ failed to be removed from the database”);
}
}
catch (Exception ex) {

© 2006, Watsh Rajneesh. All Rights Reserved.


33/86 2/9/2008

throw new EJBException(ex.toString());


}
finally {
/*
* 4) Release the DB Connection
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { }
try { if (conn != null) conn.close(); }
catch (Exception e) { }
}
}
/**
* Called by Container. Releases held resources for
* passivation.
*/
public void ejbPassivate() {
System.out.println(“ejbPassivate () called.”);
}
/**
* Called by the container. Updates the in-memory entity
* bean object to reflect the current value stored in
* the database.
*/
public void ejbLoad() {
System.out.println(“ejbLoad() called.”);
/*
* Again, query the Entity Context to get the current
* Primary Key, so we know which instance to load.
*/
AccountPK pk = (AccountPK) ctx.getPrimaryKey();
String id = pk.accountID;
PreparedStatement pstmt = null;
Connection conn = null;
try {
/*
* 1) Acquire a new DB Connection
*/
conn = getConnection();
/*
* 2) Get account from the DB, querying
* by account ID
*/
pstmt = conn.prepareStatement(“select ownerName, balance from accounts “
+ “where id = ?”);
pstmt.setString(1, id);
ResultSet rs = pstmt.executeQuery();
rs.next();
ownerName = rs.getString(“ownerName”);
balance = rs.getDouble(“balance”);
}
catch (Exception ex) {
throw new EJBException(
“Account “ + pk
+ “ failed to load from database”, ex);
}
finally {
/*
* 3) Release the DB Connection
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { }
try { if (conn != null) conn.close(); }
catch (Exception e) { }
}
}
/**
* Called from the Container. Updates the database
* to reflect the current values of this in-memory

© 2006, Watsh Rajneesh. All Rights Reserved.


34/86 2/9/2008

* entity bean instance.


*/
public void ejbStore() {
System.out.println(“ejbStore() called.”);
PreparedStatement pstmt = null;
Connection conn = null;
try {
/*
* 1) Acquire a new DB Connection
*/
conn = getConnection();
/*
* 2) Store account in DB
*/
pstmt = conn.prepareStatement(
“update accounts set ownerName = ?, balance = ?” + “ where id = ?”);
pstmt.setString(1, ownerName);
pstmt.setDouble(2, balance);
pstmt.setString(3, accountID);
pstmt.executeUpdate();
}
catch (Exception ex) {
throw new EJBException(“Account “ + accountID + “ failed to save to
database”, ex);
}
finally {
/*
* 3) Release the DB Connection
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { }
try { if (conn != null) conn.close(); }
catch (Exception e) { }
}
}
/**
* Called by the container. Associates this bean
* instance with a particular context. We can query
* the bean properties that customize the bean here.
*/
public void setEntityContext(EntityContext ctx) {
System.out.println(“setEntityContext called”);
this.ctx = ctx;
}
/**
* Called by Container. Disassociates this bean
* instance with a particular context environment.
*/
public void unsetEntityContext() {
System.out.println(“unsetEntityContext called”);
this.ctx = null;
}
/**
* Called after ejbCreate(). Now, the Bean can retrieve
* its EJBObject from its context, and pass it as
* a ‘this’ argument.
*/
public void ejbPostCreate(String accountID, String ownerName) {
}
/**
* This is the initialization method that corresponds to the
* create() method in the Home Interface.
*
* When the client calls the Home Object’s create() method,
* the Home Object then calls this ejbCreate() method.
*
* @return The primary key for this account
*/
public AccountPK ejbCreate(String accountID, String ownerName) throws CreateException {

© 2006, Watsh Rajneesh. All Rights Reserved.


35/86 2/9/2008

PreparedStatement pstmt = null;


Connection conn = null;
try {
System.out.println(“ejbCreate() called.”);
this.accountID = accountID;
this.ownerName = ownerName;
this.balance = 0;
/*
* Acquire DB connection
*/
conn = getConnection();
/*
* Insert the account into the database
*/
pstmt = conn.prepareStatement(
“insert into accounts (id, ownerName, balance)”
+ “ values (?, ?, ?)”);
pstmt.setString(1, accountID);
pstmt.setString(2, ownerName);
pstmt.setDouble(3, balance);
pstmt.executeUpdate();
/*
* Generate the Primary Key and return it
*/
return new AccountPK(accountID);
}
catch (Exception e) {
throw new CreateException(e.toString());
}
finally {
/*
* Release DB Connection for other beans
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { }
try { if (conn != null) conn.close(); }
catch (Exception e) { }
}
}
/**
* Finds a Account by its primary Key
*/
public AccountPK ejbFindByPrimaryKey(AccountPK key) throws FinderException {
PreparedStatement pstmt = null;
Connection conn = null;
try {
System.out.println(“ejbFindByPrimaryKey(“+ key + “) called”);
/*
* Acquire DB connection
*/
conn = getConnection();
/*
* Find the Entity in the DB
*/
pstmt = conn.prepareStatement(“select id from accounts where id = ?”);
pstmt.setString(1, key.toString());
ResultSet rs = pstmt.executeQuery();
rs.next();
/*
* No errors occurred, so return the Primary Key
*/
return key;
}
catch (Exception e) {
throw new FinderException(e.toString());
}
finally {
/*
* Release DB Connection for other beans

© 2006, Watsh Rajneesh. All Rights Reserved.


36/86 2/9/2008

*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { }
try { if (conn != null) conn.close(); }
catch (Exception e) { }
}
}
/**
* Finds Accounts by name
*/
public Collection ejbFindByOwnerName(String name) throws FinderException {
PreparedStatement pstmt = null;
Connection conn = null;
Vector v = new Vector();
try {
System.out.println(“ejbFindByOwnerName(“ + name + “) called”);
/*
* Acquire DB connection
*/
conn = getConnection();
/*
* Find the primary keys in the DB
*/
pstmt = conn.prepareStatement( “select id from accounts where ownerName
= ?”);
pstmt.setString(1, name);
ResultSet rs = pstmt.executeQuery();
/*
* Insert every primary key found into a vector
*/
while (rs.next()) {
String id = rs.getString(“id”);
v.addElement(new AccountPK(id));
}
/*
* Return the vector of primary keys
*/
return v;
}
catch (Exception e) {
throw new FinderException(e.toString());
}
finally {
/*
* Release DB Connection for other beans
*/
try { if (pstmt != null) pstmt.close(); }
catch (Exception e) { }
try { if (conn != null) conn.close(); }
catch (Exception e) { }
}
}
}

Deployment Descriptor
<?xml version=”1.0” encoding=”UTF-8”?>
<ejb-jar xmlns=”http://java.sun.com/xml/ns/j2ee” version=”2.1”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd”>
<display-name>AccountJAR</display-name>
<enterprise-beans>
<entity>
<ejb-name>AccountEJB</ejb-name>
<home>examples.bmp.AccountHome</home>
<remote>examples.bmp.Account</remote>
<ejb-class>examples.bmp.AccountBean</ejb-class>
<persistence-type>Bean</persistence-type>

© 2006, Watsh Rajneesh. All Rights Reserved.


37/86 2/9/2008

<prim-key-class>examples.bmp.AccountPK</prim-key-class>
<reentrant>false</reentrant>
<resource-ref>
<res-ref-name>jdbc/bmp-account</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
</entity>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>AccountEJB</ejb-name>
<method-intf>Remote</method-intf>
<method-name>*</method-name>
</method>
<method>
<ejb-name>AccountEJB</ejb-name>
<method-intf>Local</method-intf>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
Persistence-type Bean/Container
Prim-key-class Primary key class
Reentrant Whether our bean can call itself through another
bean. A given bean A is reentrant if it calls bean B
which calls back on bean A.
Resource-ref Sets up our jdbc driver at jndi location
Assembly-descriptor Associates transactions with out bean.

You will also need the AppServer specific deployement descriptor where you can configure the remote and
local home interface and the JDBC driver with JNDI locations.
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2004 Sun Microsystems, Inc. All rights reserved.
SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.0 EJB 2.1//EN"
"http://www.sun.com/software/appserver/dtds/sun-ejb-jar_2_1-0.dtd">

<sun-ejb-jar>
<enterprise-beans>
<name>BMPEntityEjb.jar</name>
<unique-id>0</unique-id>
<ejb>
<ejb-name>AccountEJB</ejb-name>
<jndi-name>AccountHome</jndi-name>
<resource-ref>
<res-ref-name>jdbc/bmp-account</res-ref-name>
<jndi-name>jdbc/bmp-account</jndi-name>
</resource-ref>
<bean-pool>
<steady-pool-size>0</steady-pool-size>
</bean-pool>
</ejb>

© 2006, Watsh Rajneesh. All Rights Reserved.


38/86 2/9/2008

</enterprise-beans>
</sun-ejb-jar>

Create the accounts table in the database using the sql file provided. This step is database specific.

Create EJB jar to deploy:

>mkdir assemble\ejbjar
Put the ejb-jar.xml and sun-ejb-jar.xml in the meta-inf folder in classes.
>jar cvf BMPEntityEJB.jar –C classes .
>move BMPEntityEJB.jar assemble\ejbjar

Client Code
package examples.bmp;
import javax.ejb.*;
import javax.naming.*;
import java.rmi.*;
import javax.rmi.*;
import java.util.*;
/**
* Sample client code that manipulates a Bank Account Entity Bean.
*/
public class AccountClient {
public static void main(String[] args) throws Exception {
Account account = null;
try {
/*
* Get a reference to the Account Home Object - the
* factory for Account EJB Objects
*/
Context ctx = new InitialContext(System.getProperties());
Object obj = ctx.lookup(“AccountHome”);
AccountHome home = (AccountHome)PortableRemoteObject.narrow(obj,
AccountHome.class);
System.err.println(“Total of all accounts in bank initially = “ +
home.getTotalBankValue());
/* Use the factory to create the Account EJB Object */

© 2006, Watsh Rajneesh. All Rights Reserved.


39/86 2/9/2008

home.create(“123-456-7890”, “John Smith”);


/* Find an account */
Iterator i = home.findByOwnerName(“John Smith”).iterator();
if (i.hasNext()) {
account =(Account)javax.rmi.PortableRemoteObject.narrow(i.next(),
Account.class);
}
else {
throw new Exception(“Could not find account”);
}
/* Call the balance() method, and print it */
System.out.println(“Initial Balance = “ + account.getBalance());
/* Deposit $100 into the account */
account.deposit(100);
/* Retrieve the resulting balance. */
System.out.println(“After depositing 100, account balance = “ +
account.getBalance());
System.out.println(“Total of all accounts in bank now = “ +
home.getTotalBankValue());
/* Retrieve the Primary Key from the EJB Object */
AccountPK pk = (AccountPK) account.getPrimaryKey();
/*
* Release our old EJB Object reference. Now call
* find() again, this time querying on Account ID
* (i.e. the Primary Key).
*/
account = null;
account = home.findByPrimaryKey(pk);
/* Print out current balance */
System.out.println(“Found account with ID “ + pk + “. Balance = “ +
account.getBalance());
/* Try to withdraw $150 */
System.out.println(“Now trying to withdraw $150, which is more “+
“than is currently available. This should “+ “generate an
exception..”);
account.withdraw(150);
}
catch (Exception e) {
System.out.println(“Caught exception!”);
e.printStackTrace();
}
finally {
/*
* Destroy the Entity permanently
*/
try {
System.out.println(“Destroying account..”);
if (account != null) {
account.remove();
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}

Run the client:


Generate the Client Jar:
>rmic -classpath .\classes;d:\Sun\AppServer\lib\j2ee.jar;d:\Sun\AppServ\lib\appserv-ext.jar -iiop
examples.bmp.Account

>rmic -classpath .\classes;d:\Sun\AppServer\lib\j2ee.jar;d:\Sun\AppServ\lib\appserv-ext.jar -iiop


examples.bmp.AccountHome

>mkdir assemble\client

© 2006, Watsh Rajneesh. All Rights Reserved.


40/86 2/9/2008

>jar cvf BMPEntityClient.jar –C classes .


>move BMPEntityClient.jar .\assemble\client

>java -cp .\assemble\client\BMPEntityClient.jar\;%CLASSPATH%


-Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
-Djava.naming.provider.url=corbaloc::localhost:3700/NameService examples.bmp.AccountClient

10. Container calls newInstance() on the bean class to create an instance of bean. This calls entity
bean’s default constructor. Container associates the bean instance with an entity context by calling
setEntityContext() method of bean class. Now the bean is put in the instance pool for that entity
bean type.
11. In the pool, the bean instance can be used to find entity data in the database by servicing a finder
method on behalf of client. It can also perform operations not dependent on a particular data
instance by servicing ejbHome() method. Container can call the unsetEntityContext() when it
wants to destroy the bean instance from pool (and the bean will be ready for garbage collection).
12. When client wants to create some new database data then it calls the create() method on the home
interface. Container grabs an entity bean from pool and calls its ejbCreate() method where the
bean initializes itself to a specific data set passed in the params of the create() method by the client
and, in case of BMP, this method will also create the corresponding data record in the database.
Now the bean moves to ready state.

© 2006, Watsh Rajneesh. All Rights Reserved.


41/86 2/9/2008

13. In the ready state, your bean is tied to a specific data and hence a specific EJB Object. Container
may occassionally need to synchronize your bean instance with the database by calling ejbLoad()
and ejbStore(). So ejbLoad() and ejbStore() will be responsible for loading and saving the data in
the database, in case of BMP.
14. If the client calls remove() on the home object or EJB object then container will call the
ejbRemove() method which in case of BMP is supposed to delete the database data associated
with this bean instance.
15. If the container needs to reuse a bean instance in the ready state to service another client, then it
will need to passivate the bean in which case it will call the ejbStore() method and then the
ejbPassivate() method, where the bean can release any resource it held. Then the bean is returned
back to pool for reuse.
16. Container may want to reassign the bean to an existing EJB object, then it will call the
ejbActivate() on the bean where the bean can reaquire the resouces it held earlier, and then the
container calls the ejbLoad() where the bean can initialize itself to the specific data (by first
learning about what primary key to use to retrieve that unique data record from the EJB object).

Container Managed Persistent (CMP) Entity Beans


With CMP, you don’t implement any persistence logic in the bean itself; rather the EJB container generates
the required storage code by subclassing your entity bean class. Thus all CMP entity beans comprise of
two classes: the superclass which you write (containing the entity bean business logic); and the subclass
which the container generates (which contains the persistence logic).

You don’t define any persistent fields and the associated get/set methods in your bean. They are kept in the
subclass (which the container generates).

You will need to declare the get/set methods as abstract methods in your entity bean class (thus
making it an abstract class). So if you need to provide a business method which works on more than one
persistent field then you can define such a method in your entity bean class itself and use the abstract
get/set methods in your implementation which will resolve to the subclasses implementation of those
get/set methods at runtime.
For example,
// CMP superclass – you write.
public abstract class CartBean implements EntityBean {
// no fields

// abstract get/set methods


public abstract float getSubTotal();
public abstract float getTaxes();

// other business methods


public float getTotal() {
return this.getSubtotal() + this.getTaxes();
}

// EJB required methods follow


}

// CMP subclass – container generated.


public class CartBeanSubClass extends CartBean {
// fields

public float subTotal;
public float taxes;

public float getSubTotal() {


return subTotal;
}
public float getTaxes() {
return taxes;

© 2006, Watsh Rajneesh. All Rights Reserved.


42/86 2/9/2008

}
// other get/set method implementations
}

Abstract Persistence Schema


...
<cmp-version>2.x</cmp-version>
<abstract-schema-name>AccountBean</abstract-schema-name>
<cmp-field>
<field-name>accountID</field-name>
</cmp-field>
<cmp-field>
<field-name>ownerName</field-name>
</cmp-field>
<cmp-field>
<field-name>balance</field-name>
</cmp-field>
<primkey-field>accountID</primkey-field>
...

Abstract persistence schema is defined in the ejb-jar.xml to let the container know what to generate for the
persistence logic. The container derieves the type of these fields from the get/set abstract methods.

EJB QL
EJB Query Language is an object-oriented SQL-like syntax for querying entity beans. You write EJB QL in
the deployment descriptor and the container should be able to generate the corresponding database logic in
SQL in a database specific way. For example, for the container to generate the implementation for the
finder method – findBigAccounts() we need to tell the container what query to perform on the database (in
a portable way using EJB QL in the DD) to generate the implementation for this method.

public Collection findBigAccounts(int minimum);

The EJB QL for this could be:

SELECT OBJECT(a)
FROM Account as a
WHERE a.balance > ?1

?1 – is the first parameter passed in to the method findBigAccounts viz minimum.

Note: Not all fields have to be managed by container. You might be pulling data from secondary sources or
you might have calculated fields. EJB container will notify your bean class during persistent operations
allowing you to manage these fields.

ejbSelect() – only in CMP


An ejbSelect() method is a query method (like a finder method) but is not directly exposed to client in the
home interface or component interface. It is used internally within an entity bean as a helper method
to access a storage. It is useful when you have entity beans in relationships with external data, such as
other entity beans. Your bean might hold references to other beans (in case of foreign key relationships). So
one bean might use ejbSelect() to verify the referential integrity for its foreign key fields. Also the bean
could use an ejbSelect() to implement a ejbHome() method (methods not related to any data instance) as
shown below:

public abstract class AccountBean implements javax.ejb.EntityBean


{
public abstract Collection ejbSelectAllAccountBalances() throws FinderException;

© 2006, Watsh Rajneesh. All Rights Reserved.


43/86 2/9/2008

public double ejbHomeGetTotalBankValue() throws Exception


{
// get a collection of bank account balances
Collection c = this.ejbSelectAllAccountBalances();
// loop through the collection and return sum
}
}

We can tell the container how to write the ejbSelectAllAccountBalances() method just like we do for finder
methods – using EJB QL in the DD.

SELECT OBJECT(a)
FROM Account AS a
WHERE a.balance IS NOT NULL

1. ejbSelect() methods are used internally within the bean and not exposed to clients.
2. Can retrieve data from other entity beans that you have relationship with.
3. Like finder methods, ejbSelect() methods can return primary key(s) or they can even return
container managed fields (a.balance above) which finder methods cannot (they must only return
primary key or collection of primary keys).

The remote, home, local and local home interfaces and primary key class remain same for both BMP and
CMP. What changes is the bean class code and the deployement descriptor. The client code does not change
if we change between BMP and CMP implementations.

Steps to follow for CMP entity bean coding: (differences from BMP highlighted in red).
17. setEntityContext() – store the entity context in a member varible. After this method executes,
bean does not hold a data yet but is available in pool.
18. ejbFindXXX() – Donot write this method in bean class, for CMP. Use EJB QL and the container
tools to tell the container what logic to execute when the client performs a finder method on the
home object.
19. ejbSelectXXX() {only in CMP}– Define this method as abstract and provide the EJB QL in the
deployment descriptor to set up the query. These are helper methods which perform queries
internally by your bean and are not accessible to clients of your bean.
20. ejbHomeXXX() {partially similar to BMP}– methods on an entity bean that are not specific to
any data record. Eg. Counting the total number of records in a table. They are special business
methods, as they are called from bean in pool before the bean is associated with any data. Clients
call home methods from local/remote home objects. For CMP, you provide this method in the bean
class and do the JDBC code yourself or have the container do it for you by using the
ejbSelectXXX() helper method mechanism described above for ejbHomeGetTotalBankValue().
21. ejbCreate() – you may not write any ejbCreate if you don’t want EJB clients to be able to create
new database data. These methods are responsible for creating new data record and initializing
your bean. For CMP, donot create database data here, rather just validate the client’s initialization
parameters and call your abstract set methods to initialize the generated bean subclass. Entity bean
instance moves to the ready state with ejbCreate().
22. ejbPostCreate() – must define one ejbPostCreate() for each ejbCreate() and both should take the
same parameters. Its called after container has associated an EJB object with your bean instance
(ie bean is in the ready state). You can get the primary key from the EJB object and use it here.
1. You can do any post initialization work here and/or
2. pass the reference to your bean’s EJB Object to other beans and/or
3. reset certain transaction related parameteres.
 ejbActivate() – acquire any resource (such as socket conncetions) if needed.

© 2006, Watsh Rajneesh. All Rights Reserved.


44/86 2/9/2008

 ejbLoad() – Don’t read data here. Container will do that right before it calls your ejbLoad(). Here
you can perform any utilities you need to work with the read-in data (such as decompressing a text
field etc) using the get/set abstract methods.
 ejbStore() – Don’t update the database here. Container will do that right after it calls you
ejbStore() method. So in this method you can prepare (eg compressing a text field) your container-
managed fields (those in the subclass) to be written in the database using the get/set abstract
methods.
 ejbPassivate() – release any resource if needed.
 ejbRemove() – Don’t delete the database data here. Container calls this method before actually
deleting the data from the database itself. Just perform any operation that must be done before the
data is destroyed.
 unsetEntityContext() – release any resource aquired in setEntityContext() and get ready to be
garbage collected. Called when entity bean instance is to be destroyed by container when it wants
to reduce its pool size.

Changing the previous example (for BMP) to use CMP, we just need to re-write the bean class and the
deployment descriptor.

Bean Class Code


package examples.cmp;

import javax.ejb.*;
/**
* Entity bean the demos CMP.
*/
public abstract class AccountBean implements EntityBean {
protected EntityContext ctx;
// no data fields

public AccountBean() {
System.out.println("New Bank Account Entity Bean Java Object created by EJB
Container.");
}

//-------------------
// Begin abstract get/set methods
//-------------------
public abstract double getBalance();
public abstract void setOwnerName(String name);
public abstract String getOwnerName();
public abstract String getAccountID();
public abstract void setAccountID(String id);
public abstract void setBalance(double balance);
//-------------------
// End abstract get/set methods
//-------------------

//-------------------
// Begin EJB required methods
//-------------------
/**
* Called by Container. Implementation can acquire
* needed resources.
*/

© 2006, Watsh Rajneesh. All Rights Reserved.


45/86 2/9/2008

public void ejbActivate() {


System.out.println("ejbActivate() called.");
}
/**
* Removes entity bean data from the database.
* Corresponds to when client calls home.remove().
*/
public void ejbRemove() throws RemoveException {
System.out.println("ejbRemove() called.");
}

/**
* Called by Container. Releases held resources for
* passivation.
*/
public void ejbPassivate() {
System.out.println("ejbPassivate () called.");
}

/**
* Called by the container. Updates the in-memory entity
* bean object to reflect the current value stored in
* the database.
*/
public void ejbLoad() {
System.out.println("ejbLoad() called.");
}

/**
* Called from the Container. Updates the database
* to reflect the current values of this in-memory
* entity bean instance.
*/
public void ejbStore() {
System.out.println("ejbStore() called.");
}

/**
* Called by the container. Associates this bean
* instance with a particular context. We can query
* the bean properties which customize the bean here.
*/
public void setEntityContext(EntityContext ctx) {
System.out.println("setEntityContext called");
this.ctx = ctx;
}

/**
* Called by Container. Disassociates this bean
* instance with a particular context environment.
*/
public void unsetEntityContext() {
System.out.println("unsetEntityContext called");
this.ctx = null;
}

© 2006, Watsh Rajneesh. All Rights Reserved.


46/86 2/9/2008

/**
* Called after ejbCreate(). Now, the Bean can retrieve
* its EJBObject from its context, and pass it as
* a 'this' argument.
*/
public void ejbPostCreate(String accountID, String ownerName) {
}

public AccountPK ejbCreate(String accountID, String ownerName) throws CreateException {


// use abstract methods to initialize the bean
setAccountID(accountID);
setOwnerName(ownerName);
return new AccountPK(accountID);
}

// no finder methods… (container implements them)

//
// Business Logic Methods
//

/**
* Deposits amt into account.
*/
public void deposit(double amt) throws AccountException
{
System.out.println("deposit(" + amt + ") called.");
setBalance(getBalanace() + amt);
}

/**
* Withdraws amt from bank account.
* @throw AccountException thrown if amt > available balance
*/
public void withdraw(double amt) throws AccountException
{
System.out.println("withdraw(" + amt + ") called.");
if (amt > getBalance()) {
throw new AccountException("Your balance is " + getBalance() +
"! You cannot withdraw " + amt + "!");
}
setBalance(getBalance() – amt);
}

public abstract Collection ejbSelectAllAccountBalances() throws FinderException;

/**
* This home business method is independent of any
* particular account instance. It returns the total
* of all the bank accounts in the bank.
*/
public double ejbHomeGetTotalBankValue() throws Exception
{
// get a collection of bank account balances
Collection c = this.ejbSelectAllAccountBalances();
// loop through the collection and return sum

© 2006, Watsh Rajneesh. All Rights Reserved.


47/86 2/9/2008

Iterator it = c.iterator();
double sumTot = 0.0;
while(it.hasNext()) {
sumTot += ((Double) it.next ()).doubleValue();
}
return sumTot;
}
}

Deployment Descriptor
We need to inform the container about our entity bean, the container managed fields and the associated EJB
QL for the finder and select methods.
<?xml version="1.0" encoding="UTF-8"?>

<ejb-jar xmlns="http://java.sun.com/xml/ns/j2ee"
version="2.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-
jar_2_1.xsd">
<display-name>Account</display-name>
<enterprise-beans>
<entity>
<ejb-name>AccountBean</ejb-name>
<home>examples.cmp.AccountHome</home>
<remote>examples.cmp.Account</remote>
<ejb-class>examples.cmp.AccountBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>examples.cmp.AccountPK</prim-key-class>

<reentrant>false</reentrant>

<cmp-version>2.x</cmp-version>
<abstract-schema-name>ACCOUNTS</abstract-schema-name>
<cmp-field>
<field-name>accountID</field-name>
<field-name>ownerName</field-name>
<field-name>balance</field-name>
</cmp-field>
<primarykey-field>accountID</primarykey-field>

<query>
<query-method>
<method-name>findByPrimaryKey</method-name>
<method-params>
<method-param>examples.cmp.AccountPK</method-param>
</method-params>
</query-method>
<ejb-ql>
SELECT OBJECT(a) FROM ACCOUNTS a WHERE a.accountID = ?1
</ejb-ql>
</query>
<query>
<query-method>
<method-name>findByOwnerName</method-name>

© 2006, Watsh Rajneesh. All Rights Reserved.


48/86 2/9/2008

<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>
SELECT OBJECT(a) FROM ACCOUNTS a WHERE a.ownerName = ?1
</ejb-ql>
</query>
<query>
<query-method>
<method-name>selectAllAccountBalances</method-name>
<method-params/>
</query-method>
<ejb-ql>
<![CDATA[SELECT OBJECT(a) FROM ACCOUNTS a WHERE a.balance > 0]]
</ejb-ql>
</query>
</entity>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>AccountBean</ejb-name>
<method-intf>Remote</method-intf>
<method-name>*</method-name>
</method>
<method>
<ejb-name>AccountBean</ejb-name>
<method-intf>Home</method-intf>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>

[Note: ejbSelect does not work! Comment out in the bean code and the DD. Problem in EJB QL.]

All EJB QL that contain < or > must be enclosed in CDATA sections (or else the XML parser will confuse a
< or > as part of some xml tag and complain).

Client (code in the BMP section of this document) used to test BMP, can be used to test CMP entity bean
too without any modification.

Note: Its always better to use a primary key class even when you have a single field as primary key.
Wrapping that field in a primary key class aids in encapsulating the fields and write code in terms of the
primary key class. So in future if the primary key class uses some other field then code which depends on
the primary key class will still remain same.

Message Driven Bean


Messaging service (MOM – message-oriented middleware) receives messages from one or more message
producers and broadcasts those messages to one or more message consumers. So producer can send
message and then continue processing and can optionally be notified of the response later when the
consumer finishes. Thus messaging aids in asynchronous programming.

© 2006, Watsh Rajneesh. All Rights Reserved.


49/86 2/9/2008

Pros of messaging paradigm are as follows:


1. Non blocking request processing: message producer does not need to block when executing a
request.
2. Message delivery guarantee: MOM (message oriented middleware) supports guaranteed
message delivery, you can send a message and know for sure that it will reach its destination, even
if the consumer is not available. The MOM will route the message to the consumer once it is
available.
3. Support for multiple producers and consumers.
Cons of messaging are:
1. It can be slower due to overhead of having a middleman (the MOM service).
Typical MOM are: Tibco Rendezvous, IBM Websphere MQ, BEA Tuxedo/Q, Sun Java System Messaging
Server, Microsoft MSMQ, Sonic MQ, FioranoMQ. These products can give value-added services like
guaranteed message delivery, fault tolerance, load balancing of destinations, subscriber throttling of
message consumption, inactive subscribers, support for SOAP over JMS etc.

Java Messaging Service (JMS)


JMS is a standard like JDBC and JNDI, which has two parts: an API layer which you use to write code to
send and receive messages, and a SPI where you plugin JMS providers for a particular product (which
knows how to talk to a specific MOM implementation). So you can learn JMS API once and reuse your
messaging code with different plug-and-play MOM implementations.

Messaging Domains

Pub/sub domain is an implementation of distributed event processing model. Subscribers register their
interest in a particular event topic. Publishers (event sources) create messages (events) that are distributed
to all of the subscribers. Publishers donot know who all are interested in the events.

Point to point: you can have only a single consumer for each message. Multiple consumers can grab the
message off the queue but any given message is consumed exactly once. Multiple producers can send
messages to the queue.

© 2006, Watsh Rajneesh. All Rights Reserved.


50/86 2/9/2008

JMS Programming Model

Steps to use JMS API for sending/receiving message:


import javax.naming.*;
import javax.jms.*;
import java.util.*;

public class Client {


public static void main (String[] args) throws Exception {
// Initialize JNDI
Context ctx = new InitialContext(System.getProperties());

// 1: Lookup ConnectionFactory via JNDI


TopicConnectionFactory factory = (TopicConnectionFactory)
ctx.lookup(“TopicConnectionFactory”);

// 2: Use ConnectionFactory to create JMS connection


TopicConnection connection = factory.createTopicConnection();

// 3: Use Connection to create session


TopicSession session = connection.createTopicSession(false,
Session.AUTO_ACKNOWLEDGE);

// 4: Lookup Destination (topic) via JNDI


Topic topic = (Topic) ctx.lookup(“testtopic”);

// 5: Create a Message Producer – associating the session with the topic


TopicPublisher publisher = session.createPublisher(topic);

// 6: Create a text message, and publish it


TextMessage msg = session.createTextMessage();
msg.setText(“This is a test message.”);
publisher.publish(msg);
}
}

© 2006, Watsh Rajneesh. All Rights Reserved.


51/86 2/9/2008

createTopicSession takes two params: false means we don’t want to use transactions and
Session.AUTO_ACKNOWLEDGE means to auto acknowledge the receipt of a message. This is meant for
receiver of the message. Since we are sending messages to the topic so we don’t really care about this
param.

Message driven beans are message consumers. It was introduced in EJB 2.0. It can receive JMS messages
as well as other types of messages (using pluggable message providers feature for receiving non JMS
messages – this feature support was added in EJB 2.1 Spec). Message driven beans consume messages of a
given message type in accordance with the message listener interface it employs, that is JMS-based
message driven beans will implement javax.jms.MessageListener interface. As of EJB 2.1, Message
driven beans can employ different listener interfaces to consume different message types in addition to JMS
(like EIS specific messages). This is achieved with help from J2EE connector architecture 1.5. So you
can provide resource adapters to asynchronously deliver messages to message endpoints (MDBs)
residing in the app server independent of specific messaging type or semantics. So resource adapters
can act as message providers. Resource adapters are pluggable to any J2EE compliant app server. For
example, to receive EbXML messages in your enterprise application, we can write a EbXML resource
adapter which provides a specific messaging listener interface (say, com.xyz.EbXMLMessageListener)
which can be implemented by MDBs so as to receive EbXML messages. Thus, any enterprise application
can send any type of messages to a MDB via J2EE connector architecture based resource adapter.

A client cannot access a MDB through a component interface. They can only send messages to the MDB
which it will receive and process. So, MDBs don’t have home, local home, remote or local interface.

The resource adapter (via the container) calls the onMessage() (or similar method as defined by the specific
message listener interface that MDB implements) upon arrival of a message. The
javax.jms.MessageListener has onMessage() method which can accept a JMS message of types:
1. ByteMessage ,
2. ObjectMessage,
3. TextMessage,
4. StreamMessage or
5. MapMessage.

© 2006, Watsh Rajneesh. All Rights Reserved.


52/86 2/9/2008

You can use instanceof operator to determine the exact type of a message at runtime.

Listener method(s):
1. May not have a return value
2. Might not send back an exception to clients but can generate a system level exception due to a
unchecked exception unhandled in the code and container will handle such exceptions.
3. Message driven beans are stateless. Thus multiple instances of MDB can process multiple messages
from the JMS destination or resource adaptor consurrently.

Bean class
public interface javax.jms.MessageListener {
public void onMessage(Message message);
}

public interface javax.ejb.MessageDrivenBean extends javax.ejb.EnterpriseBean {


public void ejbRemove() throws EJBException;
public void setMessageDrivenContext(MessageDrivenContext ctx) throws EJBException;
}

Methods to be implemented in an MDB:


1. onMessage(message) – invoked for each message that is consumed by the bean.
2. ejbCreate() – there must be one and only one ejbCreate() method which does not take any argument.
This is similar to stateless session beans as MDBs also donot have any client specific states that span
messasges.
3. Bean class constructor – a default no arg constructor is a must.
4. ejbRemove() – use this method to clean up resources used by bean.
5. setMessageDrivenContext(MessageDrivenContext) –MDB can use the context to callback
transaction related methods only (and not the getCallerPrincipal() etc methods as it does not have a
client associated with it so no client security context to verify).

package examples;
import javax.ejb.*;
import javax.jms.*;
/**
* Sample JMS Message-Driven Bean
*/

© 2006, Watsh Rajneesh. All Rights Reserved.


53/86 2/9/2008

public class LogBean implements MessageDrivenBean, MessageListener {


protected MessageDrivenContext ctx;

/**
* Associates this Bean instance with a particular context.
*/
public void setMessageDrivenContext(MessageDrivenContext ctx) {
this.ctx = ctx;
}

/**
* Initializes the bean
*/
public void ejbCreate() {
System.err.println(“ejbCreate()”);
}
/**
* Our one business method
*/
public void onMessage(Message msg) {
if (msg instanceOf TextMessage) {
TextMessage tm = (TextMessage) msg;
try {
String text = tm.getText();
System.err.println(“Received new message : “ + text);
}
catch(JMSException e) {
e.printStackTrace();
}
}
}
/**
* Destroys the bean
*/
public void ejbRemove() {
System.err.println(“ejbRemove()”);
}
}

Note: A MDB can register with EJB timer service for time based notifications by implementing
javax.ejb.TimedObject interface. Container will then invoke the bean’s ejbTimeout() method upon timer
expiration.

MDB class code is independent of destination type (queue or topic). The deployment descriptor determines
whether a topic or a queue is consumed.

Client (Message Producer)


package examples;

import javax.naming.*;

import javax.jms.*;
import java.util.*;

public class LogBeanClient {

public static void main (String[] args) throws Exception {


Properties env = new Properties();
env.put("java.naming.factory.initial",
"com.sun.enterprise.naming.SerialInitContextFactory");
env.put("java.naming.provider.url",
"iiop://localhost:3700");
InitialContext ctxt = new InitialContext(env);

TopicConnectionFactory factory = (TopicConnectionFactory)


ctxt.lookup("jms/TopicConnectionFactory");

© 2006, Watsh Rajneesh. All Rights Reserved.


54/86 2/9/2008

TopicConnection connection = factory.createTopicConnection();

TopicSession session = connection.createTopicSession(false,


Session.AUTO_ACKNOWLEDGE);

Topic topic = (Topic) ctxt.lookup("jms/Topic");

TopicPublisher publisher = session.createPublisher(topic);

TextMessage msg = session.createTextMessage();

msg.setText("This is a test message.");

publisher.publish(msg);

System.out.println ("Message published to jms/Topic. Please check application”


+ “ server's console to see the response from MDB.");
}
}

Note:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.SerialInitContextFactory");
env.put(Context.PROVIDER_URL, "localhost:1099");
Context initialContext = new InitialContext(env);

Notice that the code does not use the property names such as java.naming. factory.initial, but instead
uses Context.INITIAL_CONTEXT_FACTORY and Context.PROVIDER_URL. This is because the
javax.naming.Context interface defines a set of constants for the names of the properties that you need to
set. Thus, you do not have to remember strings such as java.naming.factory.initial. This also makes your
code more flexible because it is independent of any changes that might be made to the property names in
future versions of JNDI. You will see more on the different properties and their names shortly.

Although it is possible to hard code the JNDI properties, it is the first two approaches that are the most
suitable for production environments. For both, all that you need to do is distribute a text file with the
application.

When you create an InitialContext, JNDI searches for any application resource files called
jndi.properties on the classpath. JNDI also looks in the Java runtime home directory (which is the jre
subdirectory in the Java JDK home directory) for a file called lib\jndi.properties. All the properties
that you define in these files are placed into the environment that belongs to the initial context.

For example, the j2ee.jar file in the lib directory of the J2EE RI contains these lines::

java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory
java.naming.factory.url.pkgs=com.sun.enterprise.naming

These are a set of properties, which are simply name/value pairs. In practice, as long as the j2ee.jar file is
on the classpath, you should be all set.The first of these two properties, java.naming.factory.initial,
enables you to set the fully qualified class name of the Initial Context Factory for the JNDI Service
Provider. That is, you use this property to specify which JNDI Service Provider you want to use.

If you want to use the default naming service supplied with the J2EE RI (and the j2ee.jar file is not on
your classpath), you would use the following line in your jndi.properties file:

java.naming.factory.initial=com.sun.enterprise.naming.SerialInitContextFactory

Sun Microsystems provides several free reference implementations that are mentioned in the Table 14.1.
You can specify the values from the table for the Context.INITIAL_CONTEXT_FACTORY environment
property. Sun Microsystems maintains a list of service providers for JNDI on its Web site at
http://java.sun.com/products/jndi/serviceproviders.html.

© 2006, Watsh Rajneesh. All Rights Reserved.


55/86 2/9/2008

Table 13.1 Values of Context.INITIAL_CONTEXT_FACTORY (java.naming.factory.initial)

Value Naming Service


com.sun.jndi.cosnaming.CNCtxFactory CORBA Naming Service (COS)
com.sun.jndi.fscontext.RefFSContextFactory File System
com.sun.jndi.dnc.DnsContextFactory DNS
com.sun.jndi.ldap.LdapCtxFactory LDAP
com.sun.jndi.rmi.registry.RegistryContextFactory RMI Registry

You can find more information on these properties in the documentation for the javax.naming.Context
and Sun's JNDI Tutorial (http://java.sun.com/products/jndi/tutorial/index.html).

Deployment Descriptor
<?xml version='1.0' encoding='UTF-8'?>
<ejb-jar
xmlns="http://java.sun.com/xml/ns/j2ee"
version="2.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb
-jar_2_1.xsd"
>
<display-name>LogEjb</display-name>
<enterprise-beans>
<message-driven>
<ejb-name>LogBean</ejb-name>
<ejb-class>examples.LogBean</ejb-class>
<messaging-type>javax.jms.MessageListener</messaging-type>
<transaction-type>Bean</transaction-type>
<message-destination-type>javax.jms.Topic</message-destination-type>
<message-destination-link>PhysicalTopic</message-destination-link>
</message-driven>
</enterprise-beans>

<assembly-descriptor>
<message-destination>
<message-destination-name>PhysicalTopic</message-destination-name>
</message-destination>
</assembly-descriptor>
</ejb-jar>

<message-destination-type> Specifies whether the bean should consume queue


or topic messages.

Since the names of actual topic and queue deployed into JMS server are application server specific, the
mapping of a bean’s container to a specific JMS server destination needs to be done in the application
server specific deployment descriptor.

The following example illustrates the use of message destination linking in the deployment descriptor.

<enterprise­beans>
<session>
...
<ejb­name>EmployeeService</ejb­name>
<ejb­class>com.wombat.empl.EmployeeServiceBean</ejb­class>
...
<message­destination­ref>
<message­destination­ref­name>

© 2006, Watsh Rajneesh. All Rights Reserved.


56/86 2/9/2008

jms/EmployeeReimbursements
</message­destination­ref­name>
<message­destination­type>javax.jms.Queue</message­destination­type>
<message­destination­usage>Produces</message­destination­usage>
<message­destination­link>ExpenseProcessingQueue</message­destination­link>
</message­destination­ref>
</session>
...
<message­driven>
<ejb­name>ExpenseProcessing</ejb­name>
<ejb­class>com.wombat.empl.ExpenseProcessingBean</ejb­class>
<messaging­type>javax.jms.MessageListener</messaging­type>
...
<message­destination­type>javax.jms.Queue</message­destination­
type>
<message­destination­link>ExpenseProcessingQueue</message­destination­
link>
...
</message­driven>
...
</enterprise­beans>
...
<assembly­descriptor>
...
<message­destination>
<message­destination­name>ExpenseProcessingQueue</message­destination­
name>
</message­destination>
...
</assembly­descriptor>

The Application Assembler uses the message­destination­link element to indicate that the message destination reference
EmployeeReimbursement  declared in the EmployeeService  enterprise bean is linked to the ExpenseProcessing 
message-driven bean by means of the commen destination ExpenseProcessingQueue.

Optionally, as of EJB 2.1, you can add <application-config-property> as sub-elements to <message-driven>


tag where you can configure the MDBs operational information:
<activation-config-property> Destination Type configuration for MDB (whether
<activation-config-property-name> they consume messages from queue or topic)
destinationType
</activation-config-property-name>
<activation-config-property-value>
javax.jms.Topic
</activation-config-property-value>
</activation-config-property>
<activation-config-property> Message Selector (used to filter messages sent to
<activation-config-property-name> bean). They increase performance by reducing the
messageSelector number of messages sent to MDBs.
</activation-config-property-name>
<activation-config-property-value> The message provider (client) must first set the
JMSType=’log’ AND logLevel=’severe’ header on JMS message using JMS API as
</activation-config-property-value> message.setStringProperty(“logLevel”, “severe”)
</activation-config-property> before sending message to destination (a queue or
topic). The container applies the message selector
criteria before delivering message to a MDB.
<activation-config-property> In case of CMT (container managed transaction)
<activation-config-property-name> there is no need for acknowledgement as the
acknowledgeMode container delivers the message to MDB in the
</activation-config-property-name> context of a transaction, and if the transaction rolls
<activation-config-property-value> back then the message is automatically put back on

© 2006, Watsh Rajneesh. All Rights Reserved.


57/86 2/9/2008

Auto-acknowledge the queue.


</activation-config-property-value>
</activation-config-property> For BMT, the transaction occurs within MDB and
begins and ends in the onMessage() method, in
which case you need to tell the container to
acknowledge the receipt of messages to the JMS
server. You can either tell the container to
immediately acknowledge the receipt of the
message (Auto-acknowledge) in case of successful
return from onMessage() but if some Runtime
exception is thrown by your bean then the container
will handle it and will put back the message on the
queue. Or you can tell the container to take its own
time (Dups-ok-acknowledge) to acknowledge the
receipt of message to the JMS server (based on
when the container finds computing time/resource to
do so) in which case the container may not
acknowledge the message fast enough and your
MDB might receive the same message (duplicate)
again. You should use this only if you can tolerate
duplicate messages.
<activation-config-property> Durability allows persistent messages to be sent to a
<activation-config-property-name> topic on the JMS server. So if the application server
subscriptionDurability hosting the MDB crashes then the message will be
</activation-config-property-name> persisted on the JMS server topic until the MDB
<activation-config-property-value> subscribed to the topic is active again and has
NonDurable acknowledged the consumption of all stored
</activation-config-property-value> messages. MDB can register itself as durable or
</activation-config-property> non-durable subscriber to messages published to a
topic.

Define the app server specific ejb-jar file:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 8.0 EJB 2.1//EN
" "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_2_1-0.dtd">
<sun-ejb-jar>
<enterprise-beans>
<name>LogEjb</name>
<ejb>
<ejb-name>LogBean</ejb-name>
<jndi-name>jms/Topic</jndi-name>
<mdb-connection-factory>
<jndi-name>jms/TopicConnectionFactory</jndi-name>
</mdb-connection-factory>
</ejb>
<message-destination>
<message-destination-name>PhysicalTopic</message-destination-name>
<jndi-name>jms/Topic</jndi-name>
</message-destination>
</enterprise-beans>
</sun-ejb-jar>

You can use the deploy tool for the app server to create the JMS Resources : Connection resource as well as
the Destination Resource. You will be asked to provide a JNDI name when you create these resources. In

© 2006, Watsh Rajneesh. All Rights Reserved.


58/86 2/9/2008

our case, they should be jms/TopicConnectionFactory (connection resource) and jms/Topic (destination
resource).

Deploy the EJB jar file for your bean. Run the client to publish the message on the Topic, and check the
server log file where the bean will have printed out the message received.

The container that subscribes to a topic consumes any given message only once. So if five instances of
MDB exist in the pool, only one of the instances will receive any particular message. Other instances can
be used to concurrently process other messages published on the same topic.

If same MDB is deployed to many containers in a cluster, then each deployment of the JMS MDB will
consume a message from the topic it subscribes to. So the same message will be processed by an MDB
instance residing in different containers in the cluster. If you want that each message is consumed only
once in a cluster, then deploy a Queue instead of a Topic. For a Queue type destination, the JMS server
will deliver any message on the queue to only one consumer (container). Each container registers as a
consumer to the Queue and the JMS server load-balances messages to the consumers based on consumer’s
availability. JMS MDBs that bind to Queues that are deployed in a cluster are ideal for scalable
processing of messages.

JMS server does not guarantee delivery of messages to a pool of JMS MDBs in any particular order. So
MDBs should be prepared to process messages that are not in sequence.

You can use Queues to partition business processing in a cluster as shown below:

© 2006, Watsh Rajneesh. All Rights Reserved.


59/86 2/9/2008

Thus two different queues can be used to partition the business processing in a cluster. The production
queue will experience more load from real users so the cluster size for production stack systems can be
scaled to accommodate more traffic.

A poison message is a message that is continuously re-transmitted by a JMS destination to the consumer
because the consumer continuously fails to acknowledge the consumption of the message. This can happen
if in case of container managed transaction, the MDB calls messageDrivenContext.setRollbackOnly()/or
throws some system level exception, every time forcing the transaction to be rolled back and the container
will not send an acknowledgement in this case so the destination will resend the message to the consumer.
To avoid this case, its best not to throw a system level exception (like EJBException) and MDB’s should
not throw application level exception (its discouraged practice as application level exceptions are meant for
clients and MDBs don’t have clients), so just log the error and return (thus ignoring the message which
caused the error and continue to process next message). Remember, application level exceptions when
thrown will not lead to a transaction roll back.

If Bean managed transaction is used for MDB instead of container managed transaction, then the container
does not have any transaction to rollback and thus the acknowledgement of message is always carried out.
So use Bean Managed Transaction to avoid the possibility of poison messages.

EJB spec does not define any mechansim that specifies how MDBs can propagate a response back to client
that originally generated the message. Heres a strategy to employ when you want the client to receive the

© 2006, Watsh Rajneesh. All Rights Reserved.


60/86 2/9/2008

responses from MDBs (in a somewhat secure way guaranteeing fault tolerance, message filtering etc). For
more alternatives refer page 249-253 of Mastering EJB 3rd Edn book.

Application properties can be set by setTextMessage() method on the client end using JMS API. Security
can be improved by introducing a session EJB (stateless/stateful) as the topic that response messages are
delived to can be made available only internally by simply not exposing it to direct client access. A fixed
OutgoingResponseTopic is created at the JMS server where the responses are posted by the MDBs. Further
application properties can be added to the outgoing message by the client (for eg. If the client sends out
more than one request then it might also want to filter on the RequestID parameter with which it can
associate an incoming response message with a request.)

EJB Environment & Best Practices


From within the container, when calling one bean from another bean, you can obtain the default JNDI
initial context (ie you don’t need to pass a Context.INITIAL_CONTEXT_FACTORY and
Context.PROVIDER_URL. These will values will be set to default for your container.) So you can say:
// Obtain the DEFAULT JNDI initial context by calling the
// no-argument constructor
Context ctx = new InitialContext();

// Look up the home interface


Object result = ctx.lookup(“java:comp/env/ejb/CatalogHome”);

// Convert the result to the proper type, RMI-IIOP style


CatalogHome home = (CatalogHome) javax.rmi.PortableRemoteObject.narrow(result,
CatalogHome.class);

// Create a bean
Catalog c = home.create(...);

java:comp/env/ejb context is the recommended context in which to put your bean names that are
referrenced from other beans.

© 2006, Watsh Rajneesh. All Rights Reserved.


61/86 2/9/2008

EJB References
An EJB reference is a nickname for the JNDI location that you want to look up a bean. Your code then
looks up a home reference via this nickname and the deployer then binds that nickname (ejb reference) to
the JNDI location of its choice. For example,
...
<enterprise-beans>
<!--
Here, we define our Catalog bean. Notice we use the
“Catalog” ejb-name. We will use this below.
-->
<session>
<ejb-name>Catalog</ejb-name>
<home>examples.CatalogHome</home>
...
</session>
<session>
<ejb-name>Pricer</ejb-name>
<home>examples.PricerHome</home>
...
<ejb-ref>
<description>
This EJB reference says that the Pricing Engine
session bean (Pricer) uses the Catalog Engine
session bean (Catalog)
</description>

<!--
The nickname that Pricer uses to look
up Catalog. We declare it so the deployer
knows to bind the Catalog home in
java:comp/env/ejb/CatalogHome. This may not
correspond to the actual location to which the
deployer binds the object via the container
tools. The deployer may set up some kind of
symbolic link to have the nickname point to the
real JNDI location.
-->
<ejb-ref-name>ejb/CatalogHome</ejb-ref-name>

<!-- Catalog is a Session bean -->


<ejb-ref-type>Session</ejb-ref-type>

<!-- The Catalog home interface class -->


<home>examples.CatalogHome</home>

<!-- The Catalog remote interface class -->


<remote>examples.Catalog</remote>

<!-- (Optional) the Catalog ejb-name -->


<ejb-link>Catalog</ejb-link>
</ejb-ref>
</session>
</enterprise-beans>
...

Similar to the message-destination-link we saw earlier where a JMS destination was being shared between
two beans linking by the message-desitination-name. Similarly, when one bean has to lookup another
bean’s home interface then it can link to the bean by the ejb-link tag using bean name (optionally) and has
to specify the nickname with which it will be looking up the bean. The deployer will use the information in
the DD under Pricer bean to bind the Catalog bean with the nickname (or use a JNDI symbolic link) in the
JNDI tree. The Catalog bean could also reside in some other Ejb jar file than Pricer bean using its own DD.

A bean can also access another bean using its Local interface in the same fashion. Only change the

© 2006, Watsh Rajneesh. All Rights Reserved.


62/86 2/9/2008

1. <ejb-ref> to <ejb-local-ref>,
2. <home> to <local-home> and
3. <remote> to <local>.

The lookup code will change accordingly,

// Obtain the DEFAULT JNDI initial context by calling the


// no-argument constructor
Context ctx = new InitialContext();

// Look up the home interface


Object result = ctx.lookup(“java:comp/env/ejb/CatalogLocalHome”);

// Convert the result to the proper type. No RMI-IIOP cast


// required since local interfaces are being used.
CatalogLocalHome home = (CatalogLocalHome) result;

// Create a bean
CatalogLocal c = home.create(...);

Resource Factories
A resource factory is the driver that gives you connections (eg JDBC/JMS driver or JCA resource
adapter). EJB mandates that you need to use JNDI to lookup a resource factory.
// Obtain the initial JNDI context
Context initCtx = new InitialContext();

// Perform JNDI lookup to obtain resource factory


javax.sql.DataSource ds = (javax.sql.DataSource) initCtx.lookup(“java:comp/env/jdbc/ejbPool”);

And in your DD:


...
<enterprise-beans>
<session>
<ejb-name>Catalog</ejb-name>
<home>examples.CatalogHome</home>
...
<!--
This element indicates a resource factory reference
-->
<resource-ref>
<description>
This is a reference to a JDBC driver used within
the Catalog bean.
</description>
<!--
The JNDI location that Catalog uses to look up
the JDBC driver.
We declare it so the deployer knows to bind the
JDBC driver in java:comp/env/jdbc/ejbPool.
-->
<res-ref-name>jdbc/ejbPool</res-ref-name>
<!--
The resource factory class
-->
<res-type>javax.sql.DataSource</res-type>
<!--
Security for accessing the resource factory.
Can either be “Container” or “Application”.
-->
<res-auth>Container</res-auth>
<!--
Whether connections should be shared with other
clients in the different transactions
-->

© 2006, Watsh Rajneesh. All Rights Reserved.


63/86 2/9/2008

<res-sharing-scope>Sharable</res-sharing-scope>
</resource-ref>
</session>
</enterprise-beans>
...

Environment Properties
These are application specific properties that your beans read in at run time. Container reads in this DD and
makes the environment properties available for your bean at runtime. These are put in java:comp/env
context or in some subcontext of this context.

...
<enterprise-beans>
<session>
<ejb-name>Pricer</ejb-name>
<home>examples.PricerHome</home>
...
<!--
This element contains a single environment property.
The property is only accessible from the Pricer.
-->
<env-entry>
<description>
The algorithm for this pricing engine.
</description>
<!--
The JNDI location that Pricer uses to look up
the environment property. We declare it so the
container knows to bind the property in
java:comp/env/PricerProperties/algorithm.
-->
<env-entry-name>Pricer/algorithm</env-entry-name>
<!-- The type for this environment property -->
<env-entry-type>java.lang.String</env-entry-type>
<!-- The environment property value -->
<env-entry-value>NoTaxes</env-entry-value>
</env-entry>
</session>
</enterprise-beans>
...

Using the environment properties is as follows:

// 1: Acquire the initial context


Context initCtx = new InitialContext();

// 2: Use the initial context to look up


// the environment properties
String taxAlgorithm = (String) initCtx.lookup(“java:comp/env/Pricer/algorithm”);

// 3: Do what you want with the properties


if (!taxAlgorithm.equals(“NoTaxes”)) {
// add tax
}

EJB Object Handles


EJB Object handle is a long-lived proxy for an EJB Object. It’s a persistent reference to an EJB object.
The getHandle() method is available only for remote interfaces (not local ones). Handles are not
guranteed to be portable across containers from different vendors nor across machines.

So if you have some items in your shopping cart (viz implemented as a stateful session bean) and you
happen to loose connection, you’d want your shopping cart state maintained when you reconnect. Here’s
how you use it:

© 2006, Watsh Rajneesh. All Rights Reserved.


64/86 2/9/2008

// First, get the EJB object handle from the EJB object.
javax.ejb.Handle myHandle = myEJBObject.getHandle();

// Next, serialize myHandle, and then save it in


// permanent storage.
ObjectOutputStream stream = ...;
stream.writeObject(myHandle);

// time passes...

// When we want to use the EJB object again,


// deserialize the EJB object handle
ObjectInputStream stream = . . .;
Handle myHandle = (Handle) stream.readObject();

// Convert the EJB object handle into an EJB object


MyRemoteInterface myEJBObject = (MyRemoteInterface)
javax.rmi.PortableRemoteObject.narrow(myHandle.getEJBObject(), MyRemoteInterface.class);

// Resume calling methods again


myEJBObject.callMethod();

Home Handles
Persistent references to Home Objects. They may be useful because you can acquire a reference to a home
object, persist it, and then use it again later without knowledge of the home object’s JNDI location.

// First, get the EJB home handle from the home object.
javax.ejb.HomeHandle homeHandle = myHomeObject.getHomeHandle();

// Next, serialize the home handle, and then save it in


// permanent storage.
ObjectOutputStream stream = ...;
stream.writeObject(homeHandle);

// time passes...

// When we want to use the home object again,


// deserialize the home handle
ObjectInputStream stream = ...;
javax.ejb.HomeHandle homeHandle = (HomeHandle) stream.readObject();

// Convert the home object handle into a home object


MyHomeInterface myHomeObject = (MyHomeInterface)
javax.rmi.PortableRemoteObject.narrow(homeHandle.getHomeObject(),
MyHomeInterface.class);

// Resume using the home object


myHomeObject.create();

If distributed transactions are a must for your application then Spring + POJO will not work. But Spring
framework does support EJB based development of application. They provide a lightweight framework for
writing business tier (lightweight because they provide declarative local transaction for POJO without
relying on the container.)

StrutsEJB project (http://strutsejb.dev.java.net) provides base classes and patterns (mainly business
delegate, service locator, DTO, and Session Façade) to build Struts web application that uses EJB in the
business tier.

Struts also provides tag libraries for generating device markups (WML, HDML, and XHTML) for small
device support.

Model Driven Development (MDD) : model typically represents entity in the problem domain. MDD tools
like Compuware OptimalJ or AndoMDA MDD can generate core J2EE design patterns (with discretion

© 2006, Watsh Rajneesh. All Rights Reserved.


65/86 2/9/2008

from the architect) from model diagrams. IBM RDD (Rational Rapid Developer) donot support any
specific standard for MDD but have their own paradigm. MDD suits better for new applications. Refer
http://middlewareresearch.com/endeavors/031126MDDCOMP/endeavor.jsp.

Extreme Programming (XP) is a software engineering discipline whose core practices revolve around an
underlying assumption: Change in requirements and hence software design will inevitably occur during the
course of software development. Original thinker of XP – Kent Beck.
Core principles are:
1. Iterative development: development is given a certain target to meet per iteration (checkpoints or
milestones). Features for the iteration are defined.
2. EJB subphase: development phase for designing, developing, building and deploying EJBs on
development systems.
3. Testing subphase: build unit test clients.
4. User subphase: present work done to actual users who test the application using the acceptance
test plan. Avoid adding new features in the middle of the iteration.
5. Continuous Integration: keeping various application components in sync with each other so that
system is fully integrated most times. Builds should be made atleast once a day. Idea is not to defer
integration until last moment.
6. Refactoring: process of continuously improving the design of existing code without affecting
code behavior. Involves restructuring of code so as to remove redundant code, reduce coupling in
code, introduce better naming conventions in the code, or organize the code more cohesively. For
more, refer http://industriallogic.com/xp/refactoring/catalog.html.
7. Test-driven development: prime focus for XP.
XP is lightweight compared to more formal design processes like Rational Unified Process (RUP) or now
obsoleted waterfall model.

Apache Cactus (http://jakarta.apache.org/cactus/) is an extension of Junit specifically catering to testing


enterprise java applications. Using Cactus makes more sense when you bean clients are Servlets/JSP which
also reside in the J2EE environment (which is usually the case) as it tests these clients as well apart from
EJB. You get end-to-end framework for unit testing EJB applications with a web front end. Cactus allows
for writing three types of test case classes based on the ServletTestCase, JspTestCase, and FilterTestCase
classes also known as redirectors. Hence, your test case classes will extend any one of these, depending on
which client model you use, and get a home reference to your EJB, create an instance, call the method on it,
and assert the test results. Ant task <cactus>, provides ANT integration.

Aspect-Oriented Programming (AOP): aspects are the core of AOP. Aspects are reusable services that
are quintessentially crosscutting to your application (eg, services that provide user authentication,
authorization, logging of access to system, and persistence of application data). Crosscutting concerns
because developer cannot write robust applications without taking care of them. Hence AOP is a
programming platform that facilitates the development of aspects to mitigate concerns so that aspects can
be reused by all living objects within a given environment.

EJB containers implement these crosscutting concerns and provide reusable aspects so that all the beans
deployed within the container can offload these concerns on the container aspects. So EJB container is an
Aspect Oriented Implementation. EJB programming model does not allow you to develop new aspects to
take care of concerns that are not supported by EJB container. So J2EE is not a AOP platform even though
EJB uses AOP techniques. In order to use AOP in EJB, you can use frameworks like Spring AOP, AspectJ
or tools provided by App Server vendors. JBoss and Websphere provide AOP support. So until EJB spec
allows for AOP as standard, you loose portability using AOP with custom vendor tools.

POJOs are used to get around contraints imposed by EJB standard – like accessing filesystem or
read/write static fields (you cannot use static fields in your EJBs). We might also end up reusing these
POJOs outside the EJB container, for example, in a Web application or a Swing application. In this

© 2006, Watsh Rajneesh. All Rights Reserved.


66/86 2/9/2008

scenario, it might be better to write reusable aspects to address concerns relevant to your POJOs. For
example, consider a POJO that reads and writes to a file. Here you might need to log the
timestamp of the last updating of the file. In which case, you would create an aspect to address the logging
concern. This way you can use the Logging aspect no matter whether your POJO is being used within an
EJB container or within a Web container or in a vanilla Java Swing application.

OOP does not work when behavior needs to be reused horizontally, owing to the behavior’s crosscutting
nature. Now why would you need to reuse behavior horizontally? Because you do not want your business
object, for example a ShoppingCart, to inherit the behavior pertaining to transactions, since these behaviors
are unrelated; you do not want an apple to inherit grape-like qualities; rather you want to mix apples and
grapes to prepare a margarita drink. This is where AOP comes into picture. AOP and OOP are not
competing but complementary technologies. Consider, for example, an EJB server where crosscutting
aspects are provided to your object-oriented beans.

EJB programming APIs support only static invocation (where information about the interface and
methods to invoke on its object are known at the compile time).

Reflection facilitates dynamic (runtime) invocation of methods already implemented in class. Dynamic
proxy approach allows dynamically implementing a proxy class that implements a list of interfaces
specified by class at runtime. Proxy is generated dynamically and method invocation on the proxy object
(for eg. java.lang.reflect.Proxy) is dispatched to a single method named invoke() which takes the method
name and invokes it via java.lang.reflect.Method object and takes the method arguments as Object[]. Thus
dynamic proxy object uses reflective mechanism and provides a generic object that is capable of
intercepting methods from clients on behalf of any server object implementing the interfaces this dynamic
proxy implements. You can use it to dynamically invoke methods on EJB when client does not have a priori
knowledge of interfaces implemented by EJB.

To automate deployment of your EJB applications on multiple application servers, you can use XDoclet
framework. XDoclet is a powerful, attribute oriented code generation engine. Using XDoclet, a developer
can generate practically anything – XML descriptors (DDs – both standard and server specific ones), source
code and so on – by inserting attributes (metadata) within Javadoc for their source. Uses are: Generate code
for Value classes, primary key classes, struts action form based on Entity EJB, and home and remote
interfaces. Also integration of XDoclet with ANT through Ejbdoclet tasks makes it even more powerful
framework for deployments.

Transactions
We must guarantee data integrity even when many users concurrently update the data. A transaction is a
series of operations that appear to execute as one large, atomic operation. Databases also offer concurrency
control with different levels of isolation. But concurrency control for an enterprise application is not only
required at datasource level but at the application level where you might have several steps in a business
logic being performed and you require them to be one atomic operation – and of these steps, accessing a
datasource might just be one part but within your EJB the transaction service will guarantee that if any
unchecked or remote exception is thrown then container will rollback the transaction in which case revert
your bean state to the original state and in case you used CMP for your datasource access then it will even
not commit the data change you made to the datasource. Thus effectively the state of bean(s) will be
changed only on success of all steps constituting the business method (or a series of them if multiple beans
are involved and the same transaction is in effect for those beans – it is possible to start a new transaction
for a bean’s business method though in which case if the new transaction rolls back and the business
method throws an unchecked exception to the calling bean’s business method then the original transaction
will also be rolled back). Since beans are single threaded so concurrency control is provided by the
container by default by executing other bean instance of same type (from the instance pool) in case of
concurrent requests. The bean code does not have to code for concurrency control.

© 2006, Watsh Rajneesh. All Rights Reserved.


67/86 2/9/2008

Transaction Jargons
4. Transaction Object: A transactional object (or transactional component) is an application
component, such as a banking component, that is involved in a transaction.
5. Transaction Manager: A transaction manager is responsible for managing the
transactional operations of the transactional components. It manages the entire overhead of a
transaction, running behind the scenes to coordinate things
6. Resource: A resource is a persistent storage from which you read or write. A resource could be
a database, a message queue, or other storage.
7. Resource Manager: A resource manager manages a resource. An example of a resource
manager is a driver for a relational database, object database, message queue, or other store.
Resource managers are responsible for managing all state that is permanent. The most popular
interface for resource managers is the X/Open XA resource manager interface. Most database
drivers support this interface. Because X/Open XA is the de facto standard for resource managers,
a deployment with heterogeneous XA resource managers from different vendors can interoperate.

Transactional Models
Flat Transactions: is a series of operations that are performed atomically as a
single unit of work. Flat transactions can be chained too but if one of the
subtransaction rolls back then it causes the outer transactions to rollback too. This is
the behavior supported by EJB transaction service.

Nested Transactions: Anested transaction enables you to embed atomic units of work within
other units of work. The unit of work that is nested within another unit of work can roll back without
forcing the entire transaction to roll back. Therefore the larger unit can attempt to retry the embedded unit
of work. If the embedded unit can be made to succeed, the larger unit can succeed. If the embedded unit of
work cannot be made to work, it will ultimately force the entire unit to fail.

What’s special about nested transactions is that subtransactions can independently roll back without
affecting higher transactions in the tree. That’s a very powerful idea, and it solves our famous trip-
planning problem: If each individual booking is a nested transaction, we can roll back any one booking
without canceling all our other reservations. But in the end, if the nested transaction cannot be committed,
the entire transaction will fail.

EJB spec does not mandate support for nested transactions though so all
transactions are flat for EJBs.

A container managed transaction is shown below:

© 2006, Watsh Rajneesh. All Rights Reserved.


68/86 2/9/2008

The bean’s business method executes in the transaction context controlled by the
container (which delegates to the bean for executing the business method). So if
there is any system level execption in the bean then the transaction is rolled back by
the container. If a session bean’s transaction is already been initiated and in its
business method the bean invokes a method on an entity bean then the entity bean
can either leverage the same transactional context (Supports/Required transactional
attribute) and execute within it or it can tell the container to start a new transactional
context (RequiresNew) for its own use.

You can even have a client-initiated transaction in which case a servlet/JSP tag
library, application/applet or CORBA client or another enterprise bean which is client
to your bean can being and end transactions in that client.

Entity beans must use declarative or container managed transactions only


as loading of data from the datasource and storing/updating the data in the
datasource happen in two different methods (ejbLoad and ejbStore). When a business
method of an entity bean is called then container first invokes the ejbLoad() to get
the entity bean instance associated with data and once the business method
completes, container will call the ejbStore() to sync up the database with the in-
memory entity bean instance. So if we are doing programmatic transaction in an
entity bean then we will have open the transaction in the ejbLoad() and close it in the
ejbStore(). But since these methods are called by container so the bean has no say in
what order or when the container calls these methods. So if one starts a transaction
in ejbLoad then the transaction may not get a chance to complete if the container
decides not to call the ejbStore after the business method (depends on the container
algo – if it sees there isnt any change in the database data and the in-memory cache
so it wont have anything to write back – in case where the business method called
after ejbLoad errored out of did not change the state). So bean managed
transaction is illegal for entity beans. Session and Message driven beans can
have programmative (BMT) and CMT as their data access can happen within a single
method boundary.

A corollary of this discussion is that entity beans do not load and store their data on every method call;
rather, they load and store their data on every transaction. If your entity beans are not performing well,

© 2006, Watsh Rajneesh. All Rights Reserved.


69/86 2/9/2008

it could be because a transaction is happening on each method call, and thus a database read/write is
happening on every get/set method. The solution is to make sure your transactions begin
earlier and end later, perhaps encompassing many entity bean method calls. By
properly controlling the duration of your transactions with transaction attributes, you can control when
database reads and writes happen with entity beans.

Transaction Attributes
A transaction attribute is a setting that you give to a bean to control how your bean is enlisted in container-
managed transactions. The transactional attribute is a required part of each bean’s deployment descriptor.
The container knows how transactions should be handled with a bean by reading that bean’s transaction
attribute from its deployment descriptor. Note that you can specify transaction attributes for entire beans or
for individual bean methods. If both are specified, then method-level attributes take precedence.

<assembly-descriptor>
<!--
This demonstrates setting a transaction attribute
on every method on the bean class.
-->
<container-transaction>
<method>
<ejb-name>Employee</ejb-name>
<method-name>*</method-name>
</method>
<!--
Transaction attribute. Can be “NotSupported”,
“Supports”, “Required”, “RequiresNew”,
“Mandatory”, or “Never”.
-->
<trans-attribute>Required</trans-attribute>
</container-transaction>
<!--
You can also set transaction attributes on individual methods.
-->
<container-transaction>
<method>
<ejb-name>Employee</ejb-name>
<method-name>setName</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
<!--
You can even set different transaction attributes on
methods with the same name that take different parameters.
-->
<container-transaction>
<method>
<ejb-name>Employee</ejb-name>
<method-name>setName</method-name>
<method-param>String</method-param>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>

You must specify transaction attributes on all business methods for your beans. Furthermore, with entity
beans you must specify transaction attributes that cover home interface methods, because the home
interface creation methods insert database data and thus need to be transactional.

JCA and Transactions


The J2EE Connector Architecture defines a standard contract between Resource Adapters (RA) and
application servers such that RA can leverage the container services for supporting transactions. This
standard contract enables an application server to provide the infrastructure and runtime environment for

© 2006, Watsh Rajneesh. All Rights Reserved.


70/86 2/9/2008

transaction management of RA components. RA can support either a local transaction, which is managed
internally by the resource manager, or it can support a distributed transaction, whose coordination does
involve external transaction managers. If RA that supports local transactions, the client component, such as
an EJB, will have to acquire the common client interface API object, such as
javax.resource.cci.LocalTransaction or an equivalent from the resource adapter to demarcate the
transactions. If RA supports distributed transactions, the container will automatically enlist the client in the
transaction context, if the client wants to work within a distributed transaction. J2EE Connector
Architecture 1.5 supports the inflow of transactions fromEnterprise Information System (EIS) to the J2EE
environment. This is a powerful addition because it enables the J2EE applications to participate in
transactions initiated by backend EIS. For example, you can make your stateless session bean participate in
a transaction that was initiated in the Tuxedo environment, given that the underlying RA supports this
contract.

Required
You should use the Required mode if you want your bean to always run in a transaction. If a transaction is
already running, your bean joins in on that transaction. If no transaction is running, the EJB
container starts one for you.
The customer wants to use the credit card component to charge a user’s credit card when a user purchases a
product from a Web site. The customer then wants to submit an order to manufacture that product, which is
handled by a separate component. Thus, the customer has two separate components running but both of
them run under the same transaction. If the credit card cannot be charged, the customer doesn’t want the
order to be submitted. If the order cannot be submitted, the customer doesn’t want the credit card charged.
Therefore the customer produces his or her own workflow bean, which first calls our credit card–charging
bean and then calls the bean to generate a manufacturing order. The workflow bean is deployed with
Required, so a transaction automatically starts up. Because your credit card bean is also deployed with
Required, you join that transaction, rather than start your own transaction. If the order submission
component is also deployed with Required, it joins the transaction as well. The container commits or aborts
the transaction when the workflow bean is done.

RequiresNew
You should use the RequiresNew attribute if you always want a new transaction to begin when your
bean is called. If a transaction is already under way when your bean is called, that transaction is suspended
during the bean invocation. The container then launches a new transaction and delegates the call to the
bean. The bean performs its operations and eventually completes. The container then commits or aborts the
transaction and finally resumes the old transaction. RequiresNew is useful if your bean needs the ACID
properties of transactions but wants to run as a single unit of work without allowing other external
logic to also run in the transaction.

Supports
When a bean is called with Supports, it runs in a transaction only if the client had one running
already. If the client does not have a transaction, the bean runs with no transaction at all. Because Supports
will sometimes not run within a transaction, you should be careful when using this attribute. Mission-
critical operations should be encapsulated with a stricter transaction attribute (like Required).

Mandatory
Mandatory mandates that a transaction must be already running when your bean method is called. If a
transaction isn’t running, the javax.ejb.TransactionRequiredException exception is thrown back to the
caller (or javax.ejb.Tranasction- RequiredLocalException if the client is local). Mandatory is useful if your
component is designed to run within a larger system, such as a workflow system, where your bean is only
part of a larger suite of operations, and you want to mandate that the larger operations start a transaction
before calling your bean.

© 2006, Watsh Rajneesh. All Rights Reserved.


71/86 2/9/2008

NotSupported
If you set your bean to use NotSupported, then your bean cannot be involved in a transaction at all.
For example, assume we have two enterprise beans, Aand B. Let’s assume bean A begins a transaction and
then calls bean B. If bean B is using the NotSupported attribute, the transaction that A started is suspended.
None of B’s operations are transactional, such as reads/writes to databases. When B completes, A’s
transaction is resumed.
You should use NotSupported if you are certain that your bean operations do not need the ACID properties.
This should be used only if your beans are performing non–mission-critical operations, where you are not
worried about isolating your bean’s operations from other concurrent operations. An example here is an
enterprise bean that performs rough reporting. If you have an e-commerce Web site, you might write a
bean that routinely reports a rough average number of e-commerce purchases per hour by scanning
a database. Because this is a low-priority operation and you don’t need exact figures, NotSupported is
an ideal, low-overhead mode to use.

Never
The Never transaction attribute means that your bean cannot be involved in a transaction. Furthermore, if
the client calls your bean in a transaction, the container throws an exception back to the client
(java.rmi.RemoteException if remote, javax.ejb.EJBException if local).

This transaction attribute is useful when you want to make sure all clients that call your bean do not use
transactions. This can help reduce errors in client code, because a client will not be able to call your bean
erroneously in a transaction and expect your bean to participate in the ACID properties with other
transaction participants.

© 2006, Watsh Rajneesh. All Rights Reserved.


72/86 2/9/2008

For example, let’s say you want to perform a transfer between two bank accounts. To achieve this, you
might have a bank teller session bean that calls into two bank account entity beans. If you deploy all three
of these beans with the Required transaction attribute, they will all be involved in a single transaction.

Entity beans and stateful session beans with SessionSynchronization must use transactions. The
reason is that both of these types of beans are inherently transactional in nature. Entity beans perform
database updates, and stateful session beans with SessionSynchronization (which we describe later in this
chapter) are also transactional. Therefore you normally can’t use the following attributes: Never,
NotSupported, Supports.

There is no client, and therefore transaction attributes that deal with the notion of a client’s
transaction make no sense for message-driven beans—namely Never, Supports, RequiresNew, and
Mandatory.

Transactional Stateless Session Stateful Session Entity Beans Message Driven


Attributes Beans Beans Beans
implementing
Session
Synchronization
Required Yes Yes Yes Yes
RequiresNew Yes Yes Yes No
Mandatory Yes Yes Yes No
Supports Yes No No No
NotSupported Yes No No Yes
Never Yes No No No

Java Transaction API (JTA)


You can use the JTA in your client and bean code to programmatically control transactional boundaries.
You can do very useful things with the JTA, such as start a transaction inside your bean, call other beans
that also are involved in a transaction, and control whether things commit or abort. Non-EJB applications
can use the JTA as well—the client code that calls your beans can use the JTA to control transaction
boundaries in a workflow scenario, where the client code is calling multiple beans and wants each
bean to participate in one transaction.

javax.transaction.UserTransaction
public interface javax.transaction.UserTransaction {
public void begin(); -- begin a new transaction
public void commit(); -- runs two-phase commit protocol on an existing transaction associated
with current thread. Each resource manager makes its update durable.
public int getStatus(); -- retrieves status of transaction associated with current thread.
public void rollback(); -- rollbacks the transaction associated with current thread.
public void setRollbackOnly(); -- force current transaction to rollback.
public void setTransactionTimeout(int); -- max. time that a transaction can run before its rolled
back.
}
JTA also defines a number of constants that indicate the current status of a
transaction.
public interface javax.transaction.Status {
public static final int STATUS_ACTIVE;
public static final int STATUS_NO_TRANSACTION;
public static final int STATUS_MARKED_ROLLBACK; -- in case some party called setRollbackOnly().
public static final int STATUS_PREPARING; -- Phase one of two phase commit protocol.
public static final int STATUS_PREPARED; -- Phase one completed.
public static final int STATUS_COMMITTING; -- Phase two happening.
public static final int STATUS_COMMITTED; -- Phase two completed.
public static final int STATUS_ROLLING_BACK;
public static final int STATUS_ROLLEDBACK;
public static final int STATUS_UNKNOWN;

© 2006, Watsh Rajneesh. All Rights Reserved.


73/86 2/9/2008

Example bean method carrying out bean managed transaction:


/**
* Deposits amt into account.
*/
public void deposit(double amt) throws AccountException {
javax.transaction.UserTransaction userTran = null;
try {
System.out.println(“deposit(“ + amt + “) called.”);
userTran = ctx.getUserTransaction();
userTran.begin();
balance += amt;
userTran.commit();
}
catch (Exception e) {
if (userTran != null) userTran.rollback();
throw new AccountException(“Deposit failed because of “ + e.toString());
}
}

A bean using the above method, must be deployed with transaction type of Bean. When using
programmatic transaction always try to complete your transactions in the same method in which you began
them.

setRollbackOnly
If your bean is participating in a transaction started by some other bean then you can doom a transaction (Ie
force a transaction to abort) by calling setRollbackOnly() on your EJB context object.

If your transaction participant is a POJO (and not an EJB component) then you will have to lookup the
UserTransaction object in the JNDI and call its setRollbackOnly(), as shown below:
try {
/*
* 1: Set environment up. You must set the JNDI Initial
* Context factory, the Provider URL, and any login
* names or passwords necessary to access JNDI. See
* your application server product’s documentation for
* details on their particular JNDI settings.
*/
java.util.Properties env = ...
/*
* 2: Get the JNDI initial context
*/
Context ctx = new InitialContext(env);
/*
* 3: Look up the JTA UserTransaction interface
* via JNDI. The container is required to
* make the JTA available at the location
* java:comp/UserTransaction.
*/
userTran = (javax.transaction.UserTransaction)
ctx.lookup(“java:comp/UserTransaction”);
/*
* 4: Execute the transaction
*/
userTran.begin();
// perform business operations
userTran.commit();
}
catch (Exception e) {
// deal with any exceptions, including ones
// indicating an abort.
}

© 2006, Watsh Rajneesh. All Rights Reserved.


74/86 2/9/2008

In case there are say 10 beans in a chain executing the same transaction, and bean 2 decides to doom the
transaction then other beans should be able to detect that the transaction has been doomed and avoid
performing work when a doomed transaction exists:
1. Container managed transactional beans can detect doomed transactions by calling
getRollbackOnly() on their EJB Context object. If it returns true, then transaction is doomed.
2. Other participants, such as bean managed transactional beans, can get hold of UserTransaction
object from the JNDI and call its getStatus() method.

Transaction Isolation

Dirty Read
Adirty read occurs when your application reads data from a database that has not been committed to
permanent storage yet. Dirty reads can occur if you use the weakest isolation level, called READ
UNCOMMITTED. With this isolation level, if your transaction is executing concurrently with another
transaction, and the other transaction writes some data to the database without committing, your transaction
will read that data in.
The advantage of this isolation level is performance. The underlying transaction system doesn’t have to
acquire any locks on shared data in this mode.Your code will read committed data only when running in
READ COMMITTED mode. When you execute with this isolation level, you will not read data that has
been written but is uncommitted. This isolation level thus solves the dirty read problem. One great use
for this mode is for programs that read data from a database to report values of the data. Because reporting
tools aren’t in general missioncritical, taking a snapshot of committed data in a database makes sense.
READ COMMITTED is the default isolation level for most databases, such as Oracle or Microsoft SQL
Server.

Unrepeatable Read
Unrepeatable reads occur when a component reads some data from a database, but upon rereading the data,
the data has been changed. This can arise when another concurrently executing transaction modifies the
data being read.

REPEATABLE READ guarantees yet another property on top of READ COMMITTED: Whenever you
read committed data from a database, you will be able to reread the same data again at a later time, and the
data will have the same values as the first time. Hence, your database reads are repeatable. Use
REPEATABLE READ when you need to update one or more data elements in a resource, such as one or
more records in a relational database. You want to read each of the rows that you’re modifying and then be
able to update each row, knowing that none of the rows are being modified by other concurrent
transactions. If you choose to reread any of the rows at any time later in the transaction, you’d be
guaranteed that the rows still have the same data that they did at the beginning of the transaction.

Phantom Read
A phantom is a new set of data that magically appears in a database between two read operations. For
example, if your transaction reads a relational record, and a concurrent transaction commits a new record to
the database, a new phantom record appears that wasn’t there before. You can easily avoid phantoms (as
well as the other problems described earlier) by using the strictest isolation level: SERIALIZABLE.
SERIALIZABLE guarantees that transactions execute serially with respect to each other, and it enforces
the isolation ACID property to its fullest. This means that each transaction truly appears to be independent
of the others. Use SERIALIZABLE for mission-critical systems that absolutely must have perfect
transactional isolation. You are guaranteed that no data will be read that has been uncommitted. You’ll be
able to reread the same data again and again. And mysterious committed data will not show up in your
database while you’re operating due to concurrent transactions.

Note:

© 2006, Watsh Rajneesh. All Rights Reserved.


75/86 2/9/2008

If your bean is managing transactions, you specify isolation levels with your resource manager API
(such as JDBC). For example, you could call java.sql.Connection.SetTransactionIsolation().

If your container is managing transactions, there is no way to specify isolation levels in the deployment
descriptor. You need to either use resource manager APIs (such as JDBC) or rely on your container’s tools
or database’s tools to specify isolation.

Unfortunately, there is no way to specify isolation for container-managed transactional beans in a portable
way—you are reliant on container and database tools. This means if you have written an application, you
cannot ship that application with built-in isolation. The best strategy is to develop EJBs that are as tolerant
of isolation differences as possible. This is the typical technique used by many optimistic concurrency
libraries that have been layered over JDBC and ODBC.

Durability and Two phase commit protocol


To support durability, transactions happen in two phases:
1. Phase 1: begins by sending a before commit message to all resources involved in the transaction.
At this time, the resources involved in a transaction have a final chance to abort the transaction. If
any resource involved decides to abort, the entire transaction is cancelled and no resource updates
are performed. Otherwise, the transaction proceeds on course and cannot be stopped, unless a
catastrophic failure occurs. To prevent catastrophic failures, all resource updates are written to a
transactional log or journal. This journal is persistent, so it survives crashes and can be consulted
after a crash to reapply all resource updates.
2. Phase 2: occurs only if Phase One completed without an abort. At this time, all of the resource
managers, which can all be located and controlled separately, perform the actual data updates.

In the distributed two-phase commit, there is one master transaction manager called the distributed
transaction coordinator. The transaction coordinator runs the show and coordinates operations among the
other transaction managers across the network.

A distributed two-phase commit transaction complicates matters, because the transaction managers must all
agree on a standard mechanism of communicating. The communication mechanism used is called the
transactional communications protocol. The most important piece of information sent over the

© 2006, Watsh Rajneesh. All Rights Reserved.


76/86 2/9/2008

transactional communications protocol is the transaction context. Atransaction context is an object that
holds information about the system’s current transactional state. It is passed around among parties involved
in transactions. By querying the transaction context, you can gain insight into whether you’re in a
transaction, what stage of a transaction you are at, and other useful data. For any component to be involved
in a transaction, the current thread in which the component is executing must have a transaction context
associated with it.

For a stateless session bean, aborting a business process is a simple task—simply throw an exception back
to the client. But for a stateful session bean, things are a bit trickier. Stateful session beans represent
business processes that span multiple method calls and hence have in-memory conversational state.
Tossing away that conversation and throwing an exception to the client could entail a significant amount of
lost work. Fortunately, a well-designed stateful session bean can salvage its conversations in the case of
failed transactions. The key is to design your beans to be aware of changes to conversational state and to be
smart enough to undo any of those changes if a transactional abort occurs.

Your application server can aid you in determining when a transaction failed, enabling you to take
application-specific steps. If your session bean needs to be alerted to transaction status (like failed
transactions), your enterprise bean class can implement an optional interface called
javax.ejb.SessionSynchronization.

public interface javax.ejb.SessionSynchronization


{
public void afterBegin();
public void beforeCompletion();
public void afterCompletion(boolean);
}

The key method that is most important for rolling back conversations is afterCompletion(). The container
calls your afterCompletion() method when a transaction completes either in a commit or an abort. You can
figure out whether a commit or an abort happened by the Boolean parameter that gets passed to you in
afterCompletion(): True indicates a successful commit, false indicates an abort. If an abort happened, you
should roll back your conversational state to preserve your session bean’s conversation.

public class CountBean implements SessionBean, SessionSynchronization {


public int val;
public int oldVal;

public void ejbCreate(int val) {


this.val=val;
this.oldVal=val;
}
public void afterBegin() { oldVal = val;} // save the state
public void beforeCompletion() { }
public void afterCompletion(boolean b) {
if (b == false) val = oldVal; // if transaction failed, the rollback your
converstation state.
}
public int count() { return ++val; }
public void ejbRemove() { }
public void ejbActivate() { }
public void ejbPassivate() { }
public void setSessionContext(SessionContext ctx) { }
}

Note: You can use SessionSynchronization only with Stateful Session Beans using container managed
transactions.

Security
[Covered in my JBoss notes.]

© 2006, Watsh Rajneesh. All Rights Reserved.


77/86 2/9/2008

EJB Timer Service

Relationship between Entity Beans


BMP entity beans manage relationships explicitly in the bean itself.
public class OrderBean implements EntityBean {
// private fields
// get/set methods
// code to manage relationships in ejbXXX methods
}

With CMP, you declare the way you would like your relationships to work in your deployment descriptor.
The container then generates all the relationship code you need when the container subclasses your entity
bean.
<ejb-jar>
<enterprise-beans>
... define enterprise beans ...
</enterprise-beans>
<relationships>
... define EJB relationships ...
</relationships>
</ejb-jar>

Cardinality

The following code shows how to implement a one-to-one relationship using BMP:
public class OrderBean implements EntityBean {
private String orderPK;
private String orderName;
private Shipment shipment; // EJB local object stub
public Shipment getShipment() { return shipment; }
public void setShipment(Shipment s) { this.shipment = s;}
...
public void ejbLoad() {
// 1: SQL SELECT Order. This also retrieves the
// shipment foreign key.
//
// 2: JNDI lookup of ShipmentHome
//
// 3: Call ShipmentHome.findByPrimaryKey(), passing
// in the shipment foreign key
}
public void ejbStore() {
// 1: Call shipment.getPrimaryKey() to retrieve
// the Shipment foreign key
//
// 2: SQL UPDATE Order. This also stores the
// Shipment foreign key.
}
}

© 2006, Watsh Rajneesh. All Rights Reserved.


78/86 2/9/2008

Our ejbLoad() method loads the database data of the order, and part of that data is a foreign key to the
shipment. We need to transform that foreign key into a stub to a shipment bean. Therefore we need to
perform a JNDI lookup of the shipment home and then call a finder method, passing in the foreign key.
This gives us a stub, and we can then call business methods on the shipment.

Our ejbStore() method stores the database data for the order, and part of that data is a foreign key to the
shipment. We need to transform the shipment stub into a foreign key. Therefore, we need to call
getPrimaryKey() on the shipment stub. This gives us our foreign key, and we can then perform the SQL.

The following code shows how to implement that same one-to-one relationship using CMP:
public abstract class OrderBean implements EntityBean {
// no fields
public abstract Shipment getShipment();
public abstract void setShipment(Shipment s);
...
public void ejbLoad() { } // Empty
public void ejbStore() { } // Empty
}
We do need to specify the relationship in the deployment descriptor, and we do so as follows:
<ejb-jar xmlns=”http://java.sun.com/xml/ns/j2ee” version=”2.1”
xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd”>
<enterprise-beans>
...
</enterprise-beans>
<relationships>
<!-- This declares a relationship -->
<ejb-relation>
<!-- The nickname we’re giving this relationship -->
<ejb-relation-name>Order-Shipment</ejb-relation-name>
<!--
This declares the 1st half of the relationship
(the Order side)
-->
<ejb-relationship-role>
<!-- The nickname we’re giving this half of the relationship -->
<ejb-relationship-role-name>
order-spawns-shipment
</ejb-relationship-role-name>
<!-- The Cardinality of this half of the relationship -->
<multiplicity>One</multiplicity>
<!--
The name of the bean corresponding to this
half of the relationship
-->
<relationship-role-source>
<ejb-name>Order</ejb-name>
</relationship-role-source>
<!--
Recall that a CMP entity bean has an abstract get/set
method for the relationship. We need to tell the
container which get/set method corresponds to this
relationship, so that the container can generate the
appropriate scaffolding code when sub-classing our bean.
That is the purpose of this element, which is called the
container-managed relationship (CMR) field. The value
of the CMR field should be the name of your get/set
method, but without the get/set, and with a slight
change in capitalization. getShipment() becomes shipment.
-->
<cmr-field><cmr-field-name>shipment</cmr-field-name></cmr-
field>
</ejb-relationship-role>
<!--
This declares the 2nd half of the relationship
(the Shipment side)

© 2006, Watsh Rajneesh. All Rights Reserved.


79/86 2/9/2008

-->
<ejb-relationship-role>
<ejb-relationship-role-name>
shipment-fulfills-order
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source>
<ejb-name>Shipment</ejb-name>
</relationship-role-source>
</ejb-relationship-role>
</ejb-relation>
</relationships>
</ejb-jar>

The following code shows how to implement a one-to-many relationship using BMP:
public class CompanyBean implements EntityBean {
private String companyPK;
private String companyName;
private Vector employees; // EJB object stubs

public Collection getEmployees() { return employees; }


public void setEmployees(Collection e) {
this.employees = (Vector) e;
}
...
public void ejbLoad() {
// 1: SQL SELECT Company
// 2: JNDI lookup of EmployeeHome
// 3: Call EmployeeHome.findByCompany(companyPK)
}
public void ejbStore() {
// 2: SQL UPDATE Company
}
}
A one-to-many relationship has a Vector of stubs, rather than a single stub. Our get/set method gets and sets
this Vector (a Vector is a Collection).
Our ejbLoad() method is responsible for loading the company state, as well as loading the relationships to
employees. We do so by calling a finder method on the employee local home object. That finder method
locates each employee that is a member of this company and returns a collection of stubs to us. Note that
this causes a second SQL statement to be executed.
The employee (not the company) has an ejbStore() that persists foreign keys to the company.

The following code shows how to implement a one-to-many relationship using CMP:
public abstract class CompanyBean implements EntityBean {
// no fields
public abstract Collection getEmployees();
public abstract void setEmployees(Collection employees);
...
public void ejbLoad() { } // Empty
public void ejbStore() { } // Empty
}

© 2006, Watsh Rajneesh. All Rights Reserved.


80/86 2/9/2008

<ejb-jar xmlns=”http://java.sun.com/xml/ns/j2ee” version=”2.1”


xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd”>
<enterprise-beans>
...
</enterprise-beans>
<relationships>
<ejb-relation>
<ejb-relation-name>Company-Employees</ejb-relation-name>
<ejb-relationship-role>
<ejb-relationship-role-name>
Company-Employs-Employees
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source>
<ejb-name>Company</ejb-name>
</relationship-role-source>
<!--
When you have a relationship with more than one object, you
can use either a java.util.Collection or a java.util.Set.
We need to identify which one we’re using. How do you choose
between a Collection and a Set? A Collection can contain
duplicates, whereas a Set cannot. This needs to match up to
your bean’s get/set methods.
-->
<cmr-field>
<cmr-field-name>employees</cmr-field-name>
<cmr-field-type>java.util.Collection</cmr-field-type>
</cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>
Employees-WorkAt-Company
</ejb-relationship-role-name>
<multiplicity>Many</multiplicity>
<relationship-role-source>
<ejb-name>Employee</ejb-name>
</relationship-role-source>
</ejb-relationship-role>
</ejb-relation>
</relationships>
</ejb-jar>
To load a one-to-many relationship with BMP, we need to perform two SQL statements: We need to
ejbLoad( ) the “1” side of the relationship and then find( ) the “N” side of the relationship. This is an
inherent downside to BMP; you are limited to performing SQL operations at the granularity of an entity
bean. With CMP, if your container is good, you can optimize and tell the container to perform one gigantic
SQL statement to load yourself and your relationships.

© 2006, Watsh Rajneesh. All Rights Reserved.


81/86 2/9/2008

The following code shows how to implement a many-to-many relationship as two one-to-many
relationships using BMP:
public class StudentBean implements EntityBean {
private String studentPK;
private String studentName;
...
public void ejbLoad() { // SQL SELECT Student }
public void ejbStore() { // SQL UPDATE Student }
}
public class CourseBean implements EntityBean {
private String coursePK;
private String courseName;
...
public void ejbLoad() { // SQL SELECT Course }
public void ejbStore() { // SQL UPDATE Course }
}
public class EnrollmentBean implements EntityBean {
private String enrollmentPK;
private Student student; // EJB local object stub
private Course course; // EJB local object stub
public Course getCourse() { return course; }
public void setCourse(Course c) { this.course = c;}
public Student getStudent() { return student; }
public void setStudent(Student s) { this.student = s; }
...
public void ejbLoad() {
// 1: SQL SELECT Enrollment. This loads both the
// Enrollment plus the foreign keys to Student
// and Course.
//
// 2: JNDI lookup of StudentHome, CourseHome
//
// 3: Call findByPrimaryKey() on both the Student
// and Course homes, passing the foreign keys
}
public void ejbStore() {
// 1: Call getPrimaryKey() on Student,Course. This
// gives us our foreign keys.
//
// 2: SQL UPDATE Enrollment
}
}

A brand-new entity bean, called enrollment, models the relationship between student and course. The
enrollment bean keeps a stub for a course and a stub for a student and has get/set methods for clients to

© 2006, Watsh Rajneesh. All Rights Reserved.


82/86 2/9/2008

access those stubs. At the point in which object/relational mapping occurs, we transform those stubs to and
from their foreign key database representation.

The following code shows how to implement a fake many-to-many relationship using CMP:
public abstract class StudentBean implements EntityBean {
// no fields
...
public void ejbLoad() { } // Empty
public void ejbStore() { } // Empty
}

public abstract class CourseBean implements EntityBean {


// no fields
...
public void ejbLoad() { } // Empty
public void ejbStore() { } // Empty
}

public abstract class EnrollmentBean implements EntityBean {


// no fields
public abstract Course getCourse();
public abstract void setCourse(Course c);
public abstract Student getStudent();
public abstract void setStudent(Student s);
...
public void ejbLoad() { } // Empty
public void ejbStore() { } // Empty
}

<ejb-jar xmlns=”http://java.sun.com/xml/ns/j2ee” version=”2.1”


xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd”>
<enterprise-beans>
...
</enterprise-beans>
<relationships>
<ejb-relation>
<ejb-relation-name>Enrollment-Student</ejb-relation-name>
<ejb-relationship-role>
<ejb-relationship-role-name>
Enrollments-AreRegisteredBy-Student
</ejb-relationship-role-name>
<multiplicity>Many</multiplicity>
<relationship-role-source>
<ejb-name>Enrollment</ejb-name>
</relationship-role-source>
<cmr-field><cmr-field-name>student</cmr-field-name></cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>
Student-Has-Enrollments
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source>
<ejb-name>Student</ejb-name>
</relationship-role-source>
</ejb-relationship-role>
</ejb-relation>
<ejb-relation>
<ejb-relation-name>Enrollment-Course</ejb-relation-name>
<ejb-relationship-role>
<ejb-relationship-role-name>
Enrollments-AreRegistrationsFor-Course
</ejb-relationship-role-name>
<multiplicity>Many</multiplicity>
<relationship-role-source>
<ejb-name>Enrollment</ejb-name>

© 2006, Watsh Rajneesh. All Rights Reserved.


83/86 2/9/2008

</relationship-role-source>
<cmr-field><cmr-field-name>course</cmr-field-name></cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>
Course-Has-Enrollments
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source>
<ejb-name>Course</ejb-name>
</relationship-role-source>
</ejb-relationship-role>
</ejb-relation>
</relationships>
</ejb-jar>
We model our fake many-to-many relationship as two many-to-one relationships (one for each bean in the
relationship).

Directionality
The directionality of a relationship specifies the direction in which you can navigate a relationship. It can
be Bi-directional or Uni-directional.
In a bidirectional relationship, each bean in the relationship has a field pointing to the other bean, along
with a get/set method.
Birdirectional BMP:
public class OrderBean implements EntityBean {
private String orderPK;
private String orderName;
// EJB local object stub, must be stored/loaded
private Shipment shipment;
public Shipment getShipment() { return shipment; }
public void setShipment(Shipment s) { this.shipment = s; }
...
}
public class ShipmentBean implements EntityBean {
private String shipmentPK;
private String shipmentName;
// EJB local object stub, must be stored/loaded
private Order order;
public Order getOrder() { return order; }
public void setOrder(Order o) { this.order = o; }
...
}

Unidirectional BMP:
public class OrderBean implements EntityBean {
private String orderPK;
private String orderName;
// EJB local object stub, must be stored/loaded
private Shipment shipment;
public Shipment getShipment() { return shipment; }
public void setShipment(Shipment s) { this.shipment = s; }
...
}
public class ShipmentBean implements EntityBean {
private String shipmentPK;
private String shipmentName;
// No Order stub, no Order get/set method
...
}

Birdirectional CMP:
public abstract class OrderBean implements EntityBean {
// no fields
public abstract Shipment getShipment();
public abstract void setShipment(Shipment s);

© 2006, Watsh Rajneesh. All Rights Reserved.


84/86 2/9/2008

...
public void ejbLoad() { } // Empty
public void ejbStore() { } // Empty
}

public abstract class ShipmentBean implements EntityBean {


// no fields
public abstract Order getOrder();
public abstract void setOrder(Order o);
...
public void ejbLoad() { } // Empty
public void ejbStore() { } // Empty
}
Each bean in the relationship has a pair of abstract get/set methods pointing to the other bean. We need to
tell the container that these get/set methods are special relationship methods so that the container can
generate relationship code.

<ejb-jar xmlns=”http://java.sun.com/xml/ns/j2ee” version=”2.1”


xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd”>
<enterprise-beans>
...
</enterprise-beans>
<relationships>
<ejb-relation>
<ejb-relation-name>Order-Shipment</ejb-relation-name>
<ejb-relationship-role>
<ejb-relationship-role-name>
order-spawns-shipment
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source>
<ejb-name>Order</ejb-name>
</relationship-role-source>
<cmr-field><cmr-field-name>shipment</cmr-field-
name></cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>
shipment-fulfills-order
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source>
<ejb-name>Shipment</ejb-name>
</relationship-role-source>
<cmr-field><cmr-field-name>order</cmr-field-name></cmr-
field>
</ejb-relationship-role>
</ejb-relation>
</relationships>
</ejb-jar>
In the deployment descriptor, we set up two container-managed relationship (CMR) fields: one for each
bean’s abstract get/set method pair that points to the other bean.

Aggregation vs Composition and Cascading Deletes


An aggregation relationship is a uses relationship. For example, students use courses. If you delete a
student, you don’t delete the courses the student is registered in, because other students are using that
course. Similarly, if you delete a course, you don’t murder a student!

A composition relationship is an is-assembled-of relationship. For example, orders are assembled of line
items. Deleting an order deletes all line items. Line items shouldn’t be around if their parent order is gone.

© 2006, Watsh Rajneesh. All Rights Reserved.


85/86 2/9/2008

An aggregation relationship does not cause a cascading delete, whereas a composition relationship
does. With BMP, you implement a cascading delete manually in your ejbRemove() method.
public class OrderBean implements EntityBean {
private String orderPK;
private String orderName;
private Shipment shipment; // EJB local object stub

public Shipment getShipment() { return shipment; }


public void setShipment(Shipment s) { this.shipment = s;}
...
public void ejbRemove() {
// 1: SQL DELETE Order
// 2: shipment.remove();
}
}
With CMP, the container generates cascading delete code for you. If you have a composition relationship,
you just need to set up a <cascade-delete/> tag in the deployment descriptor, as follows:

<ejb-jar xmlns=”http://java.sun.com/xml/ns/j2ee” version=”2.1”


xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xsi:schemaLocation=”http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd”>
<enterprise-beans>
...
</enterprise-beans>
<relationships>
<ejb-relation>
<ejb-relation-name>Order-Shipment</ejb-relation-name>
<ejb-relationship-role>
<ejb-relationship-role-name>
order-spawns-shipment
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<relationship-role-source>
<ejb-name>Order</ejb-name>
</relationship-role-source>
<cmr-field><cmr-field-name>shipment</cmr-field-name></cmr-
field>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>
shipment-fulfills-order
</ejb-relationship-role-name>
<multiplicity>One</multiplicity>
<cascade-delete/>
<relationship-role-source>
<ejb-name>Shipment</ejb-name>
</relationship-role-source>
<cmr-field><cmr-field-name>order</cmr-field-name></cmr-field>
</ejb-relationship-role>
</ejb-relation>
</relationships>
</ejb-jar>

EJB Integration (JCA)

EJB Performance Tuning


[thu]

© 2006, Watsh Rajneesh. All Rights Reserved.


86/86 2/9/2008

Clustering

Sample Application
[fri]
http://java.sun.com/blueprints/code/projectconventions.html for how to arrange your project build
environment.
http://java.sun.com/blueprints/code/namingconventions.html for the naming conventions to follow for J2EE
applications.

© 2006, Watsh Rajneesh. All Rights Reserved.

You might also like