J2EE-Praktikum Enterprise JavaBeans Patterns Peter Thiemann Universität Freiburg J2EE-Praktikum, WS2005/2006
Inhalt 1 Designmuster Sitzungsfassade Wertobjekte 2 Implementierungsmuster Geschäftsinterfaces Exceptions Primärschlüssel Große Anfragen
Sitzungsfassade Problem Client hängt direkt von (Entity) Bean Methoden ab Viele externe Zugriffe über Remote Interfaces Client First RemoteHome FirstRemote Second RemoteHome SecondRemote findbyprimarykey() create() method1() method2() method3()
Sitzungsfassade Lösung Einführen einer Sitzungsfassade (session facade) Implementiert durch stateless Session-Bean Externe Zugriffe interne Zugriffe über Local Interfaces Client Session Facade First LocalHome FirstLocal Second LocalHome SecondLocal businessmethod() findbyprimarykey() create() method1() method2() method3()
Sitzungsfassade Diskussion Vereinfachung des Client-Code durch Kapselung eines Geschäftsablaufs Methode im Session-Bean läuft innerhalb einer Transaktion Vermeidung von Remote-Zugriffen (teuer) Vgl. Fassade Designmuster
Wertobjekte Problem Jeder Zugriff auf ein Remote-Interface entspricht einer Remote-Method-Invocation Jede Verwendung von RMI hat Overhead (Netzwerk, Serialisierung) Zugriff auf Komponenten eines Entity-Bean zu teuer Client Bean RemoteHome BeanRemote findbyprimarykey() getfirstname() getlastname() getbirthday()
Wertobjekte Lösung Definition von Wertobjekten: (dependent) value objects Ein Wertobjekt fasst mehrere Komponenten (eines Entity-Bean) zusammen Wertobjekte müssen serialisierbar sein, da sie im Remote-Interface verwendet werden Wertobjekte sind schreibgeschützt, da Änderungen an ihnen nicht persistent sind Client Bean RemoteHome BeanRemote findbyprimarykey() getvalueobject()
Wertobjekte Beispiel public class PersonDO implements java. i o. S e r i a l i z a b l e { private S t r i n g firstname ; private S t r i n g lastname ; private java. u t i l. Date b i r t h d a y ; public PersonDO ( S t r i n g firstname, S t r i n g lastname, java. u t i l. Date b i r t h d a y ) { this. firstname = firstname ; this. lastname = lastname ; this. b i r t h d a y = b i r t h d a y ; public S t r i n g getfirstname ( ) { return this. firstname ; public S t r i n g getlastname ( ) { return this. lastname ; public java. u t i l. Date g e t B i r t h d a y ( ) { return this. b i r t h d a y ;
Wertobjekte Anwendungen/Diskussion Beschleunigung des Remote-Zugriffs auf Entity-Beans (Remote) Datenübermittlung an Session-Beans (Allgemein sollten Remote-Aufrufe möglichst viele Daten auf einmal transportieren) Anstelle eines Entity-Beans, z.b. als Information, die extern veröffentlicht werden soll Beispiel: Buchungsbestätigung Dürfen als Typ von CMP-Feldern verwendet werden Nicht empfehlenswert, da Speicherung in der Datenbank in serialisierter Form Entkopplung von internem Persistenzmodell und Client-Code Unterschiedliche Wertobjekte für verschiedene Sichten auf gleiches Entity-Beans
Geschäftsinterfaces Problem Die Bean-Klasse implementiert nicht das Interface des Beans. Inkonsistenzen werden erst beim Deployment bemerkt. Lösungsansatz: Definition eines Geschäftsinterface Definiert die Geschäftsmethoden des Beans Die Bean-Interfaces und die Bean-Klasse erben vom Geschäftsinterface Inkonsistenzen werden beim Compilieren bemerkt. Nur zu diesem Zweck verwenden!
Geschäftsinterfaces Beispiel / / business i n t e r f a c e import java. rmi. RemoteException ; public interface OrderBI { public i n t getquantity ( ) throws RemoteException ; public void s e t Q u a n t i t y ( i n t q ) throws RemoteException ; public double getpriceperitem ( ) throws RemoteException ; public void setpriceperitem ( double p ) throws RemoteException ; public double g e t T o t a l P r i c e ( ) throws RemoteException ; / / remote i n t e r f a c e import javax. ejb. EJBObject ; public interface OrderRemote extends Order, EJBObject {
Geschäftsinterfaces Beispiel/2 / / bean class public class OrderBean implements Order, EntityBean { private i n t q u a n t i t y ; private double priceperitem ; public i n t getquantity ( ) { return q u a n t i t y ; public void s e t Q u a n t i t y ( i n t q ) { q u a n t i t y = q ; public double getpriceperitem ( ) { return priceperitem ; public void setpriceperitem ( i n t p ) { priceperitem = p ; public double g e t T o t a l P r i c e ( ) { return q u a n t i t y priceperitem ; / / f u r t h e r e n t i t y bean methods
Exceptions RemoteException Methoden von Remote-Interfaces Netzwerkprobleme Abgefangen durch Clienten-Code EJBException Ausgelöst in der EJB-Implementierung (Bean-Klasse) bei schwerwiegenden Problemen Abgefangen durch EJB-Container, nicht durch Entwickler Rollback der aktuellen Transaktion Exceptions der Anwendung Spezielle Ergebnisse von Methodenaufrufen Werden an die Anwendung weitergereicht
Primärschlüssel Primärschlüssel dürfen aus mehreren CMP-Feldern zusammengesetzt werden Separate Schlüsselklasse muss definiert werden Kann Performanceprobleme ergeben: aus Schlüssel muss hashcode() berechnet werden Verwendung als Fremdschlüssel Allgemeine Empfehlungen ein CMP-Feld als Primärschlüssel möglichst mit einfachem Typ darf sich nie ändern (dient als Identifikation eines Tupels) oft systemgenerierter Surrogatschlüssel
Große Anfragen Aufgabe: Naives Anzeigen einer Bücherliste Finder-Methode liefert eine Collection von Entity-Beans Hole Daten durch Abfragen von Wertobjekten Problem: Sehr ineffizient Lösungsvorschlag Umgehen von Entity-Beans Direkte Anfrage an die Datenbank (nur lesend!) Ergebnis: Liste von Wertobjekten Gekapselt in Session-Bean