Professional Documents
Culture Documents
Introduction to EJB3
Preview to New Enterprise JavaBean Technology
Topics
Professional Open Source™
– Goals of EJB3
– New Enterprise Bean Contract
– Interceptors
– Persistence API
1
Goals of EJB3
Professional Open Source™
How
How does
does this
this show
show up
up in
in practice?
practice?
– 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.
2
Removal of 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!!
3
Enterprise Bean Business Interfaces
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);
}
4
Enterprise Bean Implementation
Professional Open Source™
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.
}}
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......
}}
}}
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!
6
EJB3 Deployment Descriptors
Professional Open Source™
<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>
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.
……
}}
}}
MDBs
Professional Open Source™
@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;
}}
}}
8
EJB3 Client View
Professional Open Source™
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
Conclusion
Professional Open Source™
9
Professional Open Source™
EJB Transactions
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public
publicvoid
voidaddItem(String
addItem(Stringitem)
item){{…
…}}
@Remove
@Removepublic
publicvoid
voidclose()
close(){{…
…}}
}}
10
Application Exceptions
Professional Open Source™
@ApplicationException(rollback=true)
@ApplicationException(rollback=true)
public
publicclass
classAccountBillingError
AccountBillingErrorextends
extendsException
Exception{}{}
@ApplicationException(rollback=false)
@ApplicationException(rollback=false)
public
publicclass
classAppError
AppErrorextends
extendsRuntimeException
RuntimeException{}{}
11
Security Annotations
Professional Open Source™
@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() {{
…
…
}}
}}
12
EJB 3.0: Dependency Injection
Professional Open Source™
@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;} }
}}
<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>
13
Professional Open Source™
@Stateful
@Statefulpublic
publicclass
classCartBean
CartBeanimplements
implementsShoppingCart
ShoppingCart{{
public int someShoppingMethod() {...};
public int someShoppingMethod() {...};
......
@PreDestroy
@PreDestroycleanup()
cleanup(){...};
{...};
}}
14
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
}}
}}
15
EJB LifeCycle Listeners
Professional Open Source™
@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()
}}
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());
}}
}}
16
Conclusions
Professional Open Source™
EJB3 Interceptors
Customize the invocation flow
17
Interceptors in EJB3
Professional Open Source™
– 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
Interceptors in EJB3
Professional Open Source™
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...
}}
}}
18
InvocationContext
Professional Open Source™
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;
}}
Interceptors in EJB3
Professional Open Source™
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.
19
Professional Open Source™
Persistence API
New POJO Persistence for J2EE and J2SE
Goals
Professional Open Source™
20
Professional Open Source™
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;
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;
}}
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;
}}
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;
}}
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;
}}
Relationships
Professional Open Source™
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;
}}
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
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;
}}
No CMR
Professional Open Source™
public
publicvoid
voidaddCustomer(Customer
addCustomer(Customercust)
cust){{
this.customers.add(cust);
this.customers.add(cust);
cust.setAccount(this);
cust.setAccount(this);
}}
26
Multi-Table
Professional Open Source™
Multi-Table Mappings,
– Entity can be stored in one or more tables
– @SecondaryTables, @SecondaryTable
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;
}}
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;
}}
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;
}}
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;
}}
……
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;
}}
……
Entity Inheritance
Professional Open Source™
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
@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 ... ... ... Å ... ... ... ... ...
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 ... ...
32
Entity Listeners and Callback Methods
Professional Open Source™
@PostLoad
– After entity has been loaded from database to server memory
– Before the query result is returned or associations traversed
public
publicclass
classAccount
Accountimplements
implementsSerializable
Serializable{{
@PrePersist
@PrePersistpublic
publicvoid
voidvalidateFields(){
validateFields(){
}}
@PostLoad
@PostLoadpublic
publicvoid
voidensureUpperCase()
ensureUpperCase() {{
}}
}}
33
Entity Listeners and Callback Methods
Professional Open Source™
@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
}}
}}
34
Entity Manager
Professional Open Source™
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);
35
Entity Manager
Professional Open Source™
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
......
}}
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);
}}
}}
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);
}}
}}
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);
}}
}}
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);
}}
}}
38
Query API
Professional Open Source™
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);
......
39
EJB QL 3.0
Professional Open Source™
40
Persistence Packaging
Professional Open Source™
{{
@PersistenceContext(unitName=“CRM”)
@PersistenceContext(unitName=“CRM”)
private
privateEntityManager
EntityManagermanager;
manager;
}}
41
Professional Open Source™
Service bean
Professional Open Source™
Singleton services
Multi-threaded and stateful
Lifecycle and dependency management
Next iteration of the JBoss MBean
42
Service bean
Professional Open Source™
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);
}}
43
Service interfaces
Professional Open Source™
@Management
JMX interface, JMX aspect
@Management
@Management
public
publicinterface
interfaceCalculatorManagement
CalculatorManagement
{{
int
intgetPrecision();
getPrecision();
void
voidsetPrecision();
setPrecision();
}}
@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){…}
{…}
}}
44
Professional Open Source™
45
Message Driven POJOs
Professional Open Source™
Using a Producer
Professional Open Source™
{{
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();
}}
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){ {
……
}}
}}
@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);
}}
47
Message Driven POJOs
Professional Open Source™
@Producer
Professional Open Source™
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;
}}
48
Using a Producer
Professional Open Source™
{{
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();
}}
@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);
}}
49
Professional Open Source™
Asynchronous EJBs
Lightweight asynchronous communication
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.
50
Asynchronous EJBs
Professional Open Source™
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();
Asynchronous EJBs
Professional Open Source™
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
51
Asynchronous EJBs
Professional Open Source™
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.
Professional Open Source™
52