EJB 3.0 EINFÜHRUNG UND STATUS Peter Doschkinow Software Architekt Sun Microsystems 1 Agenda • Motivation • EJB 3.0 Programmier-Modell • Java Persistence API (JPA) • Aktueller Status und Zusammenfassung 2 EJB Status vor EJB 3.0 • EJB 2.1 ist sehr mächtig, aber zu komplex • Ursprungsziel der EJB Technologie > Bereitstellung einer kontrollierten Umgebung zur Unterstützung und Ablauf von Enterprise-Anwendungen • Container-Aufgaben > bietet eine Ablaufumgebung und Dienste für die Komponenten an, indem er die Aufrufe ihrer Clients abfängt > bereitgestellte Dienste > Nebenläufigkeit, Remoting, Transaktionen, EIS-Integration > Environment-Zugriff, Ressource-Pooling, Sicherheit, Persistence 3 Das Problem • um Dienste vom Container zu benutzen, mußte man umfangreiche Container-API implementieren statt sich auf die Anwendung zu konzentrieren > > > > > > EJBHome interface EJBObject interface EnterpriseBean interfaces JNDI interfaces Deployment descriptor … • die Vorteile der Verwendung von EJB mußten durch ein komplexes Programmiermodell erkauft werden 4 Beispiel: EJB 2.x Interfaces // EJB 2.x Stateless Session Bean: Remote Interface public interface Calculator extends EJBObject { } int add (int a, int b) throws RemoteException; int subtract (int a, int b)throws RemoteException; // EJB 2.x Stateless Session Bean: Home Interface public interface CalculatorHome extends EJBHome { } 5 Calculator create() throws CreateException, RemoteException; Beispiel: EJB 2.x Implementation // EJB 2.x Stateless Session Bean Implementation public class CalculatorBean implements SessionBean { private SessionContext ctx; public void setSessionContext(SessionContext s) { ctx = s; } public void ejbCreate() { } public void ejbActivate () { } public void ejbPassivate () { } public void ejbRemove () { } public int add (int a, int b) { return a + b; } public int subtract (int a, int b) { return a – b; } } 6 Beispiel: EJB 2.x Descriptor <session> <ejb-name>CalculatorEJB</ejb-name> <home>com.example.CalculatorHome</home> <remote>com.example.Calculator</remote> <ejb-class>com.example.CalculatorBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> </session> ... 7 Der Ansatz von EJB 3.0 • mehr Arbeit wird vom Container getan, weniger vom Entwickler • die Schnittstelle zwischen Container und Entwickler begünstigt den Entwickler, nicht den Container > > > > Bean bestimmt ihre Bedürfnisse durch Metadaten Implementierung von Container Interfaces entfällt Deployment Descriptor nicht mehr notwendig vernünftige Defaults, Konfiguration nur der Ausnahmen • der Container stellt nur die von der Bean angeforderten Dienste zur Verfügung 8 Agenda • Motivation • EJB 3.0 Programmier-Modell • Java Persistence API (JPA) • Aktueller Status und Zusammenfassung 9 Bean Klassen • Session Beans und Message-Driven Beans sind einfache Java Klassen – Rückkehr der POJOs! > sie müssen nicht Container-Interfaces implementieren > der Bean Typ wird durch Annotations oder XML bestimmt • Annotations der Bean Klasse > @Stateless, @Stateful, @MessageDriven • EJB 2.x Entity Beans unverändert > nicht zu empfehlen, vermutlich künftig 'deprecated' > JPA-Entitäten liefern neue Funktionalität > @Entity ist nur auf JPA-Entitäten anwendbar • Business Interfaces sind POJI 10 Beispiel // EJB 3.0 business interface (POJI) @Remote public interface Calculator { int add (int a, int b); int subtract (int a, int b); } // EJB 3.0 stateless session bean (POJO) @Stateless public class CalculatorBean implements Calculator { public int add (int a, int b) { return a + b;} public int subtract (int a, int b) { return a – b;} } 11 Zugriff auf die Environment • Über Dependency Injection oder einfaches Look-Up > die Benutzung der JNDI Interfaces nicht mehr nötig • die Abhängigkeiten der Komponente werden über Annotations oder XML ausgedrückt • bei Anwendung der Annotations auf: > Instanz Variable oder Property-Setter => Injection > Bean Klasse => dynamisches Look-Up 12 Dependency Injection • die Bean Instanz wird zum Zeitpunkt ihrer Erstellung mit Referenzen auf Environment-Ressourcen versorgt • die Reihenfolge der Injections ist nicht definiert • optional wird die @PostConstruct-Methode aufgerufen, nachdem die Injection abgeschlossen ist 13 Beispiel // EJB 3.0 Stateless Session Bean: Bean Class // Data access using injection and Java Persistence API @Stateless public class PayrollBean implements Payroll { @PersistenceContext EntityManager em; public void setSalary(int empId,int salary) { em.find(Employee.class,empId).setSalary(salary); } ... } 14 Beispiel // EJB 3.0 Stateless Session Bean: Bean Class // Data access using dynamic lookup and JPA @PersistenceContext(name=“PayrollPC“) @Stateless public class PayrollBean implements Payroll { @Resource SessionContext ctx; public void setSalary(int empId,int salary) { EntityManager em = ctx.lookup(“PayrollPC“); em.find(Employee.class,empId).setSalary(salary); } ... 15 } Vereinfachung der Client-Ansicht • durch Verwendung von Dependency Injection • einfache Business Interface Ansicht • kein Home interface • keine RemoteExceptions • keine Notwendigkeit andere checked Exceptions abzufangen 16 Beispiel // EJB 3.0: Client View @EJB Payroll payroll; // Use the bean payroll.setSalary(1234, 4000); 17 Transaktionen • Container-managed transactions > sind default • Bean-managed transactions > die Komponente verwendet UserTransaction API • Annotation: @TransactionManagement > mit Werten CONTAINER (default) oder BEAN > die Annotation wird auf die Bean Klasse angewendet • Annotation: @TransactionAttribute > Werte: REQUIRED (default), REQUIRES_NEW, MANDATORY, NEVER, NOT_SUPPORTED, SUPPORTS 18 Beispiel // EJB 3.0: Container-managed transactions @Stateless public class PayrollBean implements Payroll { @TransactionAttribute(MANDATORY) public void setSalary(int empId,int salary) { ... } public int getSalary(int empId) { ... } } 19 Beispiel // EJB 3.0: Bean-managed transactions @TransactionManagement(BEAN) @Stateless public class PayrollBean implements Payroll { @Resource UserTransaction utx; @PersistenceContext em; public void setSalary(int empId,int salary) { utx.begin(); em.find(Employee.class,empId).setSalary(salary); utx.commit(); } ... 20 } Interceptors • ermöglichen AOP in EJB-Anwendungen • können für Session und Message-Driven Beans definiert werden • das Aufruf-Modell: “around” methods > umschliesst den Aufruf von Business-Methoden > kann Aufruf-Parameter und Ergebnisse manipulieren • können auf EJB-Modul-, Bean-, oder MethodenEbene definiert werden 21 Deployment Descriptors • verfügbar als Alternative zu Annotations • benötigt für Metadaten auf Anwendungs-Ebene > z.B. default Interceptoren • können benutzt werden um manche Annotations zu überschreiben • nützlich für hinausgeschobene Konfigurationen > z.B. für die Festlegung der Security-Attribute • nützlich für diverse Konfigurationen > Java Persistence API O/R mapping • können 'sparse', vollständig und/oder durch Annotations ergänzt werden 22 Agenda • Motivation • EJB 3.0 Programmier-Modell • Java Persistence API (JPA) • Aktueller Status und Zusammenfassung 23 Hintergrund • JPA ist Teil von JSR-220 (EJB 3.0) • angefangen als Vereinfachung für Entity Beans > ausgeweitet als Persistenz-Technologie für POJOs • erweitert um Java EE und Java SE Umgebungen zu unterstützen • Referenz-Implementierung ist Bestandteil vom Projekt GlassFish > Oracle TopLink Essentials > Oracle hat sich Sun bei der Leitung der Spezifikation in Juni 2005 angeschlossen 24 Hauptmerkmale • POJO-basiertes Persistenz-Modell > einfache Java Klassen, keine Komponenten • Unterstützung für umfangreiche Domain-Modellierung > Vererbung, Polymorphismus, etc. • erweiterte Abfragesprache • standardisiertes O/R Mapping > unter Verwendung von Annotations und/oder XML • verwendbar in Java EE und Java SE Umgebungen • Unterstützung für pluggable Persistenz-Provider 25 Entitäten • Plain old Java objects > > > > erstellt mit new keine Anforderungen für Interfaces besitzen persistente Identität können persistenten und nicht-persistenten Zustand haben > einfache Typen (primitive, Wrappers, enums, serializables) > zusammengesetzte abhängige Typen (z.B. Addresse) > nicht-persistenter Zustand(transient oder @Transient) > serializable – verwendbar als Detached Objects > eliminieren den Bedarf an Data Transfer Objects(DTOs) 26 Beispiel @Entity public class Customer implements Serializable { @Id protected Long id; protected String name; @Embedded protected Address address; protected PreferredStatus status; @Transient protected int orderCount; public Customer() {} public Long getId() {return id;} protected void setId(Long id) {this.id = id;} public String getName() {return name;} public void setName(String name) {this.name = name;} 27 } Persistence Context • eine Menge von Entitäten, die von einem EntityManager verwaltet werden • eindeutige Entity-Instanz für jede persistente Identität • alle Entity-Instanzen gehören zur selben Persistence Unit(PU), abgebildet auf dieselbe DB > die PU ist eine Einheit für Packaging und Deployment • EntityManager API ist die Schittstelle zum Persistence Context und Persisitence Provider > Lebenszyklus-Verwaltung von Entitäten, Suche von Entitäten nach Id, Factory für Queries 28 Entity Lifecycle • new > Erstellung einer neuen Entity-Instanz > die Entität ist noch nicht managed oder persistent • persist > die Entität wird gemanaged > wird in der DB persistiert, wenn die Transaktion committed wird • remove > die Entität wird glöscht > wird von der DB gelöscht, wenn die Transaktion committed wird • refresh > der Zustand der Entität wird von der DB geladen • merge 29 > Zustand einer Detached-Entity zurück auf Managed-Entity kopieren Beispiel @Stateless public class OrderManagementBean implements OrderManagement { … @PersistenceContext EntityManager em; … public Order addNewOrder(Customer customer, Product product){ Order order = new Order(product); customer.addOrder(order); em.persist(order); return order; } } 30 Java Persistence Query Language • eine Erweiterung von EJB QL > wie EJB QL, SQL-ähnlich • hinzugefügte Funktionalität > > > > > > > 31 Projektions-Liste (SELECT Klausel) explizite JOINS Sub-Queries GROUP BY, HAVING EXISTS, ALL, SOME/ANY UPDATE, DELETE Operationen ... Queries • statische Queries > definiert mit Annotaions oder XML > Annotations: @NamedQuery, @NamedNativeQuery • dynamische Queries > der Query-String wird zur Laufzeit festgelegt • man kann JPA-Queries oder SQL verwenden • es gibt Benannte- oder Positions-Parameter • EntityManager ist Factory für Query Objekte > createNamedQuery, createQuery, createNativeQuery • Query-Methoden zur Kontrolle von Ergebnissen, Seitenumbruch, Flush-Mode 32 Dynamische Abfrage @PersistenceContext EntityManager em; … public List findByZipcode(String personType, int zip) { return em.createQuery ( “SELECT p FROM ” + personType + “ p WHERE p.address.zip = :zipcode”) .setParameter(“zipcode”, zip) .setMaxResults(20) .getResultList(); } 33 Object/Relational Mapping • • • • bildet den persistenten Objektzustand in relationale DB ab Abbildung von Relationen zu anderen Entitäten Mapping-Metadaten können Annotations und/oder XML sein Annotations > logisch—Object Modell (@OneToMany, @Id, @Transient) > physisch—DB Tabellen und Spalten (@Table, @Column) • XML > Elemente für das Mapping von Entitäten und ihre Felder/Properties • Regel für Default-Werte von DB Tabellen- und Spalten-Namen 34 Object/Relational Mapping • Zustand oder Relationen können EAGER oder LAZY geladen werden > LAZY ist ein Hinweis, dass der Container das Laden bis zum Zugriff auf die Felder/Relationen zurückstellt > EAGER verursacht, dass die Felder/Relationen geladen werden sobald die referenzierende Entität geladen wird • Kaskadierung von Operationen auf referenzierte Entitäten > kann pro Relation über @Cascade festgelegt werden > kann auch global im Mapping File definiert werden 35 Abbildung von Entity-Relationen • Unterstützung aller gängiger Beziehungen > @ManyToOne, @OneToOne — zu einzelnen Entitäten > @OneToMany, @ManyToMany — Sammlung von Entitäten • bidirektionale Beziehungen haben eine Eigentümerund eine Umkehrseite > sie werden von der Anwendung, nicht vom Container verwaltet • Eigentümer-Seite bestimmt das physische Mapping > legt den Fremdschlüssel fest 36 Beispiel @Entity public class Customer { @Id protected Long id; @OneToMany(mappedBy=“cust”) // reverse side protected Set<Order> orders = new HashSet(); public Set<Order> getOrders() {return orders;} public void addOrder(Order order) { getOrders().add(order); order.setCustomer(this);} ... } 37 @Entity public class Order { @Id protected Long id; @ManyToOne protected Customer cust; // owning side public Customer getCustomer() {return cust;} public void setCustomer(Customer cust) {this.cust = cust;} ... } OneToMany/ManyToOne Mapping @Entity public class Customer { @Id int id; ... CUSTOMER ID ... @OneToMany(mappedBy=“cust”) Set<Order> orders; } ORDER @Entity public class Order{ @Id int id; ... @ManyToOne Customer cust; 38 } ID ... CUST_ID Vererbung • Entittäten können vererben von > anderen Entitäten — konkret oder abstrakt > Mapped Superklassen > für gemeinsamen Zustand und Annotations > Klassen, die keine Entitäten sind — konkret oder abstrakt • Abbildung der Vererbungs-Hierarchie > SINGLE_TABLE > JOINED > TABLE_PER_CLASS 39 Objektmodell Animal id: int name: String LandAnimal legCount: int 40 AirAnimal wingSpan: int Zugehöriges Datenmodell • Single table: ANIMAL ID DISC NAME LEG_COUNT WING_SPAN ANIMAL ID LAND_ANIMAL • Joined: ID • Table per Class: 41 NAME LEG_COUNT AIR_ANIMAL ID LAND_ANIMAL ID NAME LEG_COUNT WING_SPAN AIR_ANIMAL ID NAME WING_SPAN Agenda • Motivation • EJB 3.0 Programmier-Modell • Java Persistence API (JPA) • Aktueller Status und Zusammenfassung 42 Aktueller Status • Final Release von EJB 3.0 in Mai 2006 • Java EE 5 Referenz-Implementierung in Mai 2006 > Teil vom Open-Source Projekt GlassFish • EJB 3.0 Preview-Container von Oracle, JBoss, BEA, SAP • wachsende Unterstützung von Tools > NetBeans 5.5, Eclipse, IntelliJ, JBuilder, ... • Hauptprobleme beseitigt, Bedarf an Frameworks, die Java EE unterstützen, nimmt ab 43 Zusammenfassung EJB 3.0 • deutliche Vereinfachung der EJB-Technologie für Entwickler > > > > Beans sind POJOs mit POJIs APIs neu konzipiert um benutzerfreundlich zu sein leichter Zugang zu Container-Diensten und Umgebung Deployment Descriptors sind verfügbar aber nicht zwingend notwendig • EJB 3.0 Komponenten sind kompatibel mit bestehenden J2EE-Komponenten • mächtige und leicht verwendbare Funktionalität 44 Zusammenfassung JPA • Entitäten sind einfache Java Klassen > leicht zu erstellen und intuitiv zu benutzen > können zu anderen Tiers und Servern übertragen werden • EntityManager > einfaches API zur Verwaltung von Entitäten > verwendbar in Java EE und Java SE Umgebungen • Standardisierung > O/R Mapping kann Annotations oder XML bentutzen > benannte, statische und dynamische Query-Definitionen > SPI für pluggable Persistence Provider 45 Links • Spezifikationen > http://jcp.org/en/jsr/detail?id=220 • JavaOne 2006 Sessions > alle PDFs zum Thema Java EE gepackt in http://java.sun.com/javaone/sf/2006/sessions/java_ee.zip > TS-3396, TS-3395, TS-9056, TS-1365, TS-1887 • Glassfish: Java EE 5 Referenz-Implementierung > http://glassfish.dev.java.net • Java Application Platform SDK > http://java.sun.com/javaee/downloads/index.jsp 46 EJB 3.0 EINFÜHRUNG UND STATUS Peter Doschkinow [email protected] Was fällt auf? • eine Reihe von Schwachstellen > 3 Klassen und ein Deployment Descriptor > die Interfaces sind störend > create-Methode kreiert nicht > remove-Methode löscht nicht > alle javax.ejb.SessionBean Methoden sind unnötig > der Anwendungs-Code wird unübersichtlich > der Deployment Descriptor enthält redundante Informationen • das Ziel von EJB 3.0 ist diese Probleme zu beseitigen! 48 Business Interfaces • einfache Java Interfaces (POJI) ● keine Abhängigkeit mehr von EJBObject, EJBHome • entweder für Local- oder Remote-Zugriff > Local-Zugriff ist default > Remote-Zugriff durch Annotation oder Deployment Descriptor > Remote-Methoden müssen nicht RemoteException aufwerfen • Annotations: @Remote, @Local, @WebService > kann für die Bean-Klasse oder Interface spezifiziert werden • eine Bean Klasse kann mehrere Business Interfaces haben > sie müssen dann explizit als solche durch Local/Remote-Annotations oder Deployment Descriptor ausgewiesen sein 49 Annotations für EnvironmentZugriff • @Resource ● für Connection Factories, Environment-Variablen, Topics/Queues, EJBContext, UserTransaction, etc. • @EJB > für EJB Business Interfaces oder EJB Home Interfaces • @PersistenceContext > für Container-managed EntityManager • @PersistenceUnit > für EntityManagerFactory 50 Transaktionsattribute container managed transactions • die Annotations werden auf die Bean Klasse und/oder ihre Methoden angewandt ● ● Anwendung auf die Bean Klasse gilt für alle Methoden, falls nicht auf Methoden-Ebene überschrieben Anwendung auf eine Methode gilt nur für die Methode • Annotation: @TransactionAttribute > Werte: REQUIRED (default), REQUIRES_NEW, MANDATORY, NEVER, NOT_SUPPORTED, SUPPORTS 51 Lifecycle Callbacks • EJB 2.1 postuliert EnterpriseBean Interfaces • EJB 3.0 ermöglicht die Angabe nur von Events, die man benötigt • Annotations: > > > > @PostConstruct @PreDestroy @PostActivate @PrePassivate • Annotations können auf Methoden einer Bean- oder Interceptor Klasse angewandt werden • dieselbe Methode kann für verschiedene Lifecycle Events dienen 52 Beispiel // EJB 3.0: Event Notification @Stateful public class TravelBookingBean implements TravelBooking { @PostConstruct @PostActivate private void connectToBookingSystem() {...} @PreDestroy @PrePassivate private void disconnectFromBookingSystem() {...} ... } 53 Interceptoren • Default Interceptoren > angewendet auf alle Business-Methoden von EJBs im EJB-Modul > festgelegt im Deployment Descriptor • Interceptoren auf Bean-Ebene > greifen auf alle Business-Methoden der Bean Klasse • Interceptoren auf Methoden-Ebene > angewendet nur auf eine spezifische Business-Methode • flexible Anpassungen in Bezug auf die Reihenfolge und Anwendung der Interceptoren möglich 54 Identität einer Entity • jede Entität hat eine persistente Identität > abgebildet auf den Primary Key in der DB • kann einfachen Typ haben > Annotations > @Id — für einzelne Felder/Properties in der Entity Klasse > @GeneratedValue — der Wert wird automatisch erzeugt • kann Benutzer-definierten Typ haben > Annotations > @EmbeddedId — für ein Feld/Property > @IdClass — entspricht mehreren Id Felder/Properties • definiert an der Wurzel einer Entity-Hierarchie 55 Entity Lifecycle New per sis t() update Managed remove() Removed 56 nd e PC Detached () rge e m Relationen zwischen Entitäten • One-to-one, one-to-many, many-to-many, many-toone Relationen zwischen Entitäten > Unterstützung für Collection, Set, List, Map Typen • können unidirektional oder bidirektional sein > bidirektionale Relationen werden von der Anwendung, nicht vom Container verwaltet > bidirektionale Relationen haben eine Eigentümer- und eine Umkehr-Seite 57 Einfache Mappings • direkte Abbildung von Felder/Properties auf Spalten • anwendbar für alle einfache Java Typen > primitive Typen, Wrapper-Typen, Date, Serializable, byte[ ], ... • benutzt in Verbindung mit @Column • können Default-Werte überschreiben 58 Simple Mappings @Entit public class Customer { y @Id int id; String name; @Column(name=“CRED IT”) int c_rating; @Lo b Image photo; } 59 CUSTOMER ID NAME CREDIT PHOTO Simple Mappings <entity class=“com.acme.Customer”> <attributes> <id name=“id”/> <basic name=“c_rating”> <column name=“CREDIT”/> </basic> <basic name=“photo”><lob/></basic> </attributes> </entity> 60 Many-to-Many Mapping @Entity public class Customer { ... @ManyToMany @JoinTable(table=“CUST_PHONE”), joinColumns=@JoinColumn(name=“CUST_ID”), inverseJoinColumns=@JoinColumn(name=“PHON_ID”)) Collection<Phone> phones; } PHONE CUSTOMER ID ... CUST_PHONE CUST_ID 61 PHON_ID ID ... Many-to-Many Mapping <entity class=“com.acme.Customer”> <attributes> ... <many-to-many name=“phones” <join-table name=“CUST_PHONE”> <join-column name=“CUST_ID”/> <inverse-join-column name=“PHON_ID”/> </join-table> </many-to-many> </attributes> </entity> 62 Vererbung von @MappedSuperclass public class Person { MappedSuperclass @Id protected Long id; protected String name; @Embedded protected Address address; } @Entity public class Customer extends Person { @Transient protected int orderCount; @OneToMany protected Set<Order> orders = new HashSet(); } @Entity public class Employee extends Person { @ManyToOne protected Department dept; } 63 Persistenz in Java SE • keine Deployment-Phase > die Anwendung muß über ein “Bootstrap API” eine EntityManagerFactory bekommen • verwendet Ressource-Local EntityManagers > die Anwendung benutzt lokale Transaktionen, die vom EntityManager bereitgestellt werden • neuer Persistence Context für jeden neuen EntityManager > keine Weiterleitung vom Persistence Context(wie im EJB- Container) 64 Beispiel public class SalaryChanger { public static void main(String[] args) { EntityManagerFactory emf = Persistence .createEntityManagerFactory(“HRSystem”); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Employee emp = em.find( Employee.class, new Integer(args[0])); emp.setSalary(new Integer(args[1])); em.getTransaction().commit(); em.close(); emf.close(); } } 65