Saturday, January 10, 2009

An Introduction to EJB

An Introduction to EJB

Introduction

Motivation for EJB 3.0

Java 5.0 Annotations

Types of Beans

Container Services

Interceptors

Introduction

EJB 3.0 is the next revision of the Enterprise Java Beans specification. One of the most significant changes in EJB 3.0 is the introduction of a standard O/R mapping specification and the move to POJO based persistence.

One of the principal goals of EJB 3.0 is:“Simplification of object persistence by the definition of a light-weight object/relational mapping facility based on the direct use of Java classes rather than persistent components.”

JSR 220: Enterprise JavaBeansTM,Version 3.0

EJB 3.0 Simplified API

Sun Microsystems’s Definition for EJB

The Enterprise JavaBeans architecture is a component architecture for the java development and deployment of component based distributed business applications. Application written using EJB are scalable, transactional and multi-user secure. These applications may be written once and then can be deployed on any server platform that supports EJB Specifications.

Motivation

EJB 2.1 technology very powerful, but too complex

Too many classes, interfaces

Awkward environment lookups (JNDI APIs)

Boilerplate javax.ejb interface methods

Clumsy programming model

Deployment descriptors

Java 5.0 Annotations

annotations do not directly affect program semantics

can be inspected through source parsing or by using the additional reflection APIs

define custom annotations

annotate fields, methods, classes, etc.

used to define

– bean's business interface

– O/R mapping information (specific persistence)

– resource references

– deployment information

EJB 3.0 makes extensive use of annotations to replace XML

EJB 3.0 Goals

Make EJB easier to learn and use

• Fewer classes and interfaces

• No required container interfaces

• Dependency injection

• Simple lookups

• No required deployment descriptor

• Simplified persistence

• Standardized object/relational mapping

Improve developer productivity

EJB 3.0 Approach

Simplification of the EJB APIs

• Removal of need for EJBHomes and EJBObjects

• Removal of JNDI APIs from developer and client view

• Removal of need for deployment descriptors

Use advantages of Java language metadata

• Metadata designed so that the most common cases are easiest to express

• Defaults available for expected cases

More work is done by container, less by developer

Contracts now benefit developer rather than container

• Bean specifies what it needs through metadata

No longer written to unneeded container interfaces

• Container interpositions and provides requested services to bean

Simplification of EJB Bean Types

Business interfaces are plain Java interfaces

• No more required EJBObject/EJBLocalObject interfaces

Home interfaces are no longer needed

• No more required EJBHome/EJBLocalHome interfaces

• Only need business interface, not home

Annotations for (optional) callback methods

• No more required javax.ejb.EnterpriseBean

interfaces

Dependency injection, simple lookup method

• No more need to use JNDI APIs

Example // EJB 2.1

public class PayrollBean implements javax.ejb.SessionBean {

SessionContext ctx;

DataSource empDB;

public void setSessionContext(SessionContext ctx) {

this.ctx = ctx;

}

public void ejbCreate() {

Context initialContext = new InitialContext();

empDB = (DataSource) initialContext.lookup (

“java:comp/env/jdbc/empDB”);

}

public void ejbActivate() {}

public void ejbPassivate() {}

public void ejbRemove() {}

public void setBenefitsDeduction(int empId, double deduction) {

Connection conn = empDB.getConnection();

}…

}

public interface PayrollHome extends javax.ejb.EJBLocalHome {

public Payroll create() throws CreateException;

}

public interface Payroll extends javax.ejb.EJBLocalObject {

public void setBenefitsDeduction (int empId, double deduction);

}

PayrollBean

com.example.PayrollHome

com.example.Payroll

com.example.PayrollBean

Stateful

Container

jdbc/empDB

javax.sql.DataSource

Container

Same Example // EJB 3.0

@Stateful

public class PayrollBean implements Payroll {

@Resource DataSource empDB;

public void setBenefitsDeduction (int empId, double deduction) {

Connection conn = empDB.getConnection();

}

}

@Remote

public interface Payroll {

public void setBenefitsDeduction (int empId, double deduction);

}

EJB 3.0: XML Deployment Descriptor

EJB3 takes a different approach to configuration

– Metadata annotations are used heavily

• Especially useful for mostly static configuration:

@Stateless,

@RemoteInterface

Alleviates the disconnect between Java code and XML configuration

– Defaults are used whenever possible

Container, etc.

Partial deployment descriptors are support

– Override annotations with XML

– General rule

• Use annotations when design of code is affected by metadata(i.e. @TransactionAttribute)

• Use XML when something is configurable per deployment (i.e. @RolesAllowed)

Types of Beans

Session Beans

Entity Beans

Message Driven Beans

Session Bean

Represents TaskFlow.

Fills gap left by Entity Beans

Describe interaction between other Beans

Types of Session Bean

Stateless Session Bean

They don’t maintain any conversational state.

Stateful Session Bean

They maintain a conversational and act on behalf of clients.

Stateless Session Bean

Does not retain any client specific data.

Container has pool of instances of stateless session beans and client requests are delegated to any available beans.

Reused by different clients.

Typically implements a procedural service on top of a database or legacy application.

Ex: PayRoll that simple gets db information to the user whose identity is given.

Stateless Session Beans

EJB 2.1: Requirements

Home interface

Remote/Local interface

Bean class must implement javax.ejb.SessionBean

XML Deployment descriptor

EJB 2.1: Required Interfaces

Homes for stateless beans unnecessary

Remote interface must inherit from EJBObject

Remote methods must throw RemoteException

Dependency on RMI

public interface CalculatorHome extends javax.ejb.EJBHome {

public Calculator create() throws CreateException;

}

public interface Calculator extends EJBObject {

public int add(int x, int y) throws RemoteException;

public int subtract(int x, int y) throws RemoteException;

}

EJB 2.1: Bean class requirements

Must extend verbose javax.ejb.SessionBean

Unnecessary and verbose callback methods

public class CalculatorBean implements javax.ejb.Sessionbean {

private SessionContext ctx;

public void setSessionContext(SessionContext ctx) { this.ctx = ctx; }

public void ejbCreate() { }

public void ejbRemove() {}

public void ejbActivate() {}

public void ejbPassivate() {}

public int add(int x, int y) {

return x + y;

}

public int subtract(int x, int y) {

return x – y;

}

EJB 2.1: XML Deployment Descriptor

CalculatorBean

in.cdac.CalculatorHome

in.cdac.CalculatorBean

in.cdac.CalculatorRemote

Stateless

Container

….

EJB 3.0 interface & class

Homeless

Methods don’t throw RemoteException

No verbose interface implementations

@Remote public interface Calculator {

public int add(int x, int y);

public int subtract(int x, int y);

}

@Stateless Public class CalculatorBean implements Calculator {

public int add(int x, int y) {

return x + y;

}

public int subtract(int x, int y) {

Return x – y;

}

}

LifeCycle of stateless session bean

Stateful Session Beans

Maintains client-specific session information (called conversational state) across multiple method calls and transactions

Aware of client history

Each stateful session bean has a timeout value

The bean instance is destroyed and the remote reference is invalidated after the timeout period is elapsed.

Stateful Session Beans

Still homeless

Created as they are looked up

@Remove replaces EJBObject.remove

Stateful bean is removed after method called

@Remote public interface ShoppingCart {

public void addItem(int prodId, int quantity);

public void checkout();

}

@Stateful public class ShoppingCartBean implements ShoppingCart {

@Remove

public void checkout() {

}

}

EJB 3.0 Deployment Descriptor

Believe it or not, people like XML deployment descriptors

Externalize configuration

Externalize system architecture

Although not in draft, XML DDs are optional

Replace annotations with XML and you get pure POJOs

Simplified Client View

Session beans have plain Java business interface

• Looks like normal Java interface to client

• Access can be local or remote (as specified)

Home interface not needed in client view

Remoteness is handled transparently

• No checked RemoteExceptions (unless you want them)

• EJBExceptions (unchecked exceptions) are thrown instead

Example // EJB 2.1

Context initialContext = new InitialContext();

ShoppingCartHome myCartHome = (ShoppingCartHome)

initialContext.lookup(“java:comp/env/ejb/cart”);

ShoppingCart myCart = myCartHome.create();

// Use the bean

Collection widgets = myCart.startToShop(“widgets”);

// Don’t forget to handle javax.Naming.NameNotFoundException

// Don’t forget to handle javax.ejb.CreateException

// Don’t forget deployment descriptor (ejb-refs, etc.)

}

Example: EJB 3.0 Client View

@EJB ShoppingCart myCart;

Collection widgets = myCart.startToShop(“widgets”);

OR

Context ctx = new InitialContext();

Collection c = (Collection)ctx.lookup(Collection.class.getName() );

Where Did the Home Interface Go?

Stateless Session Beans

• Home interface not needed anyway

• EJB 2.1 Home.create() didn’t really create

• Container creates or reuses pooled bean instance when business method is invoked

• Can use new SLSB class with “legacy” Home (and no

extra code)

Stateful Session Beans

• Container creates bean instance when business

method is invoked

• Initialization is part of application semantics

Don’t need a separate interface and ejbCreate method

for it

• Can use new SFSB class with “legacy” Home

@Init annotation denotes bean method that plays role of

ejbCreate

Dynamic Lookup

Dynamic lookup is simplified as well

EJBContext.lookup method is used at runtime

JNDI APIs are removed from developer’s view

Annotations to specify environment

dependencies are expressed on bean class

• Same annotations as used for injection

Example

@Resource(name=“productDB”, type=javax.sql.DataSource)

@Stateful public class ShoppingCartBean

implements ShoppingCart {

@Resource SessionContext ctx;

public Collection startToShop(String productName) {

DataSource productDB =

(DataSource)ctx.lookup(“productDB”);

Connection conn = myDB.getConnection();

}…

}

Goals of Entity Beans

Same goals as session beans

Fewer interfaces, optional XML DDs, etc.

No required interfaces or subclassing

Plain Java based

Allow new()

Provide full Object/Relational mapping

Supports Inheritance

Expanded EJBQL

Fully featured

Parallel SQL

Polymorphic Queries

Defining Entity Beans

O/R Mapping Metadata as annotations

Table mappings, @Table, @SecondaryTable

Column mappings, @Column, @JoinColumn

Relationships, @ManyToOne, @OneToOne, @OneToMany, @ManyToMany

Multi-Table mappings, @SecondaryTable

Embedded objects, @Dependent

Inheritance, @Inheritance, @DiscriminatorColumn

Identifier + Version properties, @Id, @Version

Entity Annotations

@Entity

@Table(name=“AUCTION_ITEM”)

public class Item {

private long id;

private String description;

private String productName;

@Id(generate=GeneratorType.AUTO)

@Column(name=“ITEM_ID”)

public long getId() {

return id;

}

public void setId(long id) {

this.id = id;

}

Relationships

Relationships

@ManyToOne, @OneToOne, @OneToMany, @ManyToMany

Supports lazy and eager loading of relationships

Cascades: delete, create, and merge

No CMR: You must manage the relationships somewhat.

Entity Relationships

@OneToOne(fetch=LAZY)

@Column(name=“OWNER_ID”)

public Owner getOwner() {

return owner;

}

protected void setOwner(Owner owner) {

this.owner = owner;

}

@OneToMany(cascade=ALL)

@JoinColumn(name=“ITEM_ID”)

protected Set getBids() {

return bids;

}

protected void setBids(Set bids) {

this.bids = bids;

}

Multi-Table

Multi-Table Mappings,

Entity can be stored in one or more tables

@SecondaryTables, @SecondaryTable

Multi-table Mappings

Interacting With Entity Bean

Plain Java Objects

Entity Manager

EntityManager is the central service for all persistence actions.

Entities are plain java objects that are allocated just like any other

Java object. They do not become persistent until your code

explicitly interacts with the EntityManager to make them persistent.

The EntityManager manages the O/R mapping between a fixed

set of entity classes and an underlying data source. It provides API’s

for creating queries, finding objects, synchronizing objects, and

inserting objects into the database.

EntityManager also can provide caching and manage the interaction

between an entity and transactional services in a Java EE environent

such as JTA.

All entities persisted by the EntityManager service

All access through this service

Creation, retrieval, removal, and merging

Analogous to Hibernate Session

Entity manager manages persistence contexts .

The entity manager tracks all entity objects within a persistence

context for changes and updates made, and flushes these changes

to the database using the flush mode rules.

Once the object is detached from a persistence context, it can no

longer be managed by an entity manager, and any state changes

to this object instance will not be synchronized with the database.

Injected with dependency injection

@Stateless public class ItemImpl implements ItemRemote {

@PersistenceContext(unit name=“item”)

EntityManager entityManager;

public long create(Item item) {

em.create(item);

return item.getId();

}

public Item findById(long id) {

return (Item) em.find(Item.class, id);

}

public void merge(Item item) {

em.merge(item);

}

}

Persistence Context

A persistence context is a set of managed entity object instances.

There are two types of persistence contexts:

Transaction-scoped persistence context

Extended persistence context

Transaction-scoped persistence context :

Persistence context may live as long as a transaction and be closed

when a transaction completes. This is called a transaction-scoped

persistence context.

When the transaction completes, the transaction-scoped persistence

context will be destroyed and all managed entity object instances

will become detached.

Application server managed persistence contexts can be transction-

scoped. In other words, only Entity Manager instances injected

with the @PersistenceContext annotation or its XML equivalent may

be transaction-scoped.

@PersistenceContext(unit name=“titan”)

EntityManager entityManager;

@TransactionAttribute(REQUIRED)

public Customer someMethod() {

Customer cust = entityManager.find(Customer.class,1);

cust.setName(“new name”);

return cust;

}

Extended Persistence Context

Persistence contexts may also be configured to live longer than a

transaction. This is called an extended persistence context.

Entity object instances that are attached to an extended context

remain managed even after a transaction is complete.

This feature is extremely useful in situations where you want to

have a conversation with your database but not keep a long-

running transaction, as transactions hold valuable resources

like JDBC connections and database locks.

@PersistenceContext(unitName=“titan”, type=PersistenceContextType.Extended)

private EntityManager extendedManager;

….

Customer cust = null;

transaction.begin(); //start tranasaction 1

cust = extendedManager.find(Customer.class,1);

tranasction.commit(); // tranasaction 1 ends

transaction.begin(); // start transaction 2

cust.setName(“bill”);

extendedManager.flush();

tranasaction.commit(); // cust instance remains managed and changes

// are flushed

Create the objects

Create the entities like you would any other object

Allocate entire object graph like any other Java code

Item item = new Item();

item.setDescription(“O’reilly’s EJB 4th Edition”);

item.setProductName(“EJB 2.1 Book”);

Owner bill = new Owner();

bill.setName(“Bill”);

item.setOwner(bill);

Bid bid = new Bid();

HashSet bids = new HashSet();

bids.add(bid);

item.setBids(bids);

Packaging a Persistence Unit

An example of persistence.xml fle :

java:/OracleDS

update

The JAR file of the persistence unit may also optionally contain a mapping XML DD called orm.xml in the META-INF directory of the deployment. This file used to define the mapping between the classes container in the persistence

unit and the database to which they map.

EntityManagerFactory

In Java SE, entity managers are created using

javax.pesistence.EntityManagerFactory.

public interface EntityManagerFactory {

EntityManager createEntityManager();

EntityManager createEntityManager(java.util.Map map);

void close();

boolean isOpen();

}

The createEntityManager() methods return EntityManager instances that manage a distinct extended persistence context.

Interacting with an EntityManager

The EntityManager API has methods to insert and remove entities

from a database as well as merge, updates from detached enity

instances.

public interface EntityManager {

public void persist(Object entity); // from new to managed

public T merge(T entity); // from detached to managed

public void remove(Object entity); // from managed to removed

public Object find(String entityName,

Object primaryKey); // find by primary key

public T find(Class entityClass,

Object primaryKey); // --´´--

public void flush(); // sync to database

public Query createQuery(String ejbqlString); // create EJB-QL query

public Query createNamedQuery(String name); // named queries

public Query createNativeQuery(String sqlString); // create SQL query (not portable)

public void refresh(Object entity); // sync from database

...

}

Inheritance

This feature was completely absent in EJB 2.1

Persistence mapping supports inheritance

Single table per hierarchy – SINGLE_TABLE

Join table per subclass – JOINED

Distinct table per subclass – UNION

Queries on class hierarchy are polymorphic

Inheritance – SINGLE_TABLE

@Entity

@Table(name="Animal")

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(name="TYPE")

public class Animal {

@Id private int id;

@Column(name="AVG_WEIGHT")

private int averageWeight;

...

}

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

public class Dog extends Animal{

@Column(name="BREED")

private String breed;

...

}

Inheritance – JOINED

@Entity

@Inheritance(strategy=InheritanceType.JOINED)

@Table(name="Animal")

public class Animal{

@Id private int id;

@Column(name="AVG_WEIGHT")

private int averageWeight;

...

}

@Entity

@InheritanceJoinColumn(name="DOGY_ID")

@Table(name="Doggy")

public class Dog extends Animal{

@Column(name="BREED")

private String breed;

...

}

Inheritance – UNION

@Entity

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

@Table(name="Animal")

public class Animal{

@Id private int id;

@Column(name="AVG_WEIGHT")

private int averageWeight;

...

}

@Entity

@InheritanceJoinColumn(name="DOGY_ID")

@Table(name="Doggy")

public class Dog extends Animal{

@Column(name="BREED")

private String breed;

...

}

Query API

Java interface that is obtained at runtime from Entity Manager

Queries may be expressed as EJBQL strings

Embedded in code

Externalized to metadata (named queries)

Invoke via Query interface

Named parameter binding

Pagination control

@Session public class ItemImpl {

public List findByDescription(String description, int page) {

return em.createQuery(“from Item i where i.description like :d”)

.setParameter(“d”, description)

.setMaxResults(50)

.setFirstResult(page*50)

.listResults();

}

EJB QL 3.0

EJBQL 3.0 is very similar to HQL (Hibernate Query Language)

Aggregation, projection

select max(b.amount) from Bid b where b.item = :id

select new Name(c.first, c.last) from Customer c

Fetching

from Item i left join fetch i.bids

Subselects

from Item i join i.bids bid where bid.amount = (select max(b.amount) from i.bids b)

Group By, Having, Joins

Entity Life-cycle

Entity Callbacks & Listeners

PrePersist

PostPersist

PostLoad

PreUpdate

PostUpdate

PreRemove

PostRemove

Entity Listeners are classes that can generically intercept entity callback events. You can assign methods on an entity listeners class to intercept a particular life cycle event.

Message-driven Beans

A message driven bean is an enterprise bean that allows J2EE applications to process messages asynchronously.

It acts as a JMS listener, which is similar to an event listener except that it receives messages instead of events.

The messages can be sent by any J2EE component: an application client, another enterprise bean, or a web component, or a non-J2EE system using JMS.

Retain no data or conversational state.

Message-driven Beans

Message-driven beans were already the simplest component in EJB 2.1

Message-driven beans in EJB 3.0

• Bean class implements message listener interface or designates with @MessageListener

• No requirement to implement MessageDrivenBean,

etc.

JMS Messaging Models

Basics of JMS

ConnectionFactory & Topic

Connection & Session

Message Producer

Message Consumer

Message Type

JMS Programming Model

Example

Just implements MessageListener

XML turns to annotations

@MessageDriven( activationConfig={

@ActivationConfigProperty(

propertyName=“destinationType”, propertyValue=“javax.jms.queue”)})

public class EmailBean implements MessageListener {

void onMessage(Message msg) { }

public int add(int x, int y) {

return x + y;

}

}

Life Cycle

Timer Service

The Timer Service is a facility of the EJB Container system that provides a timed event API, which can be used to schedule timers for specific dates, periods and intervals.

To use Timer Service, your beans must implement the javax.ejb.TimedObject interface.

Or put @Timeout annotation on your desired method.

@Timeout

Public void maintainence(javax.ejb.Timer timer){

…..

}

Container Services: Transactions

What is a Transaction ?

Unit of Work.

Set of Activities.

Must be having ACID properties, viz. Atomic, Consistent, Isolated, Durable

In EJB 3.0 we have Declarative Transaction Management.

Transaction management

• Container-managed transaction (CMT) by default

• Bean-managed transaction (BMT) by annotation

Container-managed transactions

• REQUIRED transaction attribute by default

• Any transaction attribute by annotation

Specified at class level => applies to all business methods of the class

Specified at method level => applies to method

(overriding any class-level specification)

• Typical case (CMT + REQUIRED) is default

Example

@Stateless public class PayrollBean implements Payroll {

@TransactionAttribute(REQUIRED)

public void setBenefitsDeduction (int empId, double

deduction) {…}

public double getBenefitsDeduction(int empId) {…}

public double getSalary(int empId) {…}

@TransactionAttribute(REQUIREDNEW)

public void setSalary(int empId, double salary) {…}

}

Security configuration typically done at deployment

• Developer can provide guidance

Security attributes

• If not specified => set on deployment or

“unchecked”

• Method permissions by annotation

Specified at class level => applies to all business

method of class

Specified at method level => applies to method

(overriding any class-level specification)

@PermitAll, @RolesAllowed

Use caller principal by default

• Run-as principal by annotation

Example

// Security view

@Stateless public class PayrollBean implements Payroll {

public void setBenefitsDeduction (int empId, double

deduction) {…}

public double getBenefitsDeduction(int empId) {…}

public double getSalary(int empId) {…}

// salary setting is intended to be more restricted

@RolesAllowed(“HR_PayrollAdministrator”)

public void setSalary(int empId, double salary) {…}

}

Container calls bean upon lifecycle events

• @PostConstruct

• @PreDestroy

• @PrePassivate

• @PostActivate

Bean specifies events it needs to know about

• Removes boilerplate code, “magic methods”

ejbCreate, ejbRemove, etc

Callback methods can be specified on separate

interceptor class or on bean class

PostConstruct and PreDestroy annotations

adopted into JSR-250 (“Common Annotations”)

Example

@Stateful public class AccountManagementBean

implements AccountManagement {

Socket cs;

@PostConstruct

@PostActivate

private void initRemoteConnectionToAccountSystem () {

}

@PreDestroy

@PrePassivate

private void closeRemoteConnectionToAccountSystem () {

}

}

Interceptors

Powerful facility for more advanced developers.

Interception of invocations of business methods, message listener methods.

Invocation model: “around” methods

• Wrapped around business method invocations

• Interceptor has control over invocation of “next

method”

• Can manipulate arguments and results

• Context data can be carried across interceptor

invocation chain

• Can use deployment descriptor to override order or

to add interceptors

Default interceptors

• Specified in deployment descriptor

Lack of application-level metadata annotation facility

Apply to all business methods of components in ejb-jar

Class-level interceptors

• Apply to all business method of bean class

Method-level interceptors

• Apply to specific business method only

High degree of control available

• Can specify exactly which interceptors in hierarchy

get invoked for a given class or method

• Ability to exclude default interceptors and/or classlevel

interceptors

Example

@Interceptors({

in.cdac.AccountAudit.class,

in.cdac.Metrics.class,

in.cdac.CustomSecurity.class

})

@Stateless public class AccountManagementBean

implements AccountManagement {

public void createAccount (int accountId, Details details) {…}

public void deleteAccount (int accountId) {…}

public void activateAccount (int accountId) {…}

public void deactivateAccount (int accountId) {…}

}

Example

public class AccountAudit{

@AroundInvoke

public Object auditAccount (InvocationContext inv)

throws Exception{

try {

Object result = inv.proceed();

return result;

} catch (Exception ex) {

throw ex;

}

……

}

}

Summary

Major simplification of EJB for developers

• Bean is plain Java class with plain Java business interface

• Injection model for services and resources

• Removal of boilerplate code

• Elimination of need for deployment descriptors

EJB 3.0 components interoperate with existing

applications

Gives developer simple-to-use and powerful

capability

No comments:

Post a Comment