introduction ejb3

52
1 Professional Open Source™ © JBoss, Inc. 2003-2005. 1 8/2/2005 Introduction to EJB3 Preview to New Enterprise JavaBean Technology © JBoss, Inc. 2003-2005. 2 Professional Open Source™ Topics Goals of EJB3 New Enterprise Bean Contract Interceptors Persistence API

Upload: api-27341052

Post on 11-Apr-2015

944 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Introduction EJB3

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

Page 2: Introduction EJB3

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.

Page 3: Introduction EJB3

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.

Page 4: Introduction EJB3

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

Page 5: Introduction EJB3

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.

Page 6: Introduction EJB3

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?!

Page 7: Introduction EJB3

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)

Page 8: Introduction EJB3

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

Page 9: Introduction EJB3

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)

Page 10: Introduction EJB3

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.

Page 11: Introduction EJB3

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

Page 12: Introduction EJB3

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

Page 13: Introduction EJB3

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>

Page 14: Introduction EJB3

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.

Page 15: Introduction EJB3

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.

Page 16: Introduction EJB3

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.

Page 17: Introduction EJB3

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

Page 18: Introduction EJB3

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.

Page 19: Introduction EJB3

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.

Page 20: Introduction EJB3

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

Page 21: Introduction EJB3

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

Page 22: Introduction EJB3

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);

Page 23: Introduction EJB3

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

Page 24: Introduction EJB3

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.

Page 25: Introduction EJB3

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

Page 26: Introduction EJB3

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

Page 27: Introduction EJB3

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

Page 28: Introduction EJB3

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;

}

Page 29: Introduction EJB3

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

Page 30: Introduction EJB3

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

Page 31: Introduction EJB3

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

Page 32: Introduction EJB3

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

Page 33: Introduction EJB3

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

Page 34: Introduction EJB3

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

Page 35: Introduction EJB3

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);

Page 36: Introduction EJB3

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

...

}

Page 37: Introduction EJB3

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

Page 38: Introduction EJB3

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

Page 39: Introduction EJB3

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);...

Page 40: Introduction EJB3

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

Page 41: Introduction EJB3

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

Page 42: Introduction EJB3

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

Page 43: Introduction EJB3

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);

}

Page 44: Introduction EJB3

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) {…}

}

Page 45: Introduction EJB3

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

Page 46: Introduction EJB3

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();

}

Page 47: Introduction EJB3

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);

}

Page 48: Introduction EJB3

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;

}

Page 49: Introduction EJB3

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);

}

Page 50: Introduction EJB3

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.

Page 51: Introduction EJB3

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

Page 52: Introduction EJB3

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