EJB 3.0 introduced a simplified programming model for enterprise Java with plain old Java objects (POJOs), dependency injection, and metadata-driven configuration. The new features include support for POJO session beans with simplified lifecycles, the Java Persistence API (JPA) for object-relational mapping, and the ability to define interceptors for cross-cutting concerns.
2. EJB 3.0 - fundamentals Presents a simplified programming and packing model Based on POJO-programming: no programmatic dependencies on framework classes
5. life cycle callbacks Default values for configurations used whenever possible: “Configure by exception”
6. Introduce object/relational mapping persistence API which works on simple domain object (inspired by Hibernate) Is still an “Enterprise” platform that offers stable handling of transactions
21. Session beans - basic A session beans is an ordinary bean implementing an interface and has a @Stateless or @Stateful annotation public interface My { public void doWork(Work w); } @Stateless public class MyBean implements My { public void doWork(Work w) {} } This will declare the bean a stateless session bean with a local business interface My
22. Add @Remote to interface or bean to make the interface Remote @Stateless @Remote public class MyBean implements My
23. Session bean – local and remote interface A session bean may have both a local and a remote interface
26. Annotation may be in interfaces @Remote public interface MyRemote extends My { } @Local public interface MyLocal extends My {} or in bean class @Sateless @Remote(MyRemote.class) @Local(MyLocal.class) public class MyBean extends My {
27. Session bean lifecycle callbacks Session beans may use annotation to declare lifecycle callback interceptor methods to receive notifications of life cycle events
28. All session beans may use @PostConstruct and @PreDestroy @PostConstruct public void init() {} @PreDestroy public void destroy() {} A stateful session may also get callback during activation from or deactivation to temporary storage with @PostActivate and @PrePassivate @PostActivate public void activate() {} @PrePassivate public void passivate() {} A stateful bean may also declare a business method to be the last in a conversation with the @Remove annotation (i.e the stateful bean is removed when call ends) @Remove public void saveCart() {}
32. May use one or more @ActivationConfigProperty annotation for configuration @MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"), @ActivationConfigProperty(propertyName="destination", propertyValue="queue/mdb") }) public class CalculatorBean implements MessageListener { public void onMessage (Message msg) {
33. Dependency injection By declaring dependencies on other EJB:s, resources or context a bean will get references to these injected at runtime
34. May be injected as an attribute (public, protected, private)
35. a setter (public, protected, private) Uses reasonable defaults
40. EJB injection Injecting an EJB attribute @EJB private MyLocal myLocal; Injecting an EJB method @EJB public void setMy(MyLocal myLocal) {} Specify a name and interface @EJB(beanName=”MySubBean”, beanInterface=MyLocal.class) private My my; Specify a direct JNDI-name @EJB(mappedName=”ear-name/MyBean/remote) private My my;
43. Injection of simple environmental entries (env-entry) @Resource int maxFoo = 5; Declaring a data base resource @Resource(name="jdbc/__default", type=javax.sql.DataSource.class) public class StatelessSessionBean Injecting it @Resource(name="jdbc/__default") DataSource myDs; Lookup any resource from JNDI (app-server specific) @Resource(mappedName=”my/jndi/ref) MyCustom custom;
45. Contexts are injected when needed @Resource SessionContext ctx; @Resource MessageDrivenContext ctx; Its also possoble to get a UserTransaction injected @Resource private UserTransaction utx;
48. May be set as default for a bean @TransactionAttribute(NOT_SUPPORTED) public class MyBean And overriden on a method base @TransactionAttribute(REQUIRED) public void save()
49. Security The allowed roles are defined with the annotations javax.annotation.security AllowedRoles and PermitAll @AllowedRoles(“USERS”); public class MyBean { @AllowAll public List list() { @AllowedRoles(“ADMIN”) public delete() { } The RunAs annotation establishes the identity a bean will have when it call other beans @RunAs(“PRIVELIGED_USERS”); public class MyBean {
54. An interceptor may be defined as a method in a bean @Stateless public class MyBean { @AroundInvoke public Object log(InvocationContext inv) throws Exception { // Do stuff return inv.proceed(); }
55. Interceptors (cont) Or in its own class public class PasswordValidator { @AroundInvoke public Object validate(InvocationContext inv) {} And be references from bean, either from class @Interceptors({PasswordValidator.class}) public class MyBean { Or on a specific method @Interceptors(PasswordValidator) public void changePassword(String old, String newP, String cmp) { Interceptors may be excluded on class and method level @ExcludeDefaultInterceptors public class MyBean @ExcludeClassInterceptor public void pure() {
56. Exceptions As before: system exceptions (java.lang.RuntimeException and java.rmi.RemoteException cases rollback
57. all application exceptions do not cause rollback New annotations for exceptions @javax.ejb.ApplicationException
59. Declarative statement if an application exception shall cause a rollback @ApplicationException(rollback=true) MyAppException extends RuntimeException {
93. In its own classes or on bean direct public class Notifyer { @PostPersist void postSave(Object entity) {} } @EntityListeners used to add listener on an entity @Entity @EntityListeners(Notifyer.class) public class MyEntity { @PostLoad void afterLoad() {}
95. must be access through the new javax.persistence.EntityManager service
96. Typically injected with @PersistenceContext annotation @PersistenceContext private EntityManager manager; May be used in session beans, message driven beans, interceptors, JSF managed beans, servlets
97. An entity is managed as long it is attached to a persistence context
98. When a persistence context is closed all entities it manages becomes detatched
99. A persistence context is only valid during a transaction, its is closed when transaction commits
103. In EJB it may only be used in stateful session beans
104. The extended context is closed when the stateful bean is removed @PersistenceContext(type=PersistenceContextType.EXTENDED) private EntityManager manager;
105. EntityManager usage Persist – queue for flush em.persist(entity); Find an entity My m = em.find(My.class, primaryKey); // null if not found My m em.getReference(My.class, primaryKey); // exception if not found Updating an entity inside a transaction (its still managed my tx) entity.setValue(newValue); Re-atatche entity – queue for flush entity.setValue(newValue); My copy = em.merge(entity); Remove an entity – queue for flush em.remove(entity); Refresh entity from backend em.refresh(entity); Check if entity is managed boolean isManaged = em.contains(entity);
106. EntityManager usage (cont) Clear context from all entities (de-tatche) em.clear(); Manually flush/save state to backend (done automatically at least in commit of transaction) em.flush(); Only flush at commit not before any queries (flush manually only for needed queries) em.setFlushMode(FlushModeType.COMMIT); When all else fail, get implementation, eg: Session ses = (Session)em.getDelegate( );
108. Create a query from en EntityManager Query q = em.createQuery(“from My m where c.value = 'myval'”); Query q = em.createNamedQuery(“myQuery”); // defined in annotation Query q = em.createNativeQuery(“select * from my”); Get the result List mys = q.getResultList(); Use parameters Query q = em.createQuery(“from My m where c.value=:value ”); q.setParameter(“value”, “myval”); Set paging q.setMaxResults(MAX).setFirstResult(index);
109. Using the Query API (cont) Support fine grained queries Query q = em.createQuery(“SELECT m.value FROM My AS m”); Support object creation from queries SELECT new my.pack.ValueHolder(m.value) FROM My AS m Supports IN
122. Delegated by default to database set isolation level in a vendor specific way Possible to use support for optimistic locking design pattern and programmatic pessimistic locking
123. Use the @Version annotation in an Entity makes it handled optimistically @Version protected long getVersion() {...} protected void setVersion(long version) {...} update MY_BEAN set value='new value', version = version + 1 where id = ID and version = LAST Or use programattic locking in EntityManager em.lock(myEntity, LockModeType.WRITE); // or READ (May by spec only be supported in Entities with a @Version property)