You are on page 1of 52

Professional Open Source™

Introduction to EJB3
Preview to New Enterprise JavaBean Technology

© JBoss, Inc. 2003-2005. 8/2/2005 1

Topics
Professional Open Source™

– Goals of EJB3
– New Enterprise Bean Contract
– Interceptors
– Persistence API

© JBoss, Inc. 2003-2005. 2

1
Goals of EJB3
Professional Open Source™

Simplify the EJB component development


– Reduce the amount of ”boiler-plate” code
• Remote, Local, Home interfaces
– Take advantage of the new Java annotation features
• Formalize code generation that was formerly done with tools
– Reduce the amount of deployment descriptors
– Overhaul of the persistence model
• Enable light-weight domain object models
• Support inheritance and polymorphism
• Address O/R Mapping configuration
• Enhance EJB-QL, dynamic queries, support for native SQL
– Simplify environmental dependencies with Dependency Injection
– Increase reusability of EJB components by moving closer to JavaBean or
Plain Old Java Object (POJO) models

How
How does
does this
this show
show up
up in
in practice?
practice?

© JBoss, Inc. 2003-2005. 3

Overview of Simplified EJB3 API


Professional Open Source™

– No home interfaces
• Removal of EJBHome and EJBLocalHome interfaces
– Session remote interface can be
• Defined by Plain Old Java Interface (POJI)
• Removal of EJBObject and EJBLocalObject interfaces
– No mandated interfaces for bean class
• Removal of SessionBean, EntityBean interfaces
– Backward compatibility
• EJBHome, EJBLocalHome, EJBObject, EJBLocalObject supported
for 2.x clients
• All metadata can be specified through deployment descriptors (ejb-
jar.xml and jboss.xml)

Let’s
Let’s see
see aa comparison
comparison example.
example.

© JBoss, Inc. 2003-2005. 4

2
Removal of Home Interfaces
Professional Open Source™

Home interfaces not required


– Applies to both Session and Entity beans
– Message Driven Beans never had home interfaces in the first place

What about home.create() calls?


– For stateless session this was a no-op, no state to initialize
– For stateful session, the bean is uninitialized from client’s point of view
• Use the business interface methods to initialize the session to a
proper state

What about home.remove() and home.find() calls?


– For stateless session this was no-op, container ignored it
– For stateful, any method signature can be annotated to mark the end of
the session’s life cycle (more on this later)
– For entities, remove and find calls are managed via persistence context
(EntityManager and Query interfaces – more on these later)

© JBoss, Inc. 2003-2005. 5

Stateless Session Bean Example: Home Interfaces


Professional Open Source™

EJB 2.x:
import
importjava.rmi.*;
java.rmi.*;
import
importjavax.ejb.*;
javax.ejb.*;

public
publicinterface
interfaceAccountManagerHome
AccountManagerHomeextends
extendsEJBHome
EJBHome{{
public
public AccountManager create() throws RemoteException,CreateException;
AccountManager create() throws RemoteException, CreateException;
}}
This call to home interface was
always redundant – the instance is
created by the container and
returned from the pool.

EJB 3.x:
////NOT
NOTREQUIRED!!
REQUIRED!!

© JBoss, Inc. 2003-2005. 6

3
Enterprise Bean Business Interfaces
Professional Open Source™

Can be a plain old Java interface (POJI)


– No need to extend EJBObject or EJBLocalObject interfaces
– If your bean declares a single, non-annotated interface, it is assumed to
be the business interface and @Local
– Use the @Remote/@Local annotations to explicity define your local and
remote business interfaces.
• Multiple remote and/or local interfaces allowed
• Annotated interface or Annotate Bean class

Let’s compare to EJB 2.x stateless


session bean.

© JBoss, Inc. 2003-2005. 7

Stateless Session Bean Example: Business Interface


Professional Open Source™

EJB 2.x:
public interface AccountManager extends EJBObject {
public void createAccount(AccountNumber number) throws RemoteException;
public void removeAccount(AccountNumber number) throws RemoteException;
public void updateAccount(AccountNumber number, AccountData data)
throws RemoteException;
}

EJB 3:
Regular, reusable Java interface
@Remote public interface AccountManager {
public void createAccount(AccountNumber number);
public void removeAccount(AccountNumber number);
public void updateAccount(AccountNumber number, AccountData data);
}

@Stateless Alternatively on bean class


@Remote(AccountManager.class)
public class AccountManagerBean implements AccountManager {
...
}
© JBoss, Inc. 2003-2005. 8

4
Enterprise Bean Implementation
Professional Open Source™

No EnterpriseBean interface implementation


– SessionBean and EntityBean interfaces removed
– EJB callback method implementations are recognized via annotations
• @PostConstruct, @PreDestroy (SLSB, SFSB & MDB)
• @PostActivate, @PrePassivate (SFSB)
• @PreRemove, @PostRemove (Entity)
• @PrePersist, @PostPersist (Entity)
• @PreUpdate, @PostUpdate (Entity)
• @PostLoad (Entity)
– Bean implementation is a regular, reusable Java object.

© JBoss, Inc. 2003-2005. 9

Stateless Session Bean Example: Bean Implementation


Professional Open Source™

EJB 2.x: Bean implementation did not implement


business interface – external validators or
import
importjavax.ejb.*;
javax.ejb.*; implementation patterns required.
public
publicclass
classAccountManagerBean
AccountManagerBeanimplements
implementsSessionBean
SessionBean {{
public
publicvoidvoidcreateAccount(AccountNumber
createAccount(AccountNumbernumber
number)) {{
////implementation
implementation… …
}}

public
publicvoid
voidremoveAccount(AccountNumber
removeAccount(AccountNumbernumber)
number){{
////implementation
implementation......
}}

public
publicvoid
voidupdateAccount(AccountNumber
updateAccount(AccountNumbernumber,
number,AccountData
AccountDatadata)
data){{
////implementation
implementation......
}}

public
publicvoid
voidsetSessionContext(
setSessionContext(SessionContext
SessionContextsc
sc)){{}}
public
publicvoid
voidejbCreate()
ejbCreate(){{}}
public
publicvoid
voidejbRemove()
ejbRemove(){{}}
public
publicvoid
voidejbActivate()
ejbActivate(){{}} Callback methods always
public
publicvoid
voidejbPassivate()
ejbPassivate(){{}} present.
}}

© JBoss, Inc. 2003-2005. 10

5
Stateless Session Bean Example: Bean Implementation 2
Professional Open Source™

EJB 3:
@Stateless
@Stateless
public
publicclass
classAccountManagerBean
AccountManagerBeanimplements
implementsAccountManager
AccountManager {{
public
publicvoidvoidcreateAccount(AccountNumber
createAccount(AccountNumbernumber
number)) {{
////implementation
implementation… …
}}

public
publicvoid
voidremoveAccount(AccountNumber
removeAccount(AccountNumbernumber)
number){{
////implementation
implementation......
}}

public
publicvoid
voidupdateAccount(AccountNumber
updateAccount(AccountNumbernumber,
number,AccountData
AccountDatadata)
data){{
////implementation
implementation......
}}
}}

Reusable Java class that implements a


regular Java interface. Interface
implementation is validated by the compiler.

© JBoss, Inc. 2003-2005. 11

EJB3 Deployment
Professional Open Source™

lookup JNDI
– Package the classes to a jar with Bind proxy
.ejb3 extension
invoke
– Drop to JBoss deploy directory
Client

SLSB Pool
@Stateless
public class AccountManagerBean implements AccountManager {
public void createAccount(AccountNumber number ) { … }
/deploy
public void removeAccount(AccountNumber number) { ... }
public void updateAccount(AccountNumber number, AccountData data) { ... }
}
@Remote public interface AccountManager {
public void createAccount(AccountNumber number); Regular Java class
public void removeAccount(AccountNumber number); annotated with @Stateless
public void updateAccount(AccountNumber number, AccountData data); deploys a stateless session
} bean. It’s that easy!

What happened to deployment descriptors?!

© JBoss, Inc. 2003-2005. 12

6
EJB3 Deployment Descriptors
Professional Open Source™

EJB3 takes a different approach to configuration


– Metadata annotations are used heavily
• Especially useful for mostly static configuration:
<session-type>  @Stateless, <remote>  @RemoteInterface
Alleviates the disconnect between Java code and XML configuration

<ejb-jar>
<display-name>Crime Portal Application</display-name> – Defaults are used
<enterprise-beans> whenever possible
<session>
• <transaction-type> 
<display-name>Money Laundering Bean</display-name>
<ejb-name>Laundry</ejb-name>
Container, etc.
<home>crimeportal.interfaces.LaundryHome</home>
<remote>crimeportal.interfaces.Laundry</remote>
<ejb-class>crimeportal.implementation.LaundryBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor/>
</ejb-jar>

© JBoss, Inc. 2003-2005. 13

EJB 3.0 Deployment Descriptor


Professional Open Source™

Believe it or not, people like XML deployment descriptors


Externalize configuration
Externalize system architecture

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)

© JBoss, Inc. 2003-2005. 14

7
Stateful Beans
Professional Open Source™

Still homeless
– Created as they are looked up
@Remove replaces EJBObject.remove
– Stateful bean is removed after method called

@Remote
@Remotepublic
publicinterface
interfaceShoppingCart
ShoppingCart { {
public
public void addItem(intprodId,
void addItem(int prodId,int
intquantity);
quantity);
public
publicvoid
voidcheckout();
checkout();
}}

@Stateful
@Statefulpublic
publicclass
classShoppingCartBean
ShoppingCartBeanimplements
implementsShoppingCart
ShoppingCart{ {

@Remove
@Remove End of method will
public
publicvoid
voidcheckout()
checkout() { { remove the session.
……
}}
}}

© JBoss, Inc. 2003-2005. 15

MDBs
Professional Open Source™

Just implements MessageListener


XML turns to annotations

@MessageDriven(
@MessageDriven(
activationConfig={
activationConfig={
ActivationConfigProperty(name=“destination”,
ActivationConfigProperty(name=“destination”,value=“queue/email”)
value=“queue/email”)
}}
))
public
publicclass
classEmailBean
EmailBeanimplements
implementsMessageListener
MessageListener{ {

void
voidonMessage(Message
onMessage(Messagemsg) msg){ {} }
public int add(int x, int y) {
public int add(int x, int y) {
return
returnxx++y;y;
}}

}}

© JBoss, Inc. 2003-2005. 16

8
EJB3 Client View
Professional Open Source™

Client view is largely similar


– With the reduced step of no home lookup
– We defaulted to global proxy lookup name based on remote interface
name

public
publicclass
classClient
Client{{
public
publicstatic
staticvoid
voidmain(String[]
main(String[]args)
args)throws
throwsException
Exception{{
Context
Contextnaming
naming==new
newInitialContext();
InitialContext();
JNDI
Global
AccountManager
AccountManagermgr
mgr==
AccountManager
(AccountManager)naming.lookup("AccountManager");
(AccountManager)naming.lookup("AccountManager");
mgr.createAccount(new
mgr.createAccount(newAccountNumber());
AccountNumber());
}}
}}

AccountMgr.ejb3
AccountManager.class
AccountManagerBean.class

© JBoss, Inc. 2003-2005. 17

Conclusion
Professional Open Source™

Simplified component contract


– No more home interfaces / proxies
Any Java interface can become remote / local interface
– No dependencies to RMI, EJB packages
Any POJO can become an EJB
– No dependencies to container
– Can be tested outside the container
Deployment simplified
– Reasonable defaults for configuration
– Annotations for mostly static configuration
– ”Sparse” descriptors (ejb-jar.xml and jboss.xml)

© JBoss, Inc. 2003-2005. 18

9
Professional Open Source™

EJB Transactions

© JBoss, Inc. 2003-2005. 8/2/2005 19

Transactions with Annotations


Professional Open Source™

– Non-annotated methods default to REQUIRED


– Method level annotation overrides bean-level annotations

Default for entire class.


@Stateful(name
@Stateful(name==“MyCart")
“MyCart")
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public
publicclass
classShoppingCart
ShoppingCartimplements
implementsCart
Cart{{

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public
publicvoid
voidaddItem(String
addItem(Stringitem)
item){{…
…}}

@Remove
@Removepublic
publicvoid
voidclose()
close(){{…
…}}
}}

© JBoss, Inc. 2003-2005. 20

10
Application Exceptions
Professional Open Source™

– Checked exceptions can be annotated to cause automatic rollback


– RuntimeExceptions can be annotated to be unwrapped

@ApplicationException(rollback=true)
@ApplicationException(rollback=true)
public
publicclass
classAccountBillingError
AccountBillingErrorextends
extendsException
Exception{}{}

@ApplicationException(rollback=false)
@ApplicationException(rollback=false)
public
publicclass
classAppError
AppErrorextends
extendsRuntimeException
RuntimeException{}{}

© JBoss, Inc. 2003-2005. 21

Professional Open Source™

EJB Security Annotations

© JBoss, Inc. 2003-2005. 8/2/2005 22

11
Security Annotations
Professional Open Source™

Security and Method Permissions


– @RolesAllowed, @PermitAll, @DenyAll, @RunAs, @SecurityRoles
– @SecurityDomain jboss specifc
– Maybe security information better suited for XML DD?

@Stateful
@Stateful
@RunAs(“Special
@RunAs(“SpecialRole”)
Role”)
@org.jboss.annotation.SecurityDomain(“LdapDomain”)
@org.jboss.annotation.SecurityDomain(“LdapDomain”)
public
publicclass
classShoppingCartBean
ShoppingCartBeanimplements
implementsShoppingCart
ShoppingCart{{

@RolesAllowed({“valid_customer”})
@RolesAllowed({“valid_customer”})
public
publicvoid
voidcheckout()
checkout() {{


}}
}}

© JBoss, Inc. 2003-2005. 23

Professional Open Source™

EJB Dependency Injection

© JBoss, Inc. 2003-2005. 8/2/2005 24

12
EJB 3.0: Dependency Injection
Professional Open Source™

Bean class specifies dependencies instead of lookup


EJB Container initializes annotated fields or calls setter methods

@Stateful
@Statefulpublic
publicclass
classShoppingCartBean
ShoppingCartBeanimplements
implementsShoppingCart
ShoppingCart{ {

@Resource
@Resourceprivate
privateSessionContext
SessionContextctx;
ctx;

@EJB(name=“CreditProcessorEJB”)
@EJB(name=“CreditProcessorEJB”)
private
privateCreditCardProcessor
CreditCardProcessorprocessor;
processor;

private
privateDataSource
DataSourcejdbc;
jdbc;

@Resource(name=“java:/DefaultDS”)
@Resource(name=“java:/DefaultDS”)
public
publicvoid
voidsetDataSource(DataSource
setDataSource(DataSourcedb)
db){ {this.jdbc
this.jdbc==db;
db;} }

}}

© JBoss, Inc. 2003-2005. 25

EJB 3.0: Dependency Injection


Professional Open Source™

XML injection also supported


<injection-target> specified field or method to inject into

<ejb-ref>
<ejb-ref>
<ejb-ref-name>ejb/Bank</ejb-ref-name>
<ejb-ref-name>ejb/Bank</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<ejb-ref-type>Session</ejb-ref-type>
<remote>org.jboss.ejb3.test.bank.Bank</remote>
<remote>org.jboss.ejb3.test.bank.Bank</remote>
<ejb-link>Bank</ejb-link>
<ejb-link>Bank</ejb-link>
<injection-target>bank</injection-target>
<injection-target>bank</injection-target>
</ejb-ref>
</ejb-ref>

© JBoss, Inc. 2003-2005. 26

13
Professional Open Source™

EJB Component Lifecycle

© JBoss, Inc. 2003-2005. 8/2/2005 27

Callbacks and Callback Listener Classes


Professional Open Source™

Reacting to Enterprise JavaBean lifecycle events:


– There’s no enforced contract from EnterpriseBean interface
• No ejbActivate/Passivate, ejbCreate/Remove, ejbLoad/Store methods
– Any method can be designated as a callback method with specific
annotations

@Stateful
@Statefulpublic
publicclass
classCartBean
CartBeanimplements
implementsShoppingCart
ShoppingCart{{
public int someShoppingMethod() {...};
public int someShoppingMethod() {...};
......
@PreDestroy
@PreDestroycleanup()
cleanup(){...};
{...};
}}

Method ”cleanup” is invoked by the Stateful


Session Bean container before the instance is
removed from memory.

– Callback methods may throw runtime exceptions but not checked


exceptions. A runtime exception will rollback the ongoing transaction.

© JBoss, Inc. 2003-2005. 28

14
Callbacks for Session Beans
Professional Open Source™

Callbacks for stateless session beans:


– @PostConstruct
• Occurs after dependency injections and before any bean business
method is called
– @PreDestroy
• Occurs at the time the bean instance is destroyed

Additional callbacks for stateful session beans:


– @PostActivate and @PrePassivate
• Occurs at passivation/activation time

© JBoss, Inc. 2003-2005. 29

Callbacks for Session Beans


Professional Open Source™

@Stateful
@Statefulpublic
publicclass
classCartBean
CartBeanimplements
implementsShoppingCart
ShoppingCart{{
......

@PostConstruct
@PostConstruct@PostActivate
@PostActivate
public
publicvoid voidinitRemoteConnectionToAccountSystem()
initRemoteConnectionToAccountSystem(){{
////initialize
initializeconnection
connectionafter
afterconstruction
constructionor
oractivation
activation
}}

@PreDestroy
@PreDestroy@PrePassivate
@PrePassivate Same method can have
public
publicvoidvoidcloseRemoteConnectionToAccountSystem()
closeRemoteConnectionToAccountSystem(){{ multiple annotations.
////close
closeconnection
connectionbefore
beforedestruction
destructionor
orpassivation
passivation
}}
}}

© JBoss, Inc. 2003-2005. 30

15
EJB LifeCycle Listeners
Professional Open Source™

Reusable listeners for EJBs:


– @CallbackListener annotation
– Implementation is any Java class with EJB lifecycle annotations

@Stateful
@Stateful(name
(name==“CustomerCart”)
“CustomerCart”)
@CallbackListener(SessionListener.class)
@CallbackListener(SessionListener.class)

public
publicclass
classCartBean
CartBeanimplements
implementsShoppingCart
ShoppingCart{{
public void addItem(...) { ...
public void addItem(...) { ... }}
public
publicvoid
voidremoveItem(...)
removeItem(...) {{......}}
public
public void checkout(){{......}}
void checkout()
}}

© JBoss, Inc. 2003-2005. 31

EJB LifeCycle Listeners


Professional Open Source™

– Can be reused for several bean implementations


– Notice the different method signature
• Reference to the bean is passed as first argument

public
publicclass
classSessionListener
SessionListener{{
@PostConstruct
@PostConstruct
public
publicvoid
voidcreate(Object
create(Objectbean)
bean){{
System.out.println(“Session
System.out.println(“Sessioncreated:
created:""++bean.toString());
bean.toString());
}} Declare the argument either as
Java ”Object” type or specific
@PreDestroy
@PreDestroy bean type.
public
publicvoid
voiddelete(CartBean
delete(CartBeanbean)
bean){{
System.out.println(“Session
System.out.println(“Sessiondestroyed:
destroyed:""++bean.toString());
bean.toString());
}}
}}

© JBoss, Inc. 2003-2005. 32

16
Conclusions
Professional Open Source™

Component life-cycle can be marked with annotations


– Any method can participate in bean life-cycle
– Listeners can be reused across bean implementations

© JBoss, Inc. 2003-2005. 33

Professional Open Source™

EJB3 Interceptors
Customize the invocation flow

© JBoss, Inc. 2003-2005. 8/2/2005 34

17
Interceptors in EJB3
Professional Open Source™

EJB3 specification formalizes interceptors


– Same concept as in JBoss since 2.x releases
– Allows you to intercept the incoming business method in the container
– Customize the EJB3 container logic
• Audit
• Custom Security
• Etc.
– Annotate with @Interceptor, @Interceptors and @AroundInvoke tags

– Interceptors are stateless and their life cycle and concurrency is not
specified by the spec
• With multiple interceptors, invocation state can be shared with
InvocationContext object

© JBoss, Inc. 2003-2005. 35

Interceptors in EJB3
Professional Open Source™

Define a stack of interceptors


@Stateless for this bean. The order is
@Stateless
relevant here.
@Interceptors({"TransactionAudit“,
@Interceptors({"TransactionAudit“,"CustomSecurity"})
"CustomSecurity"})

public
publicclass
classBankManager
BankManagerimplements
implementsBankTransaction
BankTransaction{{
@Resource public SessionContext sc;
@Resource public SessionContext sc;
public
publicvoid
voidtrade(int
trade(intamount)
amount){{
System.out.println("Traded: An interceptor specific to bean
System.out.println("Traded:""++amount
amount++""CHF");
CHF");
implementation can be included. It will
}}
be invoked after other interceptors
@AroundInvoke configured for the bean.
@AroundInvoke
public
publicObject
ObjectsendNotification(InvocationContext
sendNotification(InvocationContextctx)
ctx)throws
throwsException
Exception{{
////access
accessinternal
internalstate
stateof
ofthe
theinstance...
instance...
}}
}}

© JBoss, Inc. 2003-2005. 36

18
InvocationContext
Professional Open Source™

– Interceptor implementation has an access to an associated


InvocationContext instance

public
publicinterface
interfaceInvocationContext
InvocationContext{{
public
publicObject
ObjectgetBean();
getBean(); ////reference
referenceto
tothe
thebean
beaninstance
instance
public
publicMethod
MethodgetMethod();
getMethod(); ////method
methodtotobe
becalled
called
public
publicObject[]
Object[]getParameters();
getParameters(); ////args
argsto
tothe
themethod
method
public
publicvoid
voidsetParameters(Object[]);
setParameters(Object[]); ////access
access to mutatethe
to mutate theargs
args
public
public ContextgetEJBContext();
Context getEJBContext(); ////EJBContext
EJBContext
public Map getContextData();
public Map getContextData(); ////shared
shareddata
databetween
betweeninterceptors
interceptors
public Object proceed() throws Exception;
public Object proceed() throws Exception;
}}

Must always be called at the end of the


interceptor implementation in order for
the invocation to proceed.

© JBoss, Inc. 2003-2005. 37

Interceptors in EJB3
Professional Open Source™

– Interceptor implementation is a regular Java object with a specific


@AroundInvoke annotation
public
publicclass
classTransactionAudit
TransactionAudit{{
@AroundInvoke
@AroundInvoke
public
publicObject
ObjectauditTrade(InvocationContext
auditTrade(InvocationContextctx)
ctx)throws
throwsException
Exception{{
ifif(ctx.getMethod().getName().equals("trade"))
(ctx.getMethod().getName().equals("trade")){{
Object[]
Object[]args
args==ctx.getParameters();
ctx.getParameters();
EJBContext
EJBContextejbContext
ejbContext==ctx.getEJBContext();
ctx.getEJBContext();
Integer
IntegertradeValue
tradeValue==(Integer)args[0];
(Integer)args[0];
String
Stringcaller
caller==ejbContext.getCallerPrincipal().getName();
ejbContext.getCallerPrincipal().getName();

sendMessage(caller
sendMessage(caller++""executes
executestrade
tradeof
ofvalue:
value:""++tradeValue);
tradeValue);
}}
Interceptors can invoke JNDI, JDBC,
return
returnctx.proceed();
ctx.proceed(); JMS, EJBs. Transaction context and
}} security context are the one of the
}} executing bean business method.

© JBoss, Inc. 2003-2005. 38

19
Professional Open Source™

Persistence API
New POJO Persistence for J2EE and J2SE

© JBoss, Inc. 2003-2005. 8/2/2005 39

Goals
Professional Open Source™

Goals for Persistence API:


– Addresses O/R Mapping at specification level
• Previous Entity specification did not address the underlying relational
model
– Targets both J2EE and J2SE platforms
• POJO based programming model with persistence
• Hibernate
– Lifecycle changes
• Detach / Merge
– Query Enhancements
• EJB-QL bulk update/delete, JOIN, GROUP-BY, HAVING
• Dynamic Queries
• Allow native SQL queries
– Polymorphic
• Inheritance supported with polymorphic relationships and queries

© JBoss, Inc. 2003-2005. 40

20
Professional Open Source™

Defining Entity Beans

Full Object/Relational Database Mapping

© JBoss, Inc. 2003-2005. 8/2/2005 41

EJB 3.0 Entity Beans


Professional Open Source™

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, @Embedded
– Inheritance, @Inheritance, @DiscriminatorColumn
– Identifier + Version properties, @Id, @Version

© JBoss, Inc. 2003-2005. 42

21
Entity Annotations
Professional Open Source™

@Entity
@Entity
@Table(name=“AUCTION_ITEM”) relational table declaration
@Table(name=“AUCTION_ITEM”)
public
publicclass
classItem
Item{{
private
private longid;
long id;
private
privateString
Stringdescription;
description;
private
privateString
StringproductName;
productName;
private
privateSet<Bid>
Set<Bid>bids
bids==new
newHashSet();
HashSet();
private User seller;
private User seller;

@Id(generate=GeneratorType.AUTO) auto-key generation


@Id(generate=GeneratorType.AUTO)
@Column(name=“ITEM_ID”)
@Column(name=“ITEM_ID”)
public
publiclong
longgetId()
getId(){{
return
returnid;
id;
}}
public
publicvoid
voidsetId(long
setId(longid)
id){{
this.id
this.id==id;
id;
}}

© JBoss, Inc. 2003-2005. 43

Entity Annotations
Professional Open Source™

@Entity
@Entity create
createtable
tableAUCTION_ITEM
AUCTION_ITEM
@Table(name=“AUCTION_ITEM”)
@Table(name=“AUCTION_ITEM”) ((
public
publicclass
classItem
Item{{ ITEM_ID
ITEM_IDNumber,
Number,
private
privatelong
longid;
id; DESC
DESCvarchar(255),
varchar(255),
private
privateString
Stringdescription;
description; ProductName
ProductNamevarchar(255),
varchar(255),
private
privateString
StringproductName;
productName; USER_ID
USER_IDNumber
Number
private
privateSet<Bid>
Set<Bid>bids
bids==new
new ););
HashSet();
HashSet();
private
privateUser
Userseller;
seller;

@Id(generate=GeneratorType.AUTO)
@Id(generate=GeneratorType.AUTO)
@Column(name=“ITEM_ID”)
@Column(name=“ITEM_ID”)
public
publiclong
longgetId()
getId(){{
return
returnid;
id;
}}
public
publicvoid
voidsetId(long
setId(longid)
id){{
this.id = id;
this.id = id;
}}

© JBoss, Inc. 2003-2005. 44

22
Entity Annotations
Professional Open Source™

@Entity
@Entity create
createtable
tableAUCTION_ITEM
AUCTION_ITEM
@Table(name=“AUCTION_ITEM”)
@Table(name=“AUCTION_ITEM”) ((
public
publicclass
classItem
Item{{ ITEM_ID
ITEM_IDNumber,
Number,
private
private longid;
long id; DESC
DESCvarchar(500),
varchar(500),
private
privateString
Stringdescription;
description; ProductName
ProductNamevarchar(255),
varchar(255),
private
privateString
StringproductName;
productName; OWNER_ID
OWNER_IDNumber
Number
private
privateSet<Bid>
Set<Bid>bids
bids==new
new ););
HashSet();
HashSet();
private
privateOwner
Ownerowner;
owner;

@Id(generate=GeneratorType.AUTO)
@Id(generate=GeneratorType.AUTO)
@Column(name=“ITEM_ID”)
@Column(name=“ITEM_ID”)
public
publiclong
longgetId()
getId(){{
return id;
return id;
}}
public
publicvoid
voidsetId(long
setId(longid)
id){{
this.id = id;
this.id = id;
}}

© JBoss, Inc. 2003-2005. 45

Entity Annotations
Professional Open Source™

……

@Column(name=“DESC”,
@Column(name=“DESC”,length=500)
length=500) column mapping
public
publicString
StringgetDescription()
getDescription(){{
return
returndescription;
description;
}}
public
publicvoid
voidsetDescription(String
setDescription(Stringdesc)
desc){{
this.description
this.description==desc;
desc;
}}

public
publicString
StringgetProductName()
getProductName(){{ intuitive defaults
return productName;
return productName;
}}
protected
protectedvoid
voidsetProductName(String
setProductName(Stringname)
name){{
this.productName = name;
this.productName = name;
}}

© JBoss, Inc. 2003-2005. 46

23
Entity Annotations
Professional Open Source™

…… create
createtable
tableAUCTION_ITEM
AUCTION_ITEM
((
@Column(name=“DESC”,
@Column(name=“DESC”,length=500)
length=500) ITEM_ID
ITEM_IDNumber,
Number,
public
publicString
StringgetDescription()
getDescription(){{ DESC
DESCvarchar(500),
varchar(500),
return
returndescription;
description; ProductName
ProductNamevarchar(255),
varchar(255),
}} OWNER_ID
OWNER_IDNumber
Number
public
publicvoid
voidsetDescription(String
setDescription(Stringdesc)
desc){{ ););
this.description
this.description==desc;
desc;
}}

public
publicString
StringgetProductName()
getProductName(){{
return
returnproductName;
productName;
}}
protected
protectedvoid
voidsetProductName(String
setProductName(Stringname)
name){{
this.productName
this.productName ==name;
name;
}}

© JBoss, Inc. 2003-2005. 47

Relationships
Professional Open Source™

No longer container managed


– Developer keeps track of references
– No different from normal Java reference semantics

Same feature set:


– One-to-one, one-to-many, many-to-one, many-to-many
– Unidirectional and bidirectional
– Corresponding annotations:
• @OneToOne, @OneToMany, @ManyToOne, @ManyToMany
Fetch Strategy
– Should the relationship be lazy or eagerly loaded?

Relationships are polymorphic as well


– Collection of ”Customer” entity types may contain Customers and all its
subtypes, e.g. ValuedCustomer, VIPCustomer, etc.

© JBoss, Inc. 2003-2005. 48

24
Relationships
Professional Open Source™

@Entity
@Entitypublic
publicclass
classAccount
Accountimplements
implementsSerializable
Serializable{{
……
private
privateCollection<Customer>
Collection<Customer>customers
customers==new
newHashSet<Customer>(3);
HashSet<Customer>(3);

@Id
@Id(generate
(generate==GeneratorType.AUTO)
GeneratorType.AUTO)
public
publiclong
longgetId()
getId(){{return
returnid;
id;}}
public
publicvoid
voidsetId(long
setId(longid)
id){{…
…}}

public
publicAccountNumber
AccountNumbergetAccountNumber()
getAccountNumber(){{ Customer will maintain the FK
...... update.
@OneToMany
@OneToMany(mappedBy (mappedBy==“account”)
“account”) Physical mapping will be stored
public
publicCollection<Customer>
Collection<Customer>getCustomers()
getCustomers(){{ in Customer.account
return
returncustomers;
customers;
}}
public
publicvoid voidsetCustomers(Collection<Customer>
setCustomers(Collection<Customer>c)c){{
this.customers
this.customers==c;c;
}}

© JBoss, Inc. 2003-2005. 49

Relationships
Professional Open Source™

Default mappings
– Bidirectional relationship, with a foreign key on the ”owning” side

@Entity
@Entitypublic
publicclass
classCustomer
Customerimplements
implementsSerializable
Serializable{{
private
privateint
intid;
id;
private
privateString
Stringname;
name;
private
privateAccount
Accountaccount;
account;
......

@ManyToOne
@ManyToOne
public
publicAccount
AccountgetAccount()
getAccount(){{
return
returnaccount;
account;
}}

public
publicvoid
voidsetAccount(Account
setAccount(Accountacct)
acct){{ PK AcctNro PK Name FK
this.account
this.account==acct;
acct; 1 hj323hf 1 Ulla 1
}}
}} 2 23hrfhjk 2 Maija 1
3 234hjt3 3 Mia 3
4 4

© JBoss, Inc. 2003-2005. 50

25
Default Fetch Strategy
Professional Open Source™

@Entity
@Entitypublic
publicclass
classAccount
Accountimplements
implementsSerializable
Serializable{{
……
private
privateCollection<Customer>
Collection<Customer>customers
customers==new
newHashSet<Customer>(3);
HashSet<Customer>(3);

@Id
@Id(generate
(generate==GeneratorType.AUTO)
GeneratorType.AUTO)
public
publiclong
longgetId()
getId(){{return
returnid;
id;}} Lazily load this relationship
public
publicvoid
voidsetId(long
setId(longid)
id){{…
…}}

public
publicAccountNumber
AccountNumbergetAccountNumber()
getAccountNumber(){{
......
@OneToMany
@OneToMany(mappedBy (mappedBy==“account”,
“account”,fetch=LAZY)
fetch=LAZY)
public
publicCollection<Customer>
Collection<Customer>getCustomers()
getCustomers(){{
return
returncustomers;
customers;
}}
public
publicvoid voidsetCustomers(Collection<Customer>
setCustomers(Collection<Customer>c)c){{
this.customers
this.customers==c;c;
}}

© JBoss, Inc. 2003-2005. 51

No CMR
Professional Open Source™

– You must wire up the relationships. Remember, these are POJOs!


– If correct cascade policy set on Customers property
• new customers will be created (CascadeType.PERSIST)
• modified customers will be updated (CascadeType.REMOVE)
– removed customers are orphaned. You must remove manually
@Entity
@Entitypublic
publicclass
classAccount
Accountimplements
implementsSerializable
Serializable{{
......
@OneToMany
@OneToMany(mappedBy
(mappedBy==“account”,
“account”,fetch=LAZY,
fetch=LAZY,cascade={ALL})
cascade={ALL})
public
publicCollection<Customer>
Collection<Customer>getCustomers()
getCustomers(){{
return
returncustomers;
customers;
}}
public
publicvoid
voidsetCustomers(Collection<Customer>
setCustomers(Collection<Customer>c)c){{
this.customers
this.customers==c;c;
}}

public
publicvoid
voidaddCustomer(Customer
addCustomer(Customercust)
cust){{
this.customers.add(cust);
this.customers.add(cust);
cust.setAccount(this);
cust.setAccount(this);
}}

© JBoss, Inc. 2003-2005. 52

26
Multi-Table
Professional Open Source™

Multi-Table Mappings,
– Entity can be stored in one or more tables
– @SecondaryTables, @SecondaryTable

© JBoss, Inc. 2003-2005. 53

Multi-table Mappings
Professional Open Source™

@Entity
@Entity create
createtable
tableCustomer
Customer
@SecondaryTables({
@SecondaryTables({ ((
@SecondaryTable(name=“ADDRESS”
@SecondaryTable(name=“ADDRESS” IDIDNumber,
Number,
join={@JoinColumn(name=“ADDR_ID”)})
join={@JoinColumn(name=“ADDR_ID”)}) NAME
NAMEvarchar(255),
varchar(255),
public
publicclass
classCustomer
Customer{{ ););
private
private longid;
long id;
private
privateString
Stringname;
name; create
createtable
tableADDRESS
ADDRESS
private
privateString
Stringstreet;
street; ((
private
privateString
Stringcity;
city; ADDR_ID
ADDR_IDNumber,
Number,
private
privateString
Stringstate;
state; STREET
STREETvarchar(255),
varchar(255),
CITY
CITYvarchar(255),
varchar(255),
@Id(generate=GeneratorType.AUTO)
@Id(generate=GeneratorType.AUTO) STATE
STATEvarchar(255)
varchar(255)
public
publiclong
longgetId()
getId(){{ );z
);z
return
returnid;
id;
}}
public
publicvoid
voidsetId(long
setId(longid)
id){{
this.id = id;
this.id = id;
}}

© JBoss, Inc. 2003-2005. 54

27
Multi-Table Mappings
Professional Open Source™

@Column(name=“STREET”,
@Column(name=“STREET”, create
createtable
tableCustomer
Customer
secondaryTable=“ADDRESS”)
secondaryTable=“ADDRESS”) ((
public
publicString
StringgetStreet()
getStreet(){{ OWNER_ID
OWNER_IDNumber,
Number,
return street;
return street; NAME
NAMEvarchar(255),
varchar(255),
}} ););
public
publicvoid
voidsetStreet(String
setStreet(Stringstreet)
street){{
this.street = street;
this.street = street; create
createtable
tableADDRESS
ADDRESS
}} ((
ADDR_ID
ADDR_IDNumber,
Number,
STREET
STREETvarchar(255),
varchar(255),
@Column(name=“CITY”,
@Column(name=“CITY”, CITY
CITYvarchar(255),
varchar(255),
secondaryTable=“ADDRESS”)
secondaryTable=“ADDRESS”) STATE
STATEvarchar(255)
varchar(255)
public
publicString
StringgetCity()
getCity(){{ ););
return city;
return city;
}}
protected
protectedvoid
voidsetCity(String
setCity(Stringcity)
city){{
this.city = city;
this.city = city;
}}

© JBoss, Inc. 2003-2005. 55

Embedded Objects
Professional Open Source™

Embedded Objects
– Aggregated objects whose properties can be mapped
@Embeddable
@Embeddable
public
publicclass
classAddress
Address{ {
private
private Stringstreet;
String street;
private
privateString
Stringcity;
city;
private
privateString
Stringstate;
state;

@Column(“STREET”)
@Column(“STREET”)
public
publicString
StringgetStreet()
getStreet(){ {
return
returnstreet;
street;
}}

public
publicvoid
voidsetStreet(String
setStreet(Stringstreet)
street){ {
this.street
this.street==street;
street;
}}

public
publicString
StringgetCity()
getCity(){ {
return
returncity;
city;
}}

© JBoss, Inc. 2003-2005. 56

28
Embedded
Professional Open Source™

@Entity
@Entity
public
publicclass
classCustomer
Customer{ {
private
privateAddress
Addressaddress;
address;
……

@Embedded
@Embedded
@AttributeOverrides({
@AttributeOverrides({
@AttributeOverride(name=“street”,
@AttributeOverride(name=“street”,@Column(name=“STREET”)),
@Column(name=“STREET”)),
@AttributeOverride(name=“city”,
@AttributeOverride(name=“city”,@Column(name=“CITY”)),
@Column(name=“CITY”)),
@AttributeOverride(name=“state”,
@AttributeOverride(name=“state”,@Column(name=“STATE”))
@Column(name=“STATE”))
})})
public
publicAddress
AddressgetAddress()
getAddress(){ {
return
returnaddress;
address;
}}
public
publicvoid
voidsetAddress(Address
setAddress(Addressaddress)
address){ {
this.address
this.address==address;
address;
}}

……

© JBoss, Inc. 2003-2005. 57

Composite Keys/Primary Key Classes


Professional Open Source™

EJB 2.1 style primary keys


– Same idea as @Embedded
– @EmbeddedId, @Embeddable, @IdClass

© JBoss, Inc. 2003-2005. 58

29
Composite Keys
Professional Open Source™

@Entity
@Entity @Embeddable
@Embeddable
public
publicclass
classCustomer
Customer{{ public
publicclass
classCustomerPK
CustomerPK{{
private
private CustomerPKpk;
CustomerPK pk; private
private Stringname;
String name;
private
privatelong
longssn;
ssn;
@EmbeddedId
@EmbeddedId
public
publicCustomerPK
CustomerPKgetId()
getId(){{ @Column(“NAME”)
@Column(“NAME”)
return
returnid;
id; public
publicString
StringgetName()
getName(){{
}} return
returnstreet;
street;
public
publicvoid
voidsetId(OwnerPK
setId(OwnerPKid)id){{ }}
this.id
this.id==id;
id;
}} public
publiclong
longgetSSN()
getSSN(){{
return sn;
return sn;
}}
……

© JBoss, Inc. 2003-2005. 59

Entity Inheritance
Professional Open Source™

Entities are regular Java classes with inheritance hierarchy


– When persisted, inheritance (super/subclass variables) needs to be taken
into account
– Inheritance mapping strategies
• Single table per class hierarchy strategy (mandatory)
• Table per class strategy (optional)
• Joined subclass strategy (optional)
– Java objects are polymorphic
• Subclasses can be used wherever parent or ancestor type is allowed
– Polymorphic associations and queries also supported with entities

© JBoss, Inc. 2003-2005. 60

30
Entity Inheritance: Single Table per Class Hierarchy
Professional Open Source™

@Entity
@Entitypublic
publicclass
classCustomer
Customerimplements
implementsSerializable
Serializable{{
private
privatelong
longid;
id;
private
privateName
Namename;
name;
private
privateAddress
Addressaddress;
address;
......

@Entity
@Entitypublic
publicclass
classValuedCustomer
ValuedCustomerextends
extendsCustomer
Customer{{
private
privateAccountManager
AccountManagermanager;
manager;
private
privatePhoneNumber
PhoneNumberdirect;
direct;
PK Discr. FN LN Addr. Mgr.Name Phone
......
1 C ... ... ... null null
2 C ... ... ... null null
3 VC ... ... ... Jack 555-1231
4 VC ... ... ... Jill 555-1238

© JBoss, Inc. 2003-2005. 61

Entity Inheritance: Table Per Class


Professional Open Source™

@Entity
@Entity@Inheritance(strategy
@Inheritance(strategy==InheritanceType.TABLE_PER_CLASS)
InheritanceType.TABLE_PER_CLASS)
public
publicclass
classCustomer
Customerimplements
implementsSerializable
Serializable{{
private
privatelong
longid;
id;
private
privateName
Namename;
name;
private
privateAddress
Addressaddress;
address;
......

@Entity
@Entitypublic
publicclass
classValuedCustomer
ValuedCustomerextends
extendsCustomer
Customer{{
private
privateAccountManager
AccountManagermanager;
manager;
private
privatePhoneNumber
PhoneNumberdirect;
direct;
...... CUSTOMER VALUEDCUSTOMER
PK FN LN Addr. PK FN LN Addr. Mgr.Name Phone
1 ... ... ... X ... ... ... ... ...
2 ... ... ... Y ... ... ... ... ...
3 ... ... ... Z ... ... ... ... ...
4 ... ... ... Å ... ... ... ... ...

© JBoss, Inc. 2003-2005. 62

31
Entity Inheritance: Joined Subclass
Professional Open Source™

@Entity
@Entity@Inheritance(strategy
@Inheritance(strategy==InheritanceType.JOINED)
InheritanceType.JOINED)
public
publicclass
classCustomer
Customerimplements
implementsSerializable
Serializable{{
private long id;
private long id;
private
privateName
Namename;
name;
private
private Addressaddress;
Address address;
......

@Entity
@Entitypublic
publicclass
classValuedCustomer
ValuedCustomerextends
extendsCustomer
Customer{{
private
privateAccountManager
AccountManagermanager;
manager;
private
privatePhoneNumber
PhoneNumberdirect;
direct;
...... CUSTOMER VALUEDCUSTOMER
PK FN LN Addr. PK,FK Mgr.Name Phone
1 ... ... ... 1 ... ...
2 ... ... ... 2 ... ...
3 ... ... ... 3 ... ...
4 ... ... ... 4 ... ...

© JBoss, Inc. 2003-2005. 63

Professional Open Source™

Entity lifecycle and callbacks

Plain Java Objects

© JBoss, Inc. 2003-2005. 8/2/2005 64

32
Entity Listeners and Callback Methods
Professional Open Source™

@PrePersist and @PostPersist


– Executed before and after database insert, respectively
– Notice that @PostPersist is not necessarily directly after insert
• May be executed when flush() occurs or transaction ends

@PreUpdate and @PostUpdate


– Executed before and after the database update operations
• Again, @PostUpdate does not necessarily occur directly after EJB
field value changes but may occur at flush() time or at transaction end

@PostLoad
– After entity has been loaded from database to server memory
– Before the query result is returned or associations traversed

@PreRemove and @PostRemove


– Executed before and after database delete, respectively

© JBoss, Inc. 2003-2005. 65

Entity Callback Methods


Professional Open Source™

– Can be implemented on the bean class

public
publicclass
classAccount
Accountimplements
implementsSerializable
Serializable{{
@PrePersist
@PrePersistpublic
publicvoid
voidvalidateFields(){
validateFields(){
}}
@PostLoad
@PostLoadpublic
publicvoid
voidensureUpperCase()
ensureUpperCase() {{
}}
}}

© JBoss, Inc. 2003-2005. 66

33
Entity Listeners and Callback Methods
Professional Open Source™

– Callback methods can also be externalized in an EntityListener


• Reference to the bean is passed as first argument

@Entity
@Entity@EntityListener(AccountAudit.class)
@EntityListener(AccountAudit.class)
public
publicclass
classAccount
Accountimplements
implementsSerializable
Serializable{{
......

public
publicclass
classAccountAudit
AccountAudit{{
@PrePersist
@PrePersistpublic
publicvoid
voidvalidateFields(Object
validateFields(Objectbean)
bean){{
////check
checkfield
fieldvalues,
values,set
setclassifiers,
classifiers,other
otherbusiness
businessrules,
rules,etc.
etc.
}} Declare the argument either as
Java ”Object” type or specific
@PreUpdate
@PreUpdatepublic
publicvoid
voidaudit(Account
audit(Accountbean)
bean){{ bean type.
////set
setfield
fieldvalues
valuesfor
forcaller
callerprincipal,
principal,date
dateand
andtime
timestamp
stamp
}}
}}

© JBoss, Inc. 2003-2005. 67

Professional Open Source™

Interacting With Entity Bean

Plain Java Objects

© JBoss, Inc. 2003-2005. 8/2/2005 68

34
Entity Manager
Professional Open Source™

Entities created as any plain Java object


– Customer cust = new Customer();
Plain Java objects and homeless
Can be detached and reattached to container
– Can be serialized to remote client
– Remote client can perform updates on local copy
– Copy can be sent back to server and merged back in
Persisted by the EntityManager service
– All access through this service
– Creation, retrieval, removal, and merging
– Analogous to Hibernate Session

© JBoss, Inc. 2003-2005. 69

Create the objects


Professional Open Source™

Create the entities like you would any other object


Allocate entire object graph like any other Java code

Item
Itemitem
item==newnewItem();
Item();
item.setDescription(“O’reilly’s th
item.setDescription(“O’reilly’sEJB
EJB44thEdition”);
Edition”);
item.setProductName(“EJB
item.setProductName(“EJB2.1 2.1Book”);
Book”);
……
Owner
Ownerbillbill==new
newOwner();
Owner();
bill.setName(“Bill”);
bill.setName(“Bill”);
item.setOwner(bill);
item.setOwner(bill);
Bid
Bidbid
bid==new
newBid();
Bid();
……
HashSet<Bid>
HashSet<Bid>bids bids==new
newHashSet();
HashSet();
bids.add(bid);
bids.add(bid);
item.setBids(bids);
item.setBids(bids);

© JBoss, Inc. 2003-2005. 70

35
Entity Manager
Professional Open Source™

All entities persisted by the EntityManager service


– All access through this service
– Creation, retrieval, removal, and merging
– Analogous to Hibernate Session
Injected with dependency injection

© JBoss, Inc. 2003-2005. 71

EntityManager
Professional Open Source™

EntityManager API:
– Create and remove persistent entity instance
– Find entities by primary keys
– Execute queries for entities
public
publicinterface
interfaceEntityManager
EntityManager{{
public
publicvoid
voidpersist(Object
persist(Objectentity);
entity); ////from
fromnew
newto tomanaged
managed
public
public<T>
<T>TTmerge(T
merge(Tentity);
entity); ////from
fromdetached
detachedto tomanaged
managed
public
publicvoid
voidremove(Object
remove(Objectentity);
entity); ////from
frommanaged
managedto toremoved
removed
public
publicObject
Objectfind(String
find(StringentityName,
entityName,Object
ObjectprimaryKey);//
primaryKey);//find
findby
byprimary
primarykeykey
public
public<T>
<T>TTfind(Class
find(ClassentityClass,
entityClass,Object
ObjectprimaryKey);
primaryKey); //// --´´--
--´´--
public
publicvoid
voidflush();
flush(); ////sync
synctotodatabase
database
public Query createQuery(String ejbqlString);
public Query createQuery(String ejbqlString); //// createEJB-QL
create EJB-QLquery
query
public
publicQuery
QuerycreateNamedQuery(String
createNamedQuery(Stringname);name); ////named
namedqueries
queries
public
publicQuery
QuerycreateNativeQuery(String
createNativeQuery(StringsqlString);
sqlString); ////create
createSQL
SQLquery
query(not
(notportable)
portable)
public void refresh(Object entity);
public void refresh(Object entity); // sync from database
// sync from database
......
}}

© JBoss, Inc. 2003-2005. 72

36
EntityManager
Professional Open Source™

@Stateless
@Statelesspublic
publicclass
classItemDAOImpl
ItemDAOImplimplements
implementsItemDAORemote
ItemDAORemote{{

@PersistenceContext(unitName=“Auction”)
@PersistenceContext(unitName=“Auction”)
private
privateEntityManager
EntityManagerem;
em; Inject the EntityManager service

public
publiclong
longcreate(Item
create(Itemitem)
item){{
em.create(item);
em.create(item);
return
returnitem.getId();
item.getId();
}}

public
publicItem
ItemfindById(long
findById(longid)
id){{
return
returnem.find(Item.class,
em.find(Item.class,id);
id);
}}

public
publicvoid
voidmerge(Item
merge(Itemitem)
item){{
em.merge(item);
em.merge(item);
}}
}}

© JBoss, Inc. 2003-2005. 73

EntityManager
Professional Open Source™

@Stateless
@Statelesspublic
publicclass
classItemDAOImpl
ItemDAOImplimplements
implementsItemDAORemote
ItemDAORemote{{

@PersistenceContext(unitName=“Auction”)
@PersistenceContext(unitName=“Auction”)
private
privateEntityManager
EntityManagerem;
em;
• Item allocated
public remotely
publiclong
longcreate(Item
create(Itemitem)
item){{
em.persist(item); • If cascade CREATE,
em.persist(item); entire object graph
return
returnitem.getId();
item.getId(); inserted into storage
}}

public
publicItem
ItemfindById(long
findById(longid)
id){{
return
return em.find(Item.class,id);
em.find(Item.class, id);
}}

public
publicvoid
voidmerge(Item
merge(Itemitem)
item){{
em.merge(item);
em.merge(item);
}}
}}

© JBoss, Inc. 2003-2005. 74

37
EntityManager
Professional Open Source™

@Stateless
@Statelesspublic
publicclass
classItemDAOImpl
ItemDAOImplimplements
implementsItemDAORemote
ItemDAORemote{{

@PersistenceContext(unitName=“Auction”)
@PersistenceContext(unitName=“Auction”)
private
privateEntityManager
EntityManagerem;
em;

public
publiclong
longcreate(Item
create(Itemitem)
item){{
em.persist(item);
em.persist(item);
return
returnitem.getId();
item.getId();
}} • Item found with
primary key
public • Detached from
publicItem
ItemfindById(long
findById(longid)
id){{
return persistent storage at tx
return em.find(Item.class,id);
em.find(Item.class, id);
}} completion
• Can be serialized like
public any other object
publicvoid
voidmerge(Item
merge(Itemitem)
item){{
em.merge(item);
em.merge(item);
}}
}}

© JBoss, Inc. 2003-2005. 75

EntityManager
Professional Open Source™

@Stateless
@Statelesspublic
publicclass
classItemDAOImpl
ItemDAOImplimplements
implementsItemDAORemote
ItemDAORemote{{

@PersistenceContext(unitName=“Auction”)
@PersistenceContext(unitName=“Auction”)
private
privateEntityManager
EntityManagerem;
em;

public
publiclong
longcreate(Item
create(Itemitem)
item){{
em.persist(item);
em.persist(item);
return
returnitem.getId();
item.getId();
}}

public
publicItem
ItemfindById(long
findById(longid)
id){{
return
returnem.find(Item.class,
em.find(Item.class,id);
id); • Item can be updated remotely
}} and changes merged back to
persistent storage
public • merge() returns a managed
publicvoid
voidmerge(Item
merge(Itemitem)
item){{
em.merge(item); copy of Item
em.merge(item);
}}
}}

© JBoss, Inc. 2003-2005. 76

38
Query API
Professional Open Source™

Queries may be expressed as EJBQL strings


– Embedded in code
– Externalized to metadata (named queries)
Invoke via Query interface
– Named parameter binding
– Pagination control

Runtime query creation.


public
publicList
ListfindWithName(String
findWithName(Stringname)
name){{
return em.createQuery(
return em.createQuery(
"SELECT
"SELECTccFROMFROMCustomer
CustomerccWHERE
WHEREc.name
c.nameLIKE
LIKE:custName")
:custName")
.setParameter("custName",
.setParameter("custName",name)
name)
.setMaxResults(10)
.setMaxResults(10) Named parameters.
.getResultList();
.getResultList();
}} Pagination control.

© JBoss, Inc. 2003-2005. 77

Queries
Professional Open Source™

Query API
– Available via EntityManager interface
• createQuery(), createNamedQuery(), createNativeQuery()
/**
/**Interface
Interfaceused
usedto
tocontrol
controlquery
queryexecution.*/
execution.*/
public
publicinterface
interfaceQuery
Query{{
/**
/**Execute
Executethe
thequery
queryand
andreturn
returnthe
thequery
queryresults
resultsas
asaaList.
List.*/*/
public
publicList
ListgetResultList();
getResultList();
/**
/**Execute
Executeaaquery
querythat
thatreturns
returnsaasingle
singleresult.
result.
** @throws
@throwsNonUniqueResultException
NonUniqueResultExceptionififmore
morethan
thanone
oneresult
result*/*/
public
publicObject
ObjectgetSingleResult();
getSingleResult();
/**
/**Set
Setthe
themaximum
maximumnumber
numberofofresults
resultsto
toretrieve.
retrieve.*/*/
public
publicQuery
QuerysetMaxResults(int
setMaxResults(intmaxResult);
maxResult);
/**
/**Set
Setan
animplementation-specific
implementation-specifichint.
hint.*/*/
public
publicQuery
QuerysetHint(String
setHint(StringhintName,
hintName,Object
Objectvalue);
value);
/**
/**Bind
Bindan
anargument
argumentto
toaanamed
namedparameter.
parameter.*/*/
public
publicQuery
QuerysetParameter(String
setParameter(Stringname,
name,Object
Objectvalue);
value);
......

© JBoss, Inc. 2003-2005. 78

39
EJB QL 3.0
Professional Open Source™

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
– Eagerly fetch lazy relationships
Subselects
– from Item i join i.bids bid where bid.amount = (select max(b.amount) from
i.bids b)
Group By, Having, Joins

© JBoss, Inc. 2003-2005. 79

Professional Open Source™

Entity Bean Packaging

New .par archive

© JBoss, Inc. 2003-2005. 8/2/2005 80

40
Persistence Packaging
Professional Open Source™

Entities packaged in .par file


Has application level metadata in META-INF/persistence.xml
<entity-manager>
<entity-manager>
<name>CRM</name>
<name>CRM</name>
<jta-data-source>java:/DefaultDS</jta-data-source>
<jta-data-source>java:/DefaultDS</jta-data-source>
<jar-file>optional
<jar-file>optionaladditional
additionaljar
jarfiles
filesto
tolook
lookat</jar-file>
at</jar-file>
<class>optional
<class>optionalclass
classto
todeploy</class>
deploy</class>
<mapping-file>optional
<mapping-file>optionalresource
resourcename
nameof ofXML
XMLmapping
mappingfile</mapping-file>
file</mapping-file>
<properties>
<properties>
<property
<propertyname=“hibernate.dialect”
name=“hibernate.dialect”value=“MySQL”/>
value=“MySQL”/>
</properties>
</properties>
</entity-manager>
</entity-manager>

{{
@PersistenceContext(unitName=“CRM”)
@PersistenceContext(unitName=“CRM”)
private
privateEntityManager
EntityManagermanager;
manager;
}}

© JBoss, Inc. 2003-2005. 81

Professional Open Source™

JBoss Extensions to EJB 3

From EJBs to Enterprise POJOs

© JBoss, Inc. 2003-2005. 8/2/2005 82

41
Professional Open Source™

The Service Bean

© JBoss, Inc. 2003-2005. 8/2/2005 83

Service bean
Professional Open Source™

Singleton services
Multi-threaded and stateful
Lifecycle and dependency management
Next iteration of the JBoss MBean

© JBoss, Inc. 2003-2005. 84

42
Service bean
Professional Open Source™

Full EJB 3 library of annotations available


– @TransactionAttribute, @MethodPermissions, @Inject
@Remote and @Local interface publishing
New @Management interface
– JMX is now an aspect

© JBoss, Inc. 2003-2005. 85

Service interfaces
Professional Open Source™

@Remote, @Local
Just like EJB

@Remote
@Remote
Public
Publicinterface
interfaceCalculatorRemote
CalculatorRemote
{{
BigDecimal
BigDecimaladd(float
add(floatx,x,float
floaty);
y);
BigDecimal
BigDecimal divide(float x,float
divide(float x, floaty);
y);
}}

© JBoss, Inc. 2003-2005. 86

43
Service interfaces
Professional Open Source™

@Management
JMX interface, JMX aspect

@Management
@Management
public
publicinterface
interfaceCalculatorManagement
CalculatorManagement
{{
int
intgetPrecision();
getPrecision();
void
voidsetPrecision();
setPrecision();
}}

© JBoss, Inc. 2003-2005. 87

Service bean class


Professional Open Source™

@Service deploys a singleton


Multi-threaded and stateful

@Service
@Service
public
publicclass
classCalculatorService
CalculatorServiceimplements
implementsCalculatorRemote,
CalculatorRemote,CalculatorManagement
CalculatorManagement
{{
private
privateint
intprecision;
precision;

public
publicint
intgetPrecision()
getPrecision(){ {return
returnprecision;
precision;} }
void
void setPrecision(int p) { precision==p;p;} }
setPrecision(int p) { precision

BigDecimal
BigDecimaldivide(float
divide(floatx,x,float
floaty)y){…}
{…}
}}

© JBoss, Inc. 2003-2005. 88

44
Professional Open Source™

Message Driven POJOs


Typed MDBs

© JBoss, Inc. 2003-2005. 8/2/2005 89

Message Driven POJOs


Professional Open Source™

MDBs with a typed interface


MDBs that publish a well known interface
Simplify JMS
Invoke methods, don’t build messages
Cleaner, clearer code

© JBoss, Inc. 2003-2005. 90

45
Message Driven POJOs
Professional Open Source™

Define a @Consumer bean class


@Consumer implements 1-N @Producer interfaces
@Producer a means to send JMS messages
@Consumer a means to receive JMS messages

© JBoss, Inc. 2003-2005. 91

Using a Producer
Professional Open Source™

Producers implicitly extend ProducerObject interface

{{
EmailRemote
EmailRemotequeue
queue==(EmailRemote)ctx.lookup(EmailRemote.class.getName());
(EmailRemote)ctx.lookup(EmailRemote.class.getName());

ProducerManager
ProducerManagercon
con==((ProducerObject)queue).getProducerManager();
((ProducerObject)queue).getProducerManager();

con.connect();
con.connect();
queue.send(“spam”);
queue.send(“spam”);
queue.send(“bill@jboss.org”,
queue.send(“bill@jboss.org”,“tss@tss.com”,
“tss@tss.com”,“spam”,
“spam”,new
newHashMap());
HashMap());
con.close();
con.close();
}}

© JBoss, Inc. 2003-2005. 92

46
@Consumer
Professional Open Source™

@Consumer(activation={
@Consumer(activation={
ActivationConfigProperty(name=“destinationType”,
ActivationConfigProperty(name=“destinationType”,value=“javax.jms.queue”),
value=“javax.jms.queue”),
ActivationConfigProperty(name=“destination”,
ActivationConfigProperty(name=“destination”,value=“queue/foo”)
value=“queue/foo”)
})})
public
publicclass
classEmailerBean
EmailerBeanimplements
implementsEmailRemote,
EmailRemote,EmailXA
EmailXA{ {

public
publicvoid
voidsend(String
send(Stringmsg)
msg){ {
……
}}

public
publicvoid
voidsend(String
send(Stringto,
to,String
Stringfrom,
from,String
Stringmsg,
msg,Map
Mapprops)
props){ {
……
}}
}}

© JBoss, Inc. 2003-2005. 93

@Producer
Professional Open Source™

@Producer
@Producer
public
publicinterface
interfaceEmailRemote
EmailRemote{ {
public
publicvoid
voidsend(String
send(Stringmsg);
msg);
public
publicvoid
voidsend(String
send(Stringto,
to,String
Stringfrom,
from,String
Stringmsg,
msg,Map
Mapprops);
props);

}}

@Producer(connectionFactory=“java:/JmsXA”)
@Producer(connectionFactory=“java:/JmsXA”)
public
publicinterface
interfaceEmailXA
EmailXA{ {
public
publicvoid
voidsend(String
send(Stringmsg);
msg);
public
publicvoid
voidsend(String
send(Stringto,
to,String
Stringfrom,
from,String
Stringmsg,
msg,Map
Mapprops);
props);

}}

© JBoss, Inc. 2003-2005. 94

47
Message Driven POJOs
Professional Open Source™

Consumer registers all implements @Producer interfaces into JNDI


Clients look up these @Producers in JNDI
Clients invoke methods on the Producers
Methods turn into JMS messages and published to the queue/topic

© JBoss, Inc. 2003-2005. 95

@Producer
Professional Open Source™

Producers implicitly extend ProducerObject interface

public
publicinterface
interfaceProducerObject
ProducerObject{{
ProducerManager
ProducerManagergetProducerManager();
getProducerManager();
}}
public
publicinterface
interfaceProducerManager
ProducerManager{ {
void
void setUsername(Stringuser);
setUsername(String user);
void
voidsetPassword(String
setPassword(Stringpasswd);
passwd);
void connect()throws
voidconnect() throwsJMSException;
JMSException;
void close() throws JMSException;
void close() throws JMSException;
void commit()throws
voidcommit() throwsJMSException;
JMSException;
void throws
void rollback() throwsJMSException;
rollback() JMSException;
}}

© JBoss, Inc. 2003-2005. 96

48
Using a Producer
Professional Open Source™

Producers implicitly extend ProducerObject interface

{{
EmailRemote
EmailRemotequeue
queue==(EmailRemote)ctx.lookup(EmailRemote.class.getName());
(EmailRemote)ctx.lookup(EmailRemote.class.getName());

ProducerManager
ProducerManagercon
con==((ProducerObject)queue).getProducerManager();
((ProducerObject)queue).getProducerManager();

con.connect();
con.connect();
queue.send(“spam”);
queue.send(“spam”);
queue.send(“bill@jboss.org”,
queue.send(“bill@jboss.org”,“tss@tss.com”,
“tss@tss.com”,“spam”,
“spam”,new
newHashMap());
HashMap());
con.close();
con.close();
}}

© JBoss, Inc. 2003-2005. 97

Configuring Message Properties


Professional Open Source™

@Producer(transacted=true)
@Producer(transacted=true)
@MessageProperties(delivery=NON_PERSISTENT)
@MessageProperties(delivery=NON_PERSISTENT)
public
publicinterface
interfaceEmailRemote
EmailRemote{ {

@MessageProperties(delivery=PERSISTENT,
@MessageProperties(delivery=PERSISTENT,timeToLive=1000,
timeToLive=1000,priority=1)
priority=1)
public void send(String msg);
public void send(String msg);

public
publicvoid
voidsend(String
send(Stringto,
to,String
Stringfrom,
from,String
Stringmsg,
msg,Map
Mapmap);
map);

}}

© JBoss, Inc. 2003-2005. 98

49
Professional Open Source™

Asynchronous EJBs
Lightweight asynchronous communication

© JBoss, Inc. 2003-2005. 8/2/2005 99

Asynchronous EJBs
Professional Open Source™

Goals
– Provide a lightweight asynchronous API for all EJB types
– VM local and Remote capabilities
– Zero changes to existing interfaces/code
– Support obtaining method results asychronously
• Not just oneway.

© JBoss, Inc. 2003-2005. 100

50
Asynchronous EJBs
Professional Open Source™

Available for Stateless, Stateful, and Service


Each @Remote and @Local interface implements EJBProxy

public
publicinterface
interfaceEJBProxy
EJBProxy { {
FutureProvider
FutureProvidergetAsynchronousProxy();
getAsynchronousProxy();
}}
……

CalculatorRemote
CalculatorRemotecalc
calc==(CalculatorRemote)ctx.lookup(“calculator”);
(CalculatorRemote)ctx.lookup(“calculator”);
EJBProxy proxy = (EJBProxy)calc;
EJBProxy proxy = (EJBProxy)calc;
CalculatorRemote
CalculatorRemotecalcAsynch
calcAsynch==(CalculatorRemote)proxy.getAsynchronousProxy();
(CalculatorRemote)proxy.getAsynchronousProxy();

© JBoss, Inc. 2003-2005. 101

Asynchronous EJBs
Professional Open Source™

Asynchronous Proxy same exact interface


Invoking methods on proxy happen in background

CalculatorRemote
CalculatorRemotecalc
calc==(CalculatorRemote)ctx.lookup(“calculator”);
(CalculatorRemote)ctx.lookup(“calculator”);
EJBProxy proxy = (EJBProxy)calc;
EJBProxy proxy = (EJBProxy)calc;
CalculatorRemote
CalculatorRemotecalcAsynch
calcAsynch==(CalculatorRemote)proxy.getAsynchronousProxy();
(CalculatorRemote)proxy.getAsynchronousProxy();

calcAsynch.add(1,
calcAsynch.add(1,1);
1); ////invoked
invokedininbackground,
background,ininanother
anotherthread
thread

calcAsynch.divide(10,
calcAsynch.divide(10,2);
2);////invoked
invokedininbackground
background

© JBoss, Inc. 2003-2005. 102

51
Asynchronous EJBs
Professional Open Source™

Obtain response asynchronously


– FutureProvider and Future interfaces

FutureProvider
FutureProviderprovider
provider==(FutureProvider)calcAsynch;
(FutureProvider)calcAsynch;

calcAsynch.add(1,
calcAsynch.add(1,1);
1); ////invoked
invokedininbackground,
background,ininanother
anotherthread
thread
Future
Futureresult1
result1==provider.getFuture();
provider.getFuture();
calcAsynch.divide(10,
calcAsynch.divide(10,2);
2); ////invoked
invokedininbackground
background
Future
Futureresult2
result2==provider.getFuture();
provider.getFuture();

int
intval1
val1==result1.get();
result1.get(); ////block
blockuntil
untilfirst
firstmethod
methodcall
callreturns
returns
ifif(result2.isDone())
(result2.isDone()){ { ////poll
polltotosee
seeififdone
done
int
intval2
val2==result2.get();
result2.get();
}}

© JBoss, Inc. 2003-2005. 103

JBoss Inc.
Professional Open Source™

EJB 3.0 Available NOW!


– Download at www.jboss.org
– Tutorial with code examples

© JBoss, Inc. 2003-2005. 104

52