2. Why am I doing slides?
Too much to cover
So little time
Slides are transportable, unlike code.
3. What was wrong with 2.1?
People complained a lot about it, like Dwight
XML Hell, large deployment descriptors
Too many artifacts for one bean
Lack of support for java.util.Date and
java.util.Calendar
Create your own subclass structure
Create your own value object to represent an
already developed entity bean.
5. What is new to EJB 3.0
POJO (Plain Old Java Objects) Development
Annotations Based
Descriptors Are Optional
–
Used to provide Database Metadata
–
Uses Dependency Injection
Entities now based on proven Hibernate ideas
6. Session and MDB
POJO & POJI (Plain Old Java Interfaces)
Based
Business Interface No Longer has to implement
EJBObject or EJBLocalObject
No more Home Interfaces
Fully Annotation Based
8. Session and MDB (Continued)
Field or method dependency injection.
Using annotations (preferred) or through XML
Lifecycle methods
Custom methods for lifecycle events
–
Callback listeners maybe used for lifecycle
–
management
Interceptors
Used to intercept methods
–
Very AOP like
–
9. EJB 2.1 Session Bean Interfaces
public interface Cart extends EJBObject {
public void add(String item) throws RemoteException;
public void Collection getItems() throws RemoteException;
public void process() throws RemoteException;
}
public interface CartHome extends EJBHome {
public Cart create() throws CreateException,
RemoteException;
}
10. EJB 2.1 Session Bean Class
public class CartEJB implements SessionBean {
protected Collection items = new ArrayList();
public void add(String item) {items.add(item);}
public Collection getItems() {return items;}
public void completeOrder() {...}
public void ejbCreate() {}
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext context)
{}
}
12. So what's the big deal?
Huge, too many interfaces
Must do too much
Too many interfaces
–
Must extend javax.ejb.Session
–
XML Hell Deployment Descriptor
–
13. New EJB 3.0 Session Interface
@Remote
public interface Cart {
public void add(String item);
public Collection getItems();
public void process();
}
14. New EJB 3.0 Session Interface
@Stateful
public class CartBean implements Cart {
private ArrayList items;
public void add(String item) {
items.add(item);
}
public Collection getItems() {
return items;
}
@Remove
public void process();
}
15. Dependency Injection
Occurs when EJBContext is set
Container figures what to set
Can inject on a method or a field
Can inject any resource like and EntityManager,
MailSource, JDBC Sources, EJBContexts, etc.
J2EE Scoped
16. Some Injection Examples
@EJB BankService bankServiceBean; //field
public void makeDeposit(float deposit) {
bankServiceBean.deposit(deposit);
}
@Resource SessionContext ctx; //field
TimerService service = ctx.getTimerService();
@Resource(name=”mySQLDB”) //method injection
public void setDataSource(DataSource ds) {
....
}
17. Callbacks and Interceptors
Callbacks occur at a given lifecycle state or
event
Stateless Session Bean
PostConstruct
–
PreDestroy
–
Stateful Session Bean
Post Construct
–
PreDestroy
–
PrePassivate
–
PostActivate
–
18. Callback Example
@Stateful
public class CartBean implements Cart {
ArrayList items = new ArrayList();
@PostConstruct
public void initCart() {
items = items.clear();
}
@PreDestroy @PrePassivate
public logAsNoSale() {
....
}
}
20. Interceptor Example Part 1
@Stateless
@Interceptors(com.evolutionnext.Logger.class)
public class HumanResourcesBean implements HumanResources
{
public void createEmployee(Employee employee);
public void fireEmployee(Employee employee);
public void adjustSalary(float raiseAmt);
}
21. Interceptor Example Part 2
public class Logger {
@AroundInvoke
public Object doSomeLogging(InvocationContext inv)
throws Exception {
//logging here
inv.proceed();
}
}
22. Interceptor Example Part 3
@Stateless
public class MyBean ... {
public void notIntercepted() {}
@Interceptors(org.acme.MyInterceptor.class)
public void someMethod() {
}
@Interceptors(org.acme.MyInterceptor.class)
public void anotherMethod() {
}
}
25. Interceptors Using XML 2
<interceptor-binding>
<ejb-name>EJBNAME</ejb-name>
<interceptor-class>INTERCEPTOR</interceptor-class>
<method-name>METHOD</method-name>
<method-params>
<method-param>PARAM-1</method-param>
<method-param>PARAM-2</method-param>
...
<method-param>PARAM-n</method-param>
</method-params>
<interceptor-binding>
26. EJB Persistence API
POJO Based
Inheritance and Polymorphism
O/R Mapping
Complete Querying Capabilities
Removed need for Data Value/Transfer Objects
More testable
27. Some more advantages
Concrete Classes
No more interface hell
Can be used OUTSIDE the Container
Uses Collections for relations, no more CMR
setup.
28. More?
LifeCycle Cascading (PERSIST, REMOVE,
REFRESH, MERGE, ALL)
Extended Persistent Contexts available
Default is scoped to one transaction
–
Extended is scoped over multiple transactions
–
FETCH JOINS are finally available
29. EntityManager
public void persist(Object entity);
public <T> T merge(T entity);
public void remove(Object entity);
public <T> T find(Class<T> entityClass, Object primaryKey);
public void flush();
public void lock(Object entity, LockModeType lockMode);
public void refresh(Object entity);
public void clear();
public boolean contains(Object entity);
public Query createQuery(String ejbqlString);
public Query createNamedQuery(String name);
public Query createNativeQuery(String sqlString);
30. Persisting
@Stateless public class OrderEntryBean implements OrderEntry {
@PersistenceContext EntityManager em;
public Order enterOrder(Order newOrder) {
Order order = em.persist(newOrder);
}
}
31. Find and Remove
@Stateless public class OrderEntryBean implements OrderEntry {
@PersistenceContext EntityManager em;
public void removeOrder(Long id) {
Order order = em.find(Order.class, id);
em.remove(order);
}
}
32. Merging
@Stateless public class OrderBean implements OrderI {
@PersistenceContext EntityManager em;
public Order updateOrder(Order newOrder) {
Order order = em.merge(newOrder);
return order;
}
}
33. Flush and Refresh
@Stateless public class OrderBean implements OrderI {
@PersistenceContext EntityManager em;
public Order updateOrder(Order newOrder) {
Order order = em.merge(newOrder);
em.flush();
em.refresh(order);
return order;
}
}
34. Flush and Refresh (Cont.)
Persistence Engine may defer writing to the
database until commit-time
Flush forces the commit with underlying DB
Refresh reloads the state of instance with the
DB.
35. Extended Persistence Context
Acts as an entity cache of managed instances
when clients access the same component over
multiple requests
Spans multiple transactions
Applies to:
Stateful Session Beans
–
HttpSessions
–
36. Transaction Scoped Example
@Stateless
public class ShoppingCartImpl implements ShoppingCart {
@PersistenceContext EntityManager em;
public Order getOrder(Long id) {
return em.find(Order.class, id);
}
public Product getProduct(String name) {
return (Product) em.createQuery(quot;select p from Product p
where p.name = :namequot;)
.setParameter(quot;namequot;, name)
.getSingleResult();
}
public LineItem createLineItem(Order order, Product product, int
quantity) {
LineItem li = new LineItem(order, product, quantity);
order.getLineItems().add(li);
em.persist(li);
return li;
}
}
37. XPC Example
@Stateful
@Transaction(REQUIRES_NEW)
public class ShoppingCartImpl implements ShoppingCart {
@PersistenceContext(type=EXTENDED)
EntityManager em;
private Order order;
private Product product;
public void initOrder(Long id) {
order = em.find(Order.class, id);
}
public void initProduct(String name) {
product = (Product) em.createQuery(quot;select p from Product p
where p.name = :namequot;)
.setParameter(quot;namequot;, name)
.getSingleResult();
}
public LineItem createLineItem(int quantity) {
LineItem li = new LineItem(order, product, quantity);
order.getLineItems().add(li);
return li;
}
}
38. Entity Callbacks
PrePersist – when persist() is called
PostPersist – after SQL Insert
PreRemove – when remove() is called
PostRemove – after SQL Delete
PreUpdate – when container detects dirtyness
PostUpdate – after SQL Update
PostLoad – after instance was loaded
All Attached using an @EntityListener
annotation
39. Entity Callbacks Example
@Entity
@EntityListeners(com.acme.AlertMonitor.class)
public class Account {
...
@Id
public Long getAccountId() { ... }
public Integer getBalance() { ... }
...
@Transient // because status depends upon non-persistent context
public boolean isPreferred() { ... }
public void deposit(Integer amount) { ... }
public Integer withdraw(Integer amount) throws NSFException {... }
@PrePersist
protected void validateCreate() {...}
@PostLoad
protected void adjustPreferredStatus() {...}
}
public class AlertMonitor {
@PostPersist
public void newAccountAlert(Account acct) {
Alerts.sendMarketingInfo(acct.getAccountId(), acct.getBalance());
}
40. Primary Keys
Can be denoted using @Id
Example: @Id long myId;
Use @EmbeddedId to indicate since id field
from composite PK class
Example @EmbeddedId MyObjID id;
Also need to tell which Id class the composite
key is
@IdClass(MyObjID.class);
41. Fetch
Hint to the Container to defer loading specific
field or relationships of on object until they are
accessed
Defaults
Simple, and Single Value Relationships – EAGER
–
Multi-value Relationships – LAZY
–
Entity should not access data directly from
fields
42. Cascade
Can cause specific lifecycle operation to
cascade across relationships
Can cascade combinations of
PERSIST, MERGE, REMOVE, REFRESH, ALL
–
Default is for no cascading
44. Simple Mappings
Direct Mappings of field to columns
@Basic – known field type maps to standard DB
–
Column
@Lob – maps to BLOB or CLOB type
–
@Column – you can customize the field and db
column attributes here
Default to type deemed appropriate by the
container
You can always override.
45. Example
@Entity (access=FIELD)
public class Customer {
@Id int id;
String name;
int rating;
@Lob Image photo;
}
@Entity (access=FIELD)
public class Customer {
@Id int id;
String name;
@Column(name=”Rating”) int rating;
@Lob Image photo;
}
46. Relationship Mappings
Common relationships supported
@ManyToOne, @OneToOne – single entity
–
@OneToMany, @ManyToMany – collection
–
Unidirectional and Bidirectional
Owning and inverse sides to every relationship
47. One To One Example
@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(name = quot;ADDRESS_IDquot;)
public Address getAddress()
{
return address;
}
48. Many To Many Example
On the customer side:
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch =
FetchType.EAGER, mappedBy=quot;customersquot;)
Other side of the relationship in Flight.
@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch
=FetchType.EAGER)
@JoinTable(table = @Table(name = quot;flight_customer_tablequot;),
joinColumns = {@JoinColumn(name = quot;FLIGHT_IDquot;)},
inverseJoinColumns = {@JoinColumn(name = quot;CUSTOMER_IDquot;)})
public Set<Customer> getCustomers()
{
return customers;
}
49. One To Many Example
@OneToMany(cascade = CascadeType.ALL, fetch =
FetchType.EAGER, mappedBy=quot;orderquot;)
public Collection<LineItem> getLineItems()
{
return lineItems;
}
@ManyToOne
@JoinColumn(name = quot;order_idquot;)
public Order getOrder()
{
return order;
}
50. Embeddable Objects Example
@Embeddable
public class Name implements java.io.Serializable
{
}}
The properties of Name must then be mapped to columns within
Customer's table.
@Embedded
@AttributeOverrides({
@AttributeOverride(name = quot;firstquot;, column ={@Column(name =
quot;FIRST_NAMEquot;)}),
@AttributeOverride(name = quot;lastquot;, column = {@Column(name =
quot;LAST_NAMEquot;)})
})
public Name getName()
{
return name;
}
51. Inheritance
Entities can extend
Other entities – concrete or abstract
–
Non-entity classes – concrete or abstract
–
Three strategies
Single Table – all classes in the same table
–
Joined – each class stored in a separate table
–
Table per Class – each concrete class stored in
–
separate table
53. Single Table Example
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = quot;ANIMAL_TYPEquot;, discriminatorType =
DiscriminatorType.STRING)
public class Pet implements java.io.Serializable
{
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING)
@DiscriminatorValue(quot;DOGquot;)
public class Dog extends Pet
{
public List findByWeight(double weight)
{
return manager.createQuery(quot;from Pet p where p.weight <
:weightquot;).setParameter(quot;weightquot;, weight).getResultList();
}
54. Join Table Example
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Pet implements java.io.Serializable
{
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Dog extends Pet
{
public List findByWeight(double weight)
{
return manager.createQuery(quot;from Pet p where p.weight <
:weightquot;).setParameter(quot;weightquot;, weight).getResultList();
}
55. Table Per Class Example
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Pet implements java.io.Serializable
{
@Entity
public class Dog extends Pet
{
public List findByWeight(double weight)
{
return manager.createQuery(quot;from Pet p where
p.weight < :weightquot;).setParameter(quot;weightquot;,
weight).getResultList();
}
56. Query API
Definitely more solid!
Date support
Ability to return a single result or list
Ability to fetch results.
Ability to fetch set number of results
Best of all: Queries return objects!
58. ..but no one likes BNF syntax
Except for Dave Burkett
Let do examples!
59. Simple Queries
Retreive All Orders
SELECT o
FROM Order o
Find all orders that need to be shipped to
California:
SELECT o
FROM Order o
WHERE o.shippingAddress.state = ‘CA’
Find all states for which there are orders:
SELECT DISTINCT o.shippingAddress.state
FROM Order o
60. Queries with Relationships
Find all orders that have line items:
SELECT DISTINCT o
FROM Order o, IN(o.lineItems) l
Note that the result of this query does not include orders with no associated
line items. This query can
also be written as:
SELECT o
FROM Order o
WHERE o.lineItems IS NOT EMPTY
Find all orders that have no line items:
SELECT o
FROM Order o
WHERE o.lineItems IS EMPTY
61. More !
SELECT DISTINCT o
FROM Order o JOIN o.lineItems l
WHERE l.shipped = FALSE
SELECT o
FROM Order o
WHERE
NOT (o.shippingAddress.state = o.billingAddress.state AND
o.shippingAddress.city = o.billingAddress.city AND
o.shippingAddress.street = o.billingAddress.street)
SELECT o
FROM Order o
WHERE o.shippingAddress <> o.billingAddress
SELECT DISTINCT o
FROM Order o JOIN o.lineItems l
WHERE l.product.type = ‘book’ AND
l.product.name = ‘Applying Enterprise JavaBeans:
Component-Based Development for the J2EE Platform’
62. Now with input parameters
SELECT DISTINCT o
FROM Order o, IN(o.lineItems) l
WHERE l.product.name = ?1
or
SELECT DISTINCT o
FROM Order o, IN(o.lineItems) l
WHERE l.product.name = :name
63. So can I see a full example?
public List findOrderByCustomer(Customer cust, int max) {
return entityManager.createQuery (
“SELECT o from Order o “ +
“where customer.id = :custId “ +
“order by o.createdDateTime”)
.setParameter(“custId”, cust.getId())
.setMaxResults(max)
.getResultList();
)
}