introduction ejb3
TRANSCRIPT
1
Professional Open Source™
© JBoss, Inc. 2003-2005. 18/2/2005
Introduction to EJB3Preview to New Enterprise JavaBean Technology
© JBoss, Inc. 2003-2005. 2
Professional Open Source™
Topics
– Goals of EJB3– New Enterprise Bean Contract
– Interceptors
– Persistence API
2
© JBoss, Inc. 2003-2005. 3
Professional Open Source™
Goals of EJB3
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 does this show up in practice? How does this show up in practice?
© JBoss, Inc. 2003-2005. 4
Professional Open Source™
Overview of Simplified EJB3 API
– 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 see a comparison example. Let’s see a comparison example.
3
© JBoss, Inc. 2003-2005. 5
Professional Open Source™
Removal of Home Interfaces
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. 6
Professional Open Source™
Stateless Session Bean Example: Home Interfaces
EJB 2.x:
import java.rmi.*;
import javax.ejb.*;
public interface AccountManagerHome extends EJBHome {
public AccountManager create() throws RemoteException, CreateException;
}
import java.rmi.*;
import javax.ejb.*;
public interface AccountManagerHome extends EJBHome {
public AccountManager create() throws RemoteException, CreateException;
}
EJB 3.x:
// NOT REQUIRED!!// NOT REQUIRED!!
This call to home interface was always redundant – the instance is
created by the container and
returned from the pool.
4
© JBoss, Inc. 2003-2005. 7
Professional Open Source™
Enterprise Bean Business Interfaces
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. 8
Professional Open Source™
Stateless Session Bean Example: Business Interface
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:
@Stateless
@Remote(AccountManager.class)
public class AccountManagerBean implements AccountManager {
...
}
@Remote public interface AccountManager {
public void createAccount(AccountNumber number);
public void removeAccount(AccountNumber number);
public void updateAccount(AccountNumber number, AccountData data);
}
Regular, reusable Java interface
Alternatively on bean class
5
© JBoss, Inc. 2003-2005. 9
Professional Open Source™
Enterprise Bean Implementation
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. 10
Professional Open Source™
Stateless Session Bean Example: Bean Implementation
EJB 2.x:
import javax.ejb.*;
public class AccountManagerBean implements SessionBean {
public void createAccount(AccountNumber number ) {
// implementation …
}
public void removeAccount(AccountNumber number) {
// implementation ...
}
public void updateAccount(AccountNumber number, AccountData data) {
// implementation ...
}
public void setSessionContext( SessionContext sc ) { }
public void ejbCreate() { }
public void ejbRemove() { }
public void ejbActivate() { }
public void ejbPassivate() { }
}
import javax.ejb.*;
public class AccountManagerBean implements SessionBean {
public void createAccount(AccountNumber number ) {
// implementation …
}
public void removeAccount(AccountNumber number) {
// implementation ...
}
public void updateAccount(AccountNumber number, AccountData data) {
// implementation ...
}
public void setSessionContext( SessionContext sc ) { }
public void ejbCreate() { }
public void ejbRemove() { }
public void ejbActivate() { }
public void ejbPassivate() { }
}
Bean implementation did not implement business interface – external validators or
implementation patterns required.
Callback methods always present.
6
© JBoss, Inc. 2003-2005. 11
Professional Open Source™
Stateless Session Bean Example: Bean Implementation 2
EJB 3:
@Stateless
public class AccountManagerBean implements AccountManager {
public void createAccount(AccountNumber number ) {
// implementation …
}
public void removeAccount(AccountNumber number) {
// implementation ...
}
public void updateAccount(AccountNumber number, AccountData data) {
// implementation ...
}
}
@Stateless
public class AccountManagerBean implements AccountManager {
public void createAccount(AccountNumber number ) {
// implementation …
}
public void removeAccount(AccountNumber number) {
// implementation ...
}
public void updateAccount(AccountNumber number, AccountData data) {
// implementation ...
}
}
Reusable Java class that implements a regular Java interface. Interface
implementation is validated by the compiler.
© JBoss, Inc. 2003-2005. 12
Professional Open Source™
EJB3 Deployment
– Package the classes to a jar with .ejb3 extension
– Drop to JBoss deploy directory
@Stateless
public class AccountManagerBean implements AccountManager {
public void createAccount(AccountNumber number ) { … }
public void removeAccount(AccountNumber number) { ... }
public void updateAccount(AccountNumber number, AccountData data) { ... }
}@Remote public interface AccountManager {
public void createAccount(AccountNumber number);
public void removeAccount(AccountNumber number);
public void updateAccount(AccountNumber number, AccountData data);
}
Regular Java class annotated with @Stateless deploys a stateless session
bean. It’s that easy!
/deploy
SLSB Pool
JNDIBind proxy
Client
lookup
invoke
What happened to deployment descriptors?!
7
© JBoss, Inc. 2003-2005. 13
Professional Open Source™
EJB3 Deployment Descriptors
<ejb-jar>
<display-name>Crime Portal Application</display-name>
<enterprise-beans>
<session>
<display-name>Money Laundering Bean</display-name>
<ejb-name>Laundry</ejb-name>
<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>
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
– Defaults are used whenever possible
• <transaction-type> �Container, etc.
© JBoss, Inc. 2003-2005. 14
Professional Open Source™
EJB 3.0 Deployment Descriptor
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)
8
© JBoss, Inc. 2003-2005. 15
Professional Open Source™
Stateful Beans
@Remote public interface ShoppingCart {
public void addItem(int prodId, int quantity);
public void checkout();
}
@Stateful public class ShoppingCartBean implements ShoppingCart {
@Remove
public void checkout() {
…
}
}
@Remote public interface ShoppingCart {
public void addItem(int prodId, int quantity);
public void checkout();
}
@Stateful public class ShoppingCartBean implements ShoppingCart {
@Remove
public void checkout() {
…
}
}
Still homeless
– Created as they are looked up @Remove replaces EJBObject.remove
– Stateful bean is removed after method called
End of method will remove the session.
© JBoss, Inc. 2003-2005. 16
Professional Open Source™
MDBs
@MessageDriven(
activationConfig={
ActivationConfigProperty(name=“destination”, value=“queue/email”)
}
)
public class EmailBean implements MessageListener {
void onMessage(Message msg) { }
public int add(int x, int y) {
return x + y;
}
}
@MessageDriven(
activationConfig={
ActivationConfigProperty(name=“destination”, value=“queue/email”)
}
)
public class EmailBean implements MessageListener {
void onMessage(Message msg) { }
public int add(int x, int y) {
return x + y;
}
}
Just implements MessageListener XML turns to annotations
9
© JBoss, Inc. 2003-2005. 17
Professional Open Source™
EJB3 Client View
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
AccountMgr.ejb3AccountManager.classAccountManagerBean.class
JNDIGlobal
AccountManager
public class Client {
public static void main(String[] args) throws Exception {
Context naming = new InitialContext();
AccountManager mgr =
(AccountManager)naming.lookup("AccountManager");
mgr.createAccount(new AccountNumber());
}
}
public class Client {
public static void main(String[] args) throws Exception {
Context naming = new InitialContext();
AccountManager mgr =
(AccountManager)naming.lookup("AccountManager");
mgr.createAccount(new AccountNumber());
}
}
© JBoss, Inc. 2003-2005. 18
Professional Open Source™
Conclusion
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)
10
Professional Open Source™
© JBoss, Inc. 2003-2005. 198/2/2005
EJB Transactions
© JBoss, Inc. 2003-2005. 20
Professional Open Source™
Transactions with Annotations
– Non-annotated methods default to REQUIRED– Method level annotation overrides bean-level annotations
@Stateful(name = “MyCart")
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class ShoppingCart implements Cart {
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void addItem(String item) { … }
@Remove public void close() { … }
}
@Stateful(name = “MyCart")
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class ShoppingCart implements Cart {
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void addItem(String item) { … }
@Remove public void close() { … }
}
Default for entire class.
11
© JBoss, Inc. 2003-2005. 21
Professional Open Source™
Application Exceptions
– Checked exceptions can be annotated to cause automatic rollback– RuntimeExceptions can be annotated to be unwrapped
@ApplicationException(rollback=true)
public class AccountBillingError extends Exception {}
@ApplicationException(rollback=false)
public class AppError extends RuntimeException {}
@ApplicationException(rollback=true)
public class AccountBillingError extends Exception {}
@ApplicationException(rollback=false)
public class AppError extends RuntimeException {}
Professional Open Source™
© JBoss, Inc. 2003-2005. 228/2/2005
EJB Security Annotations
12
© JBoss, Inc. 2003-2005. 23
Professional Open Source™
Security Annotations
Security and Method Permissions– @RolesAllowed, @PermitAll, @DenyAll, @RunAs, @SecurityRoles– @SecurityDomain jboss specifc– Maybe security information better suited for XML DD?
@Stateful
@RunAs(“Special Role”)
@org.jboss.annotation.SecurityDomain(“LdapDomain”)
public class ShoppingCartBean implements ShoppingCart {
@RolesAllowed({“valid_customer”})
public void checkout() {
…
}
}
@Stateful
@RunAs(“Special Role”)
@org.jboss.annotation.SecurityDomain(“LdapDomain”)
public class ShoppingCartBean implements ShoppingCart {
@RolesAllowed({“valid_customer”})
public void checkout() {
…
}
}
Professional Open Source™
© JBoss, Inc. 2003-2005. 248/2/2005
EJB Dependency Injection
13
© JBoss, Inc. 2003-2005. 25
Professional Open Source™
EJB 3.0: Dependency Injection
Bean class specifies dependencies instead of lookup EJB Container initializes annotated fields or calls setter methods
@Stateful public class ShoppingCartBean implements ShoppingCart {
@Resource private SessionContext ctx;
@EJB(name=“CreditProcessorEJB”)
private CreditCardProcessor processor;
private DataSource jdbc;
@Resource(name=“java:/DefaultDS”)
public void setDataSource(DataSource db) { this.jdbc = db; }
}
@Stateful public class ShoppingCartBean implements ShoppingCart {
@Resource private SessionContext ctx;
@EJB(name=“CreditProcessorEJB”)
private CreditCardProcessor processor;
private DataSource jdbc;
@Resource(name=“java:/DefaultDS”)
public void setDataSource(DataSource db) { this.jdbc = db; }
}
© JBoss, Inc. 2003-2005. 26
Professional Open Source™
EJB 3.0: Dependency Injection
XML injection also supported <injection-target> specified field or method to inject into
<ejb-ref>
<ejb-ref-name>ejb/Bank</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<remote>org.jboss.ejb3.test.bank.Bank</remote>
<ejb-link>Bank</ejb-link>
<injection-target>bank</injection-target>
</ejb-ref>
<ejb-ref>
<ejb-ref-name>ejb/Bank</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<remote>org.jboss.ejb3.test.bank.Bank</remote>
<ejb-link>Bank</ejb-link>
<injection-target>bank</injection-target>
</ejb-ref>
14
Professional Open Source™
© JBoss, Inc. 2003-2005. 278/2/2005
EJB Component Lifecycle
© JBoss, Inc. 2003-2005. 28
Professional Open Source™
Callbacks and Callback Listener Classes
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 public class CartBean implements ShoppingCart {
public int someShoppingMethod() {...};
...
@PreDestroy cleanup() {...};
}
@Stateful public class CartBean implements ShoppingCart {
public int someShoppingMethod() {...};
...
@PreDestroy 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.
15
© JBoss, Inc. 2003-2005. 29
Professional Open Source™
Callbacks for Session Beans
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. 30
Professional Open Source™
Callbacks for Session Beans
@Stateful public class CartBean implements ShoppingCart {
...
@PostConstruct @PostActivate
public void initRemoteConnectionToAccountSystem() {
// initialize connection after construction or activation
}
@PreDestroy @PrePassivate
public void closeRemoteConnectionToAccountSystem() {
// close connection before destruction or passivation
}
}
@Stateful public class CartBean implements ShoppingCart {
...
@PostConstruct @PostActivate
public void initRemoteConnectionToAccountSystem() {
// initialize connection after construction or activation
}
@PreDestroy @PrePassivate
public void closeRemoteConnectionToAccountSystem() {
// close connection before destruction or passivation
}
}
Same method can have multiple annotations.
16
© JBoss, Inc. 2003-2005. 31
Professional Open Source™
EJB LifeCycle Listeners
Reusable listeners for EJBs:– @CallbackListener annotation
– Implementation is any Java class with EJB lifecycle annotations
@Stateful (name = “CustomerCart”)
@CallbackListener(SessionListener.class)
public class CartBean implements ShoppingCart {
public void addItem(...) { ... }
public void removeItem(...) { ... }
public void checkout() { ... }
}
@Stateful (name = “CustomerCart”)
@CallbackListener(SessionListener.class)
public class CartBean implements ShoppingCart {
public void addItem(...) { ... }
public void removeItem(...) { ... }
public void checkout() { ... }
}
© JBoss, Inc. 2003-2005. 32
Professional Open Source™
EJB LifeCycle Listeners
– Can be reused for several bean implementations– Notice the different method signature
• Reference to the bean is passed as first argument
public class SessionListener {
@PostConstruct
public void create(Object bean) {
System.out.println(“Session created: " + bean.toString());
}
@PreDestroy
public void delete(CartBean bean) {
System.out.println(“Session destroyed: " + bean.toString());
}
}
public class SessionListener {
@PostConstruct
public void create(Object bean) {
System.out.println(“Session created: " + bean.toString());
}
@PreDestroy
public void delete(CartBean bean) {
System.out.println(“Session destroyed: " + bean.toString());
}
}
Declare the argument either as Java ”Object” type or specific
bean type.
17
© JBoss, Inc. 2003-2005. 33
Professional Open Source™
Conclusions
Component life-cycle can be marked with annotations– Any method can participate in bean life-cycle
– Listeners can be reused across bean implementations
Professional Open Source™
© JBoss, Inc. 2003-2005. 348/2/2005
EJB3 InterceptorsCustomize the invocation flow
18
© JBoss, Inc. 2003-2005. 35
Professional Open Source™
Interceptors in EJB3
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. 36
Professional Open Source™
Interceptors in EJB3
@Stateless
@Interceptors({"TransactionAudit“, "CustomSecurity"})
public class BankManager implements BankTransaction {
@Resource public SessionContext sc;
public void trade(int amount) {
System.out.println("Traded: " + amount + " CHF");
}
@AroundInvoke
public Object sendNotification(InvocationContext ctx) throws Exception {
// access internal state of the instance...
}
}
@Stateless
@Interceptors({"TransactionAudit“, "CustomSecurity"})
public class BankManager implements BankTransaction {
@Resource public SessionContext sc;
public void trade(int amount) {
System.out.println("Traded: " + amount + " CHF");
}
@AroundInvoke
public Object sendNotification(InvocationContext ctx) throws Exception {
// access internal state of the instance...
}
}
Define a stack of interceptors for this bean. The order is
relevant here.
An interceptor specific to bean implementation can be included. It will
be invoked after other interceptors
configured for the bean.
19
© JBoss, Inc. 2003-2005. 37
Professional Open Source™
InvocationContext
– Interceptor implementation has an access to an associated InvocationContext instance
public interface InvocationContext {
public Object getBean(); // reference to the bean instance
public Method getMethod(); // method to be called
public Object[] getParameters(); // args to the method
public void setParameters(Object[]); // access to mutate the args
public Context getEJBContext(); // EJBContext
public Map getContextData(); // shared data between interceptors
public Object proceed() throws Exception;
}
public interface InvocationContext {
public Object getBean(); // reference to the bean instance
public Method getMethod(); // method to be called
public Object[] getParameters(); // args to the method
public void setParameters(Object[]); // access to mutate the args
public Context getEJBContext(); // EJBContext
public Map getContextData(); // shared data between interceptors
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. 38
Professional Open Source™
Interceptors in EJB3
– Interceptor implementation is a regular Java object with a specific @AroundInvoke annotation
public class TransactionAudit {
@AroundInvoke
public Object auditTrade(InvocationContext ctx) throws Exception {
if (ctx.getMethod().getName().equals("trade")) {
Object[] args = ctx.getParameters();
EJBContext ejbContext = ctx.getEJBContext();
Integer tradeValue = (Integer)args[0];
String caller = ejbContext.getCallerPrincipal().getName();
sendMessage(caller + " executes trade of value: " + tradeValue);
}
return ctx.proceed();
}
}
public class TransactionAudit {
@AroundInvoke
public Object auditTrade(InvocationContext ctx) throws Exception {
if (ctx.getMethod().getName().equals("trade")) {
Object[] args = ctx.getParameters();
EJBContext ejbContext = ctx.getEJBContext();
Integer tradeValue = (Integer)args[0];
String caller = ejbContext.getCallerPrincipal().getName();
sendMessage(caller + " executes trade of value: " + tradeValue);
}
return ctx.proceed();
}
}
Interceptors can invoke JNDI, JDBC, JMS, EJBs. Transaction context and security context are the one of the
executing bean business method.
20
Professional Open Source™
© JBoss, Inc. 2003-2005. 398/2/2005
Persistence APINew POJO Persistence for J2EE and J2SE
© JBoss, Inc. 2003-2005. 40
Professional Open Source™
Goals
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
21
Professional Open Source™
© JBoss, Inc. 2003-2005. 418/2/2005
Defining Entity Beans
Full Object/Relational Database Mapping
© JBoss, Inc. 2003-2005. 42
Professional Open Source™
EJB 3.0 Entity Beans
O/R Mapping Metadata as annotations– Table mappings, @Table, @SecondaryTable– Column mappings, @Column, @JoinColumn– Relationships, @ManyToOne, @OneToOne, @OneToMany,
@ManyToMany– Multi-Table mappings, @SecondaryTable– Embedded objects, @Embedded– Inheritance, @Inheritance, @DiscriminatorColumn– Identifier + Version properties, @Id, @Version
22
© JBoss, Inc. 2003-2005. 43
Professional Open Source™
Entity Annotations
@Entity@Table(name=“AUCTION_ITEM”)public class Item {
private long id;private String description;private String productName;private Set<Bid> bids = new HashSet();private User seller;
@Id(generate=GeneratorType.AUTO) @Column(name=“ITEM_ID”)public long getId() {
return id; }public void setId(long id) {
this.id = id; }
@Entity@Table(name=“AUCTION_ITEM”)public class Item {
private long id;private String description;private String productName;private Set<Bid> bids = new HashSet();private User seller;
@Id(generate=GeneratorType.AUTO) @Column(name=“ITEM_ID”)public long getId() {
return id; }public void setId(long id) {
this.id = id; }
relational table declaration
auto-key generation
© JBoss, Inc. 2003-2005. 44
Professional Open Source™
Entity Annotations
@Entity@Table(name=“AUCTION_ITEM”)public class Item {
private long id;private String description;private String productName;private Set<Bid> bids = new
HashSet();private User seller;
@Id(generate=GeneratorType.AUTO) @Column(name=“ITEM_ID”)public long getId() {
return id; }public void setId(long id) {
this.id = id; }
@Entity@Table(name=“AUCTION_ITEM”)public class Item {
private long id;private String description;private String productName;private Set<Bid> bids = new
HashSet();private User seller;
@Id(generate=GeneratorType.AUTO) @Column(name=“ITEM_ID”)public long getId() {
return id; }public void setId(long id) {
this.id = id; }
create table AUCTION_ITEM(ITEM_ID Number,DESC varchar(255),ProductName varchar(255),USER_ID Number);
create table AUCTION_ITEM(ITEM_ID Number,DESC varchar(255),ProductName varchar(255),USER_ID Number);
23
© JBoss, Inc. 2003-2005. 45
Professional Open Source™
Entity Annotations
@Entity@Table(name=“AUCTION_ITEM”)public class Item {
private long id;private String description;private String productName;private Set<Bid> bids = new
HashSet();private Owner owner;
@Id(generate=GeneratorType.AUTO) @Column(name=“ITEM_ID”)public long getId() {
return id; }public void setId(long id) {
this.id = id; }
@Entity@Table(name=“AUCTION_ITEM”)public class Item {
private long id;private String description;private String productName;private Set<Bid> bids = new
HashSet();private Owner owner;
@Id(generate=GeneratorType.AUTO) @Column(name=“ITEM_ID”)public long getId() {
return id; }public void setId(long id) {
this.id = id; }
create table AUCTION_ITEM(ITEM_ID Number,DESC varchar(500),ProductName varchar(255),OWNER_ID Number);
create table AUCTION_ITEM(ITEM_ID Number,DESC varchar(500),ProductName varchar(255),OWNER_ID Number);
© JBoss, Inc. 2003-2005. 46
Professional Open Source™
Entity Annotations
…
@Column(name=“DESC”, length=500)public String getDescription() {
return description; }public void setDescription(String desc) {
this.description = desc; }
public String getProductName() { return productName;
}protected void setProductName(String name) {
this.productName = name; }
…
@Column(name=“DESC”, length=500)public String getDescription() {
return description; }public void setDescription(String desc) {
this.description = desc; }
public String getProductName() { return productName;
}protected void setProductName(String name) {
this.productName = name; }
column mapping
intuitive defaults
24
© JBoss, Inc. 2003-2005. 47
Professional Open Source™
Entity Annotations
…
@Column(name=“DESC”, length=500)public String getDescription() {
return description; }public void setDescription(String desc) {
this.description = desc; }
public String getProductName() { return productName;
}protected void setProductName(String name) {
this.productName = name; }
…
@Column(name=“DESC”, length=500)public String getDescription() {
return description; }public void setDescription(String desc) {
this.description = desc; }
public String getProductName() { return productName;
}protected void setProductName(String name) {
this.productName = name; }
create table AUCTION_ITEM(ITEM_ID Number,DESC varchar(500),ProductName varchar(255),OWNER_ID Number);
create table AUCTION_ITEM(ITEM_ID Number,DESC varchar(500),ProductName varchar(255),OWNER_ID Number);
© JBoss, Inc. 2003-2005. 48
Professional Open Source™
Relationships
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.
25
© JBoss, Inc. 2003-2005. 49
Professional Open Source™
Relationships
@Entity public class Account implements Serializable {
…
private Collection<Customer> customers = new HashSet<Customer>(3);
@Id (generate = GeneratorType.AUTO)
public long getId() { return id; }
public void setId(long id) { … }
public AccountNumber getAccountNumber() {
...
@OneToMany (mappedBy = “account”)
public Collection<Customer> getCustomers() {
return customers;
}
public void setCustomers(Collection<Customer> c) {
this.customers = c;
}
@Entity public class Account implements Serializable {
…
private Collection<Customer> customers = new HashSet<Customer>(3);
@Id (generate = GeneratorType.AUTO)
public long getId() { return id; }
public void setId(long id) { … }
public AccountNumber getAccountNumber() {
...
@OneToMany (mappedBy = “account”)
public Collection<Customer> getCustomers() {
return customers;
}
public void setCustomers(Collection<Customer> c) {
this.customers = c;
}
Customer will maintain the FK update.
Physical mapping will be stored in Customer.account
© JBoss, Inc. 2003-2005. 50
Professional Open Source™
Relationships
Default mappings– Bidirectional relationship, with a foreign key on the ”owning” side
@Entity public class Customer implements Serializable {
private int id;private String name;private Account account;
...
@ManyToOnepublic Account getAccount() {
return account;}
public void setAccount(Account acct) {this.account = acct;
}}
@Entity public class Customer implements Serializable {
private int id;private String name;private Account account;
...
@ManyToOnepublic Account getAccount() {
return account;}
public void setAccount(Account acct) {this.account = acct;
}}
AcctNro
hj323hf
PK
1
2
3
4
23hrfhjk
234hjt3
Name
Ulla
PK
1
2
3
4
Maija
Mia
FK
1
1
3
26
© JBoss, Inc. 2003-2005. 51
Professional Open Source™
Default Fetch Strategy
@Entity public class Account implements Serializable {
…
private Collection<Customer> customers = new HashSet<Customer>(3);
@Id (generate = GeneratorType.AUTO)
public long getId() { return id; }
public void setId(long id) { … }
public AccountNumber getAccountNumber() {
...
@OneToMany (mappedBy = “account”, fetch=LAZY)
public Collection<Customer> getCustomers() {
return customers;
}
public void setCustomers(Collection<Customer> c) {
this.customers = c;
}
@Entity public class Account implements Serializable {
…
private Collection<Customer> customers = new HashSet<Customer>(3);
@Id (generate = GeneratorType.AUTO)
public long getId() { return id; }
public void setId(long id) { … }
public AccountNumber getAccountNumber() {
...
@OneToMany (mappedBy = “account”, fetch=LAZY)
public Collection<Customer> getCustomers() {
return customers;
}
public void setCustomers(Collection<Customer> c) {
this.customers = c;
}
Lazily load this relationship
© JBoss, Inc. 2003-2005. 52
Professional Open Source™
No CMR
@Entity public class Account implements Serializable {
...
@OneToMany (mappedBy = “account”, fetch=LAZY, cascade={ALL})
public Collection<Customer> getCustomers() {
return customers;
}
public void setCustomers(Collection<Customer> c) {
this.customers = c;
}
public void addCustomer(Customer cust) {
this.customers.add(cust);
cust.setAccount(this);
}
@Entity public class Account implements Serializable {
...
@OneToMany (mappedBy = “account”, fetch=LAZY, cascade={ALL})
public Collection<Customer> getCustomers() {
return customers;
}
public void setCustomers(Collection<Customer> c) {
this.customers = c;
}
public void addCustomer(Customer cust) {
this.customers.add(cust);
cust.setAccount(this);
}
– 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
27
© JBoss, Inc. 2003-2005. 53
Professional Open Source™
Multi-Table
Multi-Table Mappings, – Entity can be stored in one or more tables– @SecondaryTables, @SecondaryTable
© JBoss, Inc. 2003-2005. 54
Professional Open Source™
Multi-table Mappings
@Entity@SecondaryTables({@SecondaryTable(name=“ADDRESS”
join={@JoinColumn(name=“ADDR_ID”)})public class Customer {
private long id;private String name;private String street;private String city;private String state;
@Id(generate=GeneratorType.AUTO) public long getId() {
return id; }public void setId(long id) {
this.id = id; }
@Entity@SecondaryTables({@SecondaryTable(name=“ADDRESS”
join={@JoinColumn(name=“ADDR_ID”)})public class Customer {
private long id;private String name;private String street;private String city;private String state;
@Id(generate=GeneratorType.AUTO) public long getId() {
return id; }public void setId(long id) {
this.id = id; }
create table Customer(ID Number,NAME varchar(255),);
create table ADDRESS(ADDR_ID Number,STREET varchar(255),CITY varchar(255),STATE varchar(255));z
create table Customer(ID Number,NAME varchar(255),);
create table ADDRESS(ADDR_ID Number,STREET varchar(255),CITY varchar(255),STATE varchar(255));z
28
© JBoss, Inc. 2003-2005. 55
Professional Open Source™
Multi-Table Mappings
@Column(name=“STREET”, secondaryTable=“ADDRESS”)
public String getStreet() { return street;
}public void setStreet(String street) {
this.street = street; }
@Column(name=“CITY”, secondaryTable=“ADDRESS”)
public String getCity() { return city;
}protected void setCity(String city) {
this.city = city; }
@Column(name=“STREET”, secondaryTable=“ADDRESS”)
public String getStreet() { return street;
}public void setStreet(String street) {
this.street = street; }
@Column(name=“CITY”, secondaryTable=“ADDRESS”)
public String getCity() { return city;
}protected void setCity(String city) {
this.city = city; }
create table Customer(OWNER_ID Number,NAME varchar(255),);
create table ADDRESS (ADDR_ID Number,STREET varchar(255),CITY varchar(255),STATE varchar(255));
create table Customer(OWNER_ID Number,NAME varchar(255),);
create table ADDRESS (ADDR_ID Number,STREET varchar(255),CITY varchar(255),STATE varchar(255));
© JBoss, Inc. 2003-2005. 56
Professional Open Source™
Embedded Objects
Embedded Objects– Aggregated objects whose properties can be mapped
@Embeddablepublic class Address {
private String street;private String city;private String state;
@Column(“STREET”)
public String getStreet() {return street;
}
public void setStreet(String street) {
this.street = street;}
public String getCity() {return city;
}
@Embeddablepublic class Address {
private String street;private String city;private String state;
@Column(“STREET”)
public String getStreet() {return street;
}
public void setStreet(String street) {
this.street = street;}
public String getCity() {return city;
}
29
© JBoss, Inc. 2003-2005. 57
Professional Open Source™
Embedded
@Entitypublic class Customer {
private Address address;…
@Embedded@AttributeOverrides({
@AttributeOverride(name=“street”, @Column(name=“STREET”)),
@AttributeOverride(name=“city”, @Column(name=“CITY”)),
@AttributeOverride(name=“state”, @Column(name=“STATE”))})public Address getAddress() {
return address; }
public void setAddress(Address address) { this.address = address;
}
…
@Entitypublic class Customer {
private Address address;…
@Embedded@AttributeOverrides({
@AttributeOverride(name=“street”, @Column(name=“STREET”)),
@AttributeOverride(name=“city”, @Column(name=“CITY”)),
@AttributeOverride(name=“state”, @Column(name=“STATE”))})public Address getAddress() {
return address; }
public void setAddress(Address address) { this.address = address;
}
…
© JBoss, Inc. 2003-2005. 58
Professional Open Source™
Composite Keys/Primary Key Classes
EJB 2.1 style primary keys– Same idea as @Embedded– @EmbeddedId, @Embeddable, @IdClass
30
© JBoss, Inc. 2003-2005. 59
Professional Open Source™
Composite Keys
@Entitypublic class Customer {
private CustomerPK pk;
@EmbeddedIdpublic CustomerPK getId() {
return id; }public void setId(OwnerPK id) {
this.id = id; }
@Entitypublic class Customer {
private CustomerPK pk;
@EmbeddedIdpublic CustomerPK getId() {
return id; }public void setId(OwnerPK id) {
this.id = id; }
@Embeddablepublic class CustomerPK {
private String name;private long ssn;
@Column(“NAME”)public String getName() {
return street;}
public long getSSN() {return sn;
}…
@Embeddablepublic class CustomerPK {
private String name;private long ssn;
@Column(“NAME”)public String getName() {
return street;}
public long getSSN() {return sn;
}…
© JBoss, Inc. 2003-2005. 60
Professional Open Source™
Entity Inheritance
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
31
© JBoss, Inc. 2003-2005. 61
Professional Open Source™
Entity Inheritance: Single Table per Class Hierarchy
@Entity public class Customer implements Serializable {
private long id;
private Name name;
private Address address;
...
@Entity public class Customer implements Serializable {
private long id;
private Name name;
private Address address;
...
@Entity public class ValuedCustomer extends Customer {
private AccountManager manager;
private PhoneNumber direct;
...
@Entity public class ValuedCustomer extends Customer {
private AccountManager manager;
private PhoneNumber direct;
...Discr.PK LNFN
1
Mgr.Name PhoneAddr.
2
3
4 VC
VC
C
C ...
...
...
...
...
...
...
...
...
...
...
...
null
null
Jack
Jill
555-1231
555-1238
null
null
© JBoss, Inc. 2003-2005. 62
Professional Open Source™
Entity Inheritance: Table Per Class
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Customer implements Serializable {
private long id;
private Name name;
private Address address;
...
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Customer implements Serializable {
private long id;
private Name name;
private Address address;
...
@Entity public class ValuedCustomer extends Customer {
private AccountManager manager;
private PhoneNumber direct;
...
@Entity public class ValuedCustomer extends Customer {
private AccountManager manager;
private PhoneNumber direct;
...
PK LNFN
X
Mgr.Name PhoneAddr.
Y
Z
Å
...
...
...
...
...
...
...
...
...
...
...
...
FNPK LN Addr.
1
2
3
4
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
...
CUSTOMER VALUEDCUSTOMER
32
© JBoss, Inc. 2003-2005. 63
Professional Open Source™
Entity Inheritance: Joined Subclass
@Entity @Inheritance(strategy = InheritanceType.JOINED)
public class Customer implements Serializable {
private long id;
private Name name;
private Address address;
...
@Entity @Inheritance(strategy = InheritanceType.JOINED)
public class Customer implements Serializable {
private long id;
private Name name;
private Address address;
...
@Entity public class ValuedCustomer extends Customer {
private AccountManager manager;
private PhoneNumber direct;
...
@Entity public class ValuedCustomer extends Customer {
private AccountManager manager;
private PhoneNumber direct;
...
PK,FK Mgr.Name Phone
...
...
...
...
...
...
...
...
FNPK LN Addr.
1
2
3
4
...
...
...
...
...
...
...
...
...
...
...
...
CUSTOMER VALUEDCUSTOMER
1
2
3
4
Professional Open Source™
© JBoss, Inc. 2003-2005. 648/2/2005
Entity lifecycle and callbacks
Plain Java Objects
33
© JBoss, Inc. 2003-2005. 65
Professional Open Source™
Entity Listeners and Callback Methods
@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. 66
Professional Open Source™
Entity Callback Methods
public class Account implements Serializable {
@PrePersist public void validateFields(){
}
@PostLoad public void ensureUpperCase() {
}
}
public class Account implements Serializable {
@PrePersist public void validateFields(){
}
@PostLoad public void ensureUpperCase() {
}
}
– Can be implemented on the bean class
34
© JBoss, Inc. 2003-2005. 67
Professional Open Source™
Entity Listeners and Callback Methods
@Entity @EntityListener(AccountAudit.class)
public class Account implements Serializable {
...
@Entity @EntityListener(AccountAudit.class)
public class Account implements Serializable {
...
public class AccountAudit {
@PrePersist public void validateFields(Object bean) {
// check field values, set classifiers, other business rules, etc.
}
@PreUpdate public void audit(Account bean) {
// set field values for caller principal, date and time stamp
}
}
public class AccountAudit {
@PrePersist public void validateFields(Object bean) {
// check field values, set classifiers, other business rules, etc.
}
@PreUpdate public void audit(Account bean) {
// set field values for caller principal, date and time stamp
}
}
– Callback methods can also be externalized in an EntityListener
• Reference to the bean is passed as first argument
Declare the argument either as Java ”Object” type or specific
bean type.
Professional Open Source™
© JBoss, Inc. 2003-2005. 688/2/2005
Interacting With Entity Bean
Plain Java Objects
35
© JBoss, Inc. 2003-2005. 69
Professional Open Source™
Entity Manager
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. 70
Professional Open Source™
Create the objects
Create the entities like you would any other object
Allocate entire object graph like any other Java code
Item item = new Item();
item.setDescription(“O’reilly’s EJB 4th Edition”);
item.setProductName(“EJB 2.1 Book”);
…
Owner bill = new Owner();
bill.setName(“Bill”);
item.setOwner(bill);
Bid bid = new Bid();
…
HashSet<Bid> bids = new HashSet();
bids.add(bid);
item.setBids(bids);
Item item = new Item();
item.setDescription(“O’reilly’s EJB 4th Edition”);
item.setProductName(“EJB 2.1 Book”);
…
Owner bill = new Owner();
bill.setName(“Bill”);
item.setOwner(bill);
Bid bid = new Bid();
…
HashSet<Bid> bids = new HashSet();
bids.add(bid);
item.setBids(bids);
36
© JBoss, Inc. 2003-2005. 71
Professional Open Source™
Entity Manager
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. 72
Professional Open Source™
EntityManager
EntityManager API:– Create and remove persistent entity instance
– Find entities by primary keys– Execute queries for entities
public interface EntityManager {
public void persist(Object entity); // from new to managed
public <T> T merge(T entity); // from detached to managed
public void remove(Object entity); // from managed to removed
public Object find(String entityName, Object primaryKey);// find by primary key
public <T> T find(Class entityClass, Object primaryKey); // --´´--
public void flush(); // sync to database
public Query createQuery(String ejbqlString); // create EJB-QL query
public Query createNamedQuery(String name); // named queries
public Query createNativeQuery(String sqlString); // create SQL query (not portable)
public void refresh(Object entity); // sync from database
...
}
public interface EntityManager {
public void persist(Object entity); // from new to managed
public <T> T merge(T entity); // from detached to managed
public void remove(Object entity); // from managed to removed
public Object find(String entityName, Object primaryKey);// find by primary key
public <T> T find(Class entityClass, Object primaryKey); // --´´--
public void flush(); // sync to database
public Query createQuery(String ejbqlString); // create EJB-QL query
public Query createNamedQuery(String name); // named queries
public Query createNativeQuery(String sqlString); // create SQL query (not portable)
public void refresh(Object entity); // sync from database
...
}
37
© JBoss, Inc. 2003-2005. 73
Professional Open Source™
EntityManager
@Stateless public class ItemDAOImpl implements ItemDAORemote {
@PersistenceContext(unitName=“Auction”)private EntityManager em;
public long create(Item item) {em.create(item); return item.getId();
}
public Item findById(long id) {return em.find(Item.class, id);
}
public void merge(Item item) {em.merge(item);
}}
@Stateless public class ItemDAOImpl implements ItemDAORemote {
@PersistenceContext(unitName=“Auction”)private EntityManager em;
public long create(Item item) {em.create(item); return item.getId();
}
public Item findById(long id) {return em.find(Item.class, id);
}
public void merge(Item item) {em.merge(item);
}}
Inject the EntityManager service
© JBoss, Inc. 2003-2005. 74
Professional Open Source™
EntityManager
@Stateless public class ItemDAOImpl implements ItemDAORemote {
@PersistenceContext(unitName=“Auction”)private EntityManager em;
public long create(Item item) {em.persist(item); return item.getId();
}
public Item findById(long id) {return em.find(Item.class, id);
}
public void merge(Item item) {em.merge(item);
}}
@Stateless public class ItemDAOImpl implements ItemDAORemote {
@PersistenceContext(unitName=“Auction”)private EntityManager em;
public long create(Item item) {em.persist(item); return item.getId();
}
public Item findById(long id) {return em.find(Item.class, id);
}
public void merge(Item item) {em.merge(item);
}}
• Item allocated
remotely
• If cascade CREATE,
entire object graph
inserted into storage
38
© JBoss, Inc. 2003-2005. 75
Professional Open Source™
EntityManager
@Stateless public class ItemDAOImpl implements ItemDAORemote {
@PersistenceContext(unitName=“Auction”)private EntityManager em;
public long create(Item item) {em.persist(item); return item.getId();
}
public Item findById(long id) {return em.find(Item.class, id);
}
public void merge(Item item) {em.merge(item);
}}
@Stateless public class ItemDAOImpl implements ItemDAORemote {
@PersistenceContext(unitName=“Auction”)private EntityManager em;
public long create(Item item) {em.persist(item); return item.getId();
}
public Item findById(long id) {return em.find(Item.class, id);
}
public void merge(Item item) {em.merge(item);
}}
• Item found with
primary key
• Detached from
persistent storage at tx
completion
• Can be serialized like
any other object
© JBoss, Inc. 2003-2005. 76
Professional Open Source™
EntityManager
@Stateless public class ItemDAOImpl implements ItemDAORemote {
@PersistenceContext(unitName=“Auction”)private EntityManager em;
public long create(Item item) {em.persist(item); return item.getId();
}
public Item findById(long id) {return em.find(Item.class, id);
}
public void merge(Item item) {em.merge(item);
}}
@Stateless public class ItemDAOImpl implements ItemDAORemote {
@PersistenceContext(unitName=“Auction”)private EntityManager em;
public long create(Item item) {em.persist(item); return item.getId();
}
public Item findById(long id) {return em.find(Item.class, id);
}
public void merge(Item item) {em.merge(item);
}}
• Item can be updated remotely
and changes merged back to
persistent storage
• merge() returns a managed
copy of Item
39
© JBoss, Inc. 2003-2005. 77
Professional Open Source™
Query API
Queries may be expressed as EJBQL strings– Embedded in code– Externalized to metadata (named queries)
Invoke via Query interface– Named parameter binding– Pagination control
public List findWithName(String name) {
return em.createQuery(
"SELECT c FROM Customer c WHERE c.name LIKE :custName")
.setParameter("custName", name)
.setMaxResults(10)
.getResultList();
}
public List findWithName(String name) {
return em.createQuery(
"SELECT c FROM Customer c WHERE c.name LIKE :custName")
.setParameter("custName", name)
.setMaxResults(10)
.getResultList();
}
Runtime query creation.
Named parameters.
Pagination control.
© JBoss, Inc. 2003-2005. 78
Professional Open Source™
Queries
Query API– Available via EntityManager interface
• createQuery(), createNamedQuery(), createNativeQuery()
/** Interface used to control query execution.*/public interface Query {
/** Execute the query and return the query results as a List. */public List getResultList();
/** Execute a query that returns a single result.* @throws NonUniqueResultException if more than one result */
public Object getSingleResult();
/** Set the maximum number of results to retrieve. */public Query setMaxResults(int maxResult);
/** Set an implementation-specific hint. */public Query setHint(String hintName, Object value);
/** Bind an argument to a named parameter. */public Query setParameter(String name, Object value);...
/** Interface used to control query execution.*/public interface Query {
/** Execute the query and return the query results as a List. */public List getResultList();
/** Execute a query that returns a single result.* @throws NonUniqueResultException if more than one result */
public Object getSingleResult();
/** Set the maximum number of results to retrieve. */public Query setMaxResults(int maxResult);
/** Set an implementation-specific hint. */public Query setHint(String hintName, Object value);
/** Bind an argument to a named parameter. */public Query setParameter(String name, Object value);...
40
© JBoss, Inc. 2003-2005. 79
Professional Open Source™
EJB QL 3.0
EJBQL 3.0 is very similar to HQL (Hibernate Query Language) Aggregation, projection
– select max(b.amount) from Bid b where b.item = :id– select new Name(c.first, c.last) from Customer c
Fetching– from Item i left join fetch i.bids– 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
Professional Open Source™
© JBoss, Inc. 2003-2005. 808/2/2005
Entity Bean Packaging
New .par archive
41
© JBoss, Inc. 2003-2005. 81
Professional Open Source™
Persistence Packaging
Entities packaged in .par file Has application level metadata in META-INF/persistence.xml
<entity-manager>
<name>CRM</name>
<jta-data-source>java:/DefaultDS</jta-data-source>
<jar-file>optional additional jar files to look at</jar-file>
<class>optional class to deploy</class>
<mapping-file>optional resource name of XML mapping file</mapping-file>
<properties>
<property name=“hibernate.dialect” value=“MySQL”/>
</properties>
</entity-manager>
<entity-manager>
<name>CRM</name>
<jta-data-source>java:/DefaultDS</jta-data-source>
<jar-file>optional additional jar files to look at</jar-file>
<class>optional class to deploy</class>
<mapping-file>optional resource name of XML mapping file</mapping-file>
<properties>
<property name=“hibernate.dialect” value=“MySQL”/>
</properties>
</entity-manager>
{
@PersistenceContext(unitName=“CRM”)
private EntityManager manager;
}
{
@PersistenceContext(unitName=“CRM”)
private EntityManager manager;
}
Professional Open Source™
© JBoss, Inc. 2003-2005. 828/2/2005
JBoss Extensions to EJB 3
From EJBs to Enterprise POJOs
42
Professional Open Source™
© JBoss, Inc. 2003-2005. 838/2/2005
The Service Bean
© JBoss, Inc. 2003-2005. 84
Professional Open Source™
Service bean
Singleton services Multi-threaded and stateful Lifecycle and dependency management Next iteration of the JBoss MBean
43
© JBoss, Inc. 2003-2005. 85
Professional Open Source™
Service bean
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. 86
Professional Open Source™
Service interfaces
@Remote, @Local Just like EJB
@Remote
Public interface CalculatorRemote
{
BigDecimal add(float x, float y);
BigDecimal divide(float x, float y);
}
@Remote
Public interface CalculatorRemote
{
BigDecimal add(float x, float y);
BigDecimal divide(float x, float y);
}
44
© JBoss, Inc. 2003-2005. 87
Professional Open Source™
Service interfaces
@Management JMX interface, JMX aspect
@Management
public interface CalculatorManagement
{
int getPrecision();
void setPrecision();
}
@Management
public interface CalculatorManagement
{
int getPrecision();
void setPrecision();
}
© JBoss, Inc. 2003-2005. 88
Professional Open Source™
Service bean class
@Service deploys a singleton Multi-threaded and stateful
@Service
public class CalculatorService implements CalculatorRemote, CalculatorManagement
{
private int precision;
public int getPrecision() { return precision; }
void setPrecision(int p) { precision = p; }
BigDecimal divide(float x, float y) {…}
}
@Service
public class CalculatorService implements CalculatorRemote, CalculatorManagement
{
private int precision;
public int getPrecision() { return precision; }
void setPrecision(int p) { precision = p; }
BigDecimal divide(float x, float y) {…}
}
45
Professional Open Source™
© JBoss, Inc. 2003-2005. 898/2/2005
Message Driven POJOsTyped MDBs
© JBoss, Inc. 2003-2005. 90
Professional Open Source™
Message Driven POJOs
MDBs with a typed interface MDBs that publish a well known interface Simplify JMS Invoke methods, don’t build messages Cleaner, clearer code
46
© JBoss, Inc. 2003-2005. 91
Professional Open Source™
Message Driven POJOs
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. 92
Professional Open Source™
Using a Producer
Producers implicitly extend ProducerObject interface
{
EmailRemote queue = (EmailRemote)ctx.lookup(EmailRemote.class.getName());
ProducerManager con = ((ProducerObject)queue).getProducerManager();
con.connect();
queue.send(“spam”);
queue.send(“[email protected]”, “[email protected]”, “spam”, new HashMap());
con.close();
}
{
EmailRemote queue = (EmailRemote)ctx.lookup(EmailRemote.class.getName());
ProducerManager con = ((ProducerObject)queue).getProducerManager();
con.connect();
queue.send(“spam”);
queue.send(“[email protected]”, “[email protected]”, “spam”, new HashMap());
con.close();
}
47
© JBoss, Inc. 2003-2005. 93
Professional Open Source™
@Consumer
@Consumer(activation={
ActivationConfigProperty(name=“destinationType”, value=“javax.jms.queue”),
ActivationConfigProperty(name=“destination”, value=“queue/foo”)
})
public class EmailerBean implements EmailRemote, EmailXA {
public void send(String msg) {
…
}
public void send(String to, String from, String msg, Map props) {
…
}
}
@Consumer(activation={
ActivationConfigProperty(name=“destinationType”, value=“javax.jms.queue”),
ActivationConfigProperty(name=“destination”, value=“queue/foo”)
})
public class EmailerBean implements EmailRemote, EmailXA {
public void send(String msg) {
…
}
public void send(String to, String from, String msg, Map props) {
…
}
}
© JBoss, Inc. 2003-2005. 94
Professional Open Source™
@Producer
@Producer
public interface EmailRemote {
public void send(String msg);
public void send(String to, String from, String msg, Map props);
}
@Producer
public interface EmailRemote {
public void send(String msg);
public void send(String to, String from, String msg, Map props);
}
@Producer(connectionFactory=“java:/JmsXA”)
public interface EmailXA {
public void send(String msg);
public void send(String to, String from, String msg, Map props);
}
@Producer(connectionFactory=“java:/JmsXA”)
public interface EmailXA {
public void send(String msg);
public void send(String to, String from, String msg, Map props);
}
48
© JBoss, Inc. 2003-2005. 95
Professional Open Source™
Message Driven POJOs
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. 96
Professional Open Source™
@Producer
Producers implicitly extend ProducerObject interface
public interface ProducerObject {
ProducerManager getProducerManager();
}
public interface ProducerManager {
void setUsername(String user);
void setPassword(String passwd);
void connect() throws JMSException;
void close() throws JMSException;
void commit() throws JMSException;
void rollback() throws JMSException;
}
public interface ProducerObject {
ProducerManager getProducerManager();
}
public interface ProducerManager {
void setUsername(String user);
void setPassword(String passwd);
void connect() throws JMSException;
void close() throws JMSException;
void commit() throws JMSException;
void rollback() throws JMSException;
}
49
© JBoss, Inc. 2003-2005. 97
Professional Open Source™
Using a Producer
Producers implicitly extend ProducerObject interface
{
EmailRemote queue = (EmailRemote)ctx.lookup(EmailRemote.class.getName());
ProducerManager con = ((ProducerObject)queue).getProducerManager();
con.connect();
queue.send(“spam”);
queue.send(“[email protected]”, “[email protected]”, “spam”, new HashMap());
con.close();
}
{
EmailRemote queue = (EmailRemote)ctx.lookup(EmailRemote.class.getName());
ProducerManager con = ((ProducerObject)queue).getProducerManager();
con.connect();
queue.send(“spam”);
queue.send(“[email protected]”, “[email protected]”, “spam”, new HashMap());
con.close();
}
© JBoss, Inc. 2003-2005. 98
Professional Open Source™
Configuring Message Properties
@Producer(transacted=true)
@MessageProperties(delivery=NON_PERSISTENT)
public interface EmailRemote {
@MessageProperties(delivery=PERSISTENT, timeToLive=1000, priority=1)
public void send(String msg);
public void send(String to, String from, String msg, Map map);
}
@Producer(transacted=true)
@MessageProperties(delivery=NON_PERSISTENT)
public interface EmailRemote {
@MessageProperties(delivery=PERSISTENT, timeToLive=1000, priority=1)
public void send(String msg);
public void send(String to, String from, String msg, Map map);
}
50
Professional Open Source™
© JBoss, Inc. 2003-2005. 998/2/2005
Asynchronous EJBsLightweight asynchronous communication
© JBoss, Inc. 2003-2005. 100
Professional Open Source™
Asynchronous EJBs
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.
51
© JBoss, Inc. 2003-2005. 101
Professional Open Source™
Asynchronous EJBs
Available for Stateless, Stateful, and Service Each @Remote and @Local interface implements EJBProxy
public interface EJBProxy {
FutureProvider getAsynchronousProxy();
}
…
CalculatorRemote calc = (CalculatorRemote)ctx.lookup(“calculator”);
EJBProxy proxy = (EJBProxy)calc;
CalculatorRemote calcAsynch = (CalculatorRemote)proxy.getAsynchronousProxy();
public interface EJBProxy {
FutureProvider getAsynchronousProxy();
}
…
CalculatorRemote calc = (CalculatorRemote)ctx.lookup(“calculator”);
EJBProxy proxy = (EJBProxy)calc;
CalculatorRemote calcAsynch = (CalculatorRemote)proxy.getAsynchronousProxy();
© JBoss, Inc. 2003-2005. 102
Professional Open Source™
Asynchronous EJBs
Asynchronous Proxy same exact interface Invoking methods on proxy happen in background
CalculatorRemote calc = (CalculatorRemote)ctx.lookup(“calculator”);
EJBProxy proxy = (EJBProxy)calc;
CalculatorRemote calcAsynch = (CalculatorRemote)proxy.getAsynchronousProxy();
calcAsynch.add(1, 1); // invoked in background, in another thread
calcAsynch.divide(10, 2); // invoked in background
CalculatorRemote calc = (CalculatorRemote)ctx.lookup(“calculator”);
EJBProxy proxy = (EJBProxy)calc;
CalculatorRemote calcAsynch = (CalculatorRemote)proxy.getAsynchronousProxy();
calcAsynch.add(1, 1); // invoked in background, in another thread
calcAsynch.divide(10, 2); // invoked in background
52
© JBoss, Inc. 2003-2005. 103
Professional Open Source™
Asynchronous EJBs
Obtain response asynchronously– FutureProvider and Future interfaces
FutureProvider provider = (FutureProvider)calcAsynch;
calcAsynch.add(1, 1); // invoked in background, in another thread
Future result1 = provider.getFuture();
calcAsynch.divide(10, 2); // invoked in background
Future result2 = provider.getFuture();
int val1 = result1.get(); // block until first method call returns
if (result2.isDone()) { // poll to see if done
int val2 = result2.get();
}
FutureProvider provider = (FutureProvider)calcAsynch;
calcAsynch.add(1, 1); // invoked in background, in another thread
Future result1 = provider.getFuture();
calcAsynch.divide(10, 2); // invoked in background
Future result2 = provider.getFuture();
int val1 = result1.get(); // block until first method call returns
if (result2.isDone()) { // poll to see if done
int val2 = result2.get();
}
© JBoss, Inc. 2003-2005. 104
Professional Open Source™
JBoss Inc.
EJB 3.0 Available NOW!– Download at www.jboss.org– Tutorial with code examples