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);
…
}
…
…
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:
Alleviates the disconnect between Java code and XML configuration
– Defaults are used whenever possible
•
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
….
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
return bids;
}
protected void setBids(Set
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.add(bid);
item.setBids(bids);
Packaging a Persistence Unit
An example of persistence.xml fle :
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
public void remove(Object entity); // from managed to removed
public Object find(String entityName,
Object primaryKey); // find by primary key
public
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