Gliederung 1. Software-Komponenten: Grundlegende Begriffe 2. Systematischer Entwicklungsprozess für Komponenten-Software mit UML 3. Java-Komponenten-Technologien 3.1 JavaBeans-Technologie 3.2 Web-Komponenten mit Java 3.3 Enterprise JavaBeans-Technologie 4. Komponentenspezifikation 5. Komponententechnologien im Vergleich 5.1 Microsoft COM/DCOM/COM+ 5.2 CORBA Component Model 5.3 Vergleich der Komponentenstandards 6. Zusammenfassung und Ausblick Technische Universität Dresden Prof. Hußmann Softwarekomponenten Kapitel 3 Java-Komponenten-Technologien 3.3 Enterprise JavaBeans-Technologie – EJB-Architektur – Session Beans Wiederholung; Rollen in der EJB-Entwicklung – Entity Beans – Transaktionsbehandlung, Sicherheit – Message-Driven Beans Technische Universität Dresden Prof. Hußmann Seite 1 Softwarekomponenten Zweck der EJB-Technologie: Aufgabenteilung • "Vertrag" (programming contract) für den Hersteller der ServerKomponenten: – Einhalten von Programmier-Konventionen – Bereitstellung der Software in gebrauchsfertiger Verpackung » z.B. JAR-Archive in verschiedenen Varianten – Nutzung von Infrastrukturdiensten des Containers » z.B. Container-Managed Persistence – Berücksichtigung von Container-Aktionen » z.B. Activate-/Passivate-Methoden (Hook-Methoden) – "Verstecken" der Client-Systeme und der Infrastruktur • "Vertrag" für den Programmierer der Client-Anwendung: – Programmieren "gegen" abstrakte Schnittstellen » Objekt-Schnittstelle (Remote Interface) » Verwaltungs-Schnittstelle (Home Interface) – "Verstecken" der Implementierungsdetails und der Infrastruktur Technische Universität Dresden Prof. Hußmann Softwarekomponenten Wiederholung: EJB Class "CounterEJB" (1) import javax.ejb.SessionBean; import javax.ejb.SessionContext; public class CounterEJB implements SessionBean { private private private private int count; int startValue; int incrValue; boolean enabled; public void ejbCreate() { startValue = 0; incrValue = 1; reset(); enabled = true; } public int getCurrent () { return count; } public int getStartValue () { return startValue; } ... Technische Universität Dresden Prof. Hußmann Seite 2 Sicht: Hersteller von Server-Komponenten Softwarekomponenten Wiederholung: EJB Class "CounterEJB" (2) ... public void reset () { count = startValue; } public void count () { if (enabled) { count += incrValue; } } // EJB Lifecycle Callback Methods public public public public void void void void ejbRemove() {} ejbActivate() {} ejbPassivate() {} setSessionContext(SessionContext sc) {} } Sicht: Hersteller von Server-Komponenten Technische Universität Dresden Prof. Hußmann Softwarekomponenten Wiederholung: Schnittstellen für Client public interface Counter extends EJBObject { public int getCurrent() throws RemoteException; public int getStartValue() throws RemoteException; public void setStartValue(int value) throws RemoteException; public int getIncrValue() throws RemoteException; public void setIncrValue(int value) throws RemoteException; public boolean getEnabled() throws RemoteException; public void setEnabled(boolean value) throws RemoteException; public void reset() throws RemoteException; public void count() throws RemoteException; } public interface CounterHome extends EJBHome { Counter create() throws RemoteException, CreateException; } Sicht: Hersteller von Client-Software Technische Universität Dresden Prof. Hußmann Seite 3 Softwarekomponenten Wiederholung: Client-Programm import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; ... try { Context ictx = new InitialContext(); Object ctrRef = ictx.lookup("JNDI Name"); CounterHome ctrHome = (CounterHome)PortableRemoteObject.narrow (ctrRef,CounterHome.class); Counter counter = ctrHome.create(); ... counter.setStartValue(...); counter.count(); ... } catch (Exception ex) { System.err.println("Error when connecting to server"); ex.printStackTrace(); } Sicht: Hersteller von Client-Software Technische Universität Dresden Prof. Hußmann Softwarekomponenten "Offizielles" EJB-Rollenmodell • EJB-2.0-Standard definiert sieben verschiedene Rollen: – Enterprise Bean Provider » Hersteller flexibler, wiederverwendbarer Server-Komponenten – Application Assembler » Erstellung von Anwendungen aus EJBs und anderen Komponenten – Deployer » Anpassung und Installation einer bestimmten Anwendung für Ausführungsumgebung (incl. EJB Server und Container) – EJB Server Provider & EJB Container Provider » Bereitstellung von Server-Software und Werkzeugen » vgl. Sun Referenz-Implementierung für J2EE-Server – Persistence Manager Provider » Bereitstellung von persistenter Speicherung für Entity Beans – System Administrator » Konfiguration, Beobachtung, Anpassung im laufenden Betrieb Technische Universität Dresden Prof. Hußmann Seite 4 Softwarekomponenten Kapitel 3 Java-Komponenten-Technologien 3.3 Enterprise JavaBeans-Technologie – EJB-Architektur – Session Beans Wiederholung; Rollen in der EJB-Entwicklung – Entity Beans – Transaktionsbehandlung, Sicherheit – Message-Driven Beans Achtung: Dieser Abschnitt gibt verbesserte und detailliertere Fassungen der Folien Nr. 29-33 aus der letzten Vorlesung! Technische Universität Dresden Prof. Hußmann Softwarekomponenten Entity Beans • Aus der Sicht eines Client-Programms: – Entity Bean = Komponente, die eine objektorientierte Sicht auf eine oder mehrere Entitäten bereitstellt, die in persistentem (dauerhaftem) Speicher abgelegt werden. – Sehr ähnliche Konventionen wie für Session Beans • Container-Managed Persistence (CMP): (siehe folgendes Beispiel) – Volle Ausnutzung der möglichen Aufgabenteilung – Abbildung auf persistente Speicherung verborgen vor dem Entwickler der Server-Komponenten (EJB Provider) (Hier: EJB 2.0-Standard) • Bean-Managed Persistence (BMP): – Persistenz als Bestandteil der Server-Komponenten – Verwendung traditioneller Hilfsmittel (z.B. eingebettetes SQL) Technische Universität Dresden Prof. Hußmann Seite 5 Softwarekomponenten Beispiel: Remote Interface "Account" import java.rmi.RemoteException; import javax.ejb.EJBObject; public interface Account extends EJBObject { int getAccountNo() throws RemoteException; int getBalance() throws RemoteException; String getOwner() throws RemoteException; void credit(int amount) throws RemoteException; void debit(int amount) throws RemoteException, InsufficientFundsException; } public class InsufficientFundsException extends Exception { public InsufficientFundsException() {} } • Eine Entity-Bean-Klasse repräsentiert eine Sicht auf einen Datenbestand. – Bevorzugt Getter- und Setter-Methoden – Objektorientiertes Prinzip: auch fachliche Methoden definiert • Hilfsklassen z.B. für fachliche Ausnahmesituationen Technische Universität Dresden Prof. Hußmann Softwarekomponenten Granularität von Entity Beans • Eine Instanz einer Entity Bean umfaßt mindestens einen Datensatz, kann aber auch mehrere Datensätze kapseln. • Empfehlenswert: – Kapselung eines (existenz-)unabhängigen Objekts mit davon abhängigen Objekten (dependent objects) – "Granularität" von EJBs nicht zu klein wählen! • Beispiel: Bestellung Order 1..* 1 OrderLine 1 * Product – Order und Product sind unabhängig voneinander – OrderLine ist abhängig von Order und Product – Eine Entity Bean für Order und OrderLine verwenden ! Technische Universität Dresden Prof. Hußmann Seite 6 Softwarekomponenten Beispiel: Home Interface "AccountHome" import javax.ejb.EJBHome; import java.rmi.RemoteException; import javax.ejb.CreateException; import javax.ejb.FinderException; import java.util.Collection; public interface AccountHome extends EJBHome { Account create(String owner, int accountNo) throws RemoteException, CreateException; Account findByPrimaryKey(Integer pk) throws RemoteException, FinderException; Collection findByOwner(String owner) throws RemoteException, FinderException; } • Verwaltung großer Mengen von Entity-Bean-Instanzen – Diverse Such-Methoden; verpflichtend findByPrimaryKey – Löschen von Instanzen über Methoden von javax.ejb.EJBHome • Ergebnis einer Suchmethode – Remote Interface Klasse, falls immer einelementig – java.util.Collection (von Remote Interface), falls mehrelementig • "Home Methods": Fachliche Methoden, die auf allen Instanzen arbeiten Technische Universität Dresden Prof. Hußmann Softwarekomponenten Objektidentität und Primärschlüssel • Identität über Home Interface und Primärschlüssel: – Wenn zwei Objekte über das gleiche Home-Interface zugänglich sind und den gleichen Primärschlüssel tragen, gelten sie als identisch. – Der Primärschlüssel-Wert eines Objektes darf sich über seine Lebenszeit nicht verändern. • Vordefinierte Methode in EJBObject: boolean isIdentical(EJBObject o) – Folgende Verfahren stellen nicht (immer) die Identität zweier Objekte fest: » Vergleich der Referenzen mit "==" » Vergleich der Objektidentität mit equals() – Container müssen Objektinstanzen entfernen, erzeugen, umwidmen etc. können, unabhängig von der fachlichen Identität. Technische Universität Dresden Prof. Hußmann Seite 7 Softwarekomponenten Beispiel: EJB Class mit CMP "AccountEJB" (1) import javax.ejb.EntityBean; import javax.ejb.EntityContext; public abstract class AccountEJB implements EntityBean { // Container-managed persistent fields public abstract int getAccountNo(); public abstract void setAccountNo(int no); public abstract String getOwner(); public abstract void setOwner(String owner); public abstract int getBalance(); public abstract void setBalance(int bal); Persistentes Feld "accountNo" // Constructor public AccountEJB() {} public Integer ejbCreate(String owner, int accountNo) { setAccountNo(accountNo); Initialisierung setOwner(owner); bei Erzeugung setBalance(0); return null; } ... Typ des Primärschlüssels als Resultat; Konvention (bei CMP): Rückgabewert "null" Technische Universität Dresden Prof. Hußmann Softwarekomponenten Deployment-Information zur Persistenz Technische Universität Dresden Prof. Hußmann Seite 8 Softwarekomponenten Wahl von Primärschlüssel-Klassen • Einfache Primärschlüssel: – java.lang.String, java.lang.Integer etc. – Konversion von int nach Integer etc. vom Container unterstützt • Zusammengesetzte Primärschlüssel: – Eigene Hilfsklasse definieren (z.B. AccountPK) – – – – Reine Datenstrukturklasse, Schlüsselbestandteile als öffentliche Felder Feldnamen identisch zu Namen der entsprechenden persistenten Felder hashCode() und equals() implementiert z.B.: public AccountPK { public Integer accountNo; public String owner; ... } Technische Universität Dresden Prof. Hußmann Softwarekomponenten Remote Interface und persistente Felder public interface Account extends EJBObject { Remote public int getAccountNo() throws RemoteException; Interface public int getBalance() throws RemoteException; public String getOwner() throws RemoteException; ... } public abstract class AccountEJB implements EntityBean { public abstract int getAccountNo(); public abstract void setAccountNo(int no); Persistente public abstract int getBalance(); Felder in public abstract void setBalance(int bal); EJB Class public abstract String getOwner(); public abstract void setOwner(String owner); ... } • Implementierung der Get- und Set-Methoden durch Container • Offenlegung (exposition) von Get- und Set-Methoden im Remote Interface – Meist nur Auswahl offengelegt (hier z.B. "read-only") – Set-Methode für Primärschlüssel (hier setAccountNo) niemals offenlegen ! Technische Universität Dresden Prof. Hußmann Seite 9 Softwarekomponenten Beispiel: EJB Class mit CMP "AccountEJB" (2) … public void ejbPostCreate(String owner, int accountNo) {} public void credit(int amount) { Nichttrivial nur, wenn eigene setBalance(getBalance() + amount); Objektidentität verarbeitet wird. } public void debit(int amount) throws InsufficientFundsException { int oldBalance = getBalance(); if (amount > oldBalance) throw new InsufficientFundsException(); else setBalance(oldBalance - amount); } Speichern des Entity Context // EJB Lifecycle Callback Methods meist sinnvoll public void ejbRemove() {} (Zugang zu weiterer Information) public void ejbActivate() {} public void ejbPassivate() {} public void setEntityContext(EntityContext ec) {} public void unsetEntityContext() {} public void ejbLoad() {} public void ejbStore() {} Trivial nur im Falle der } Container Managed Persistence! Technische Universität Dresden Prof. Hußmann Softwarekomponenten Und wer kümmert sich um die Datenbank? • Quellcode der Entity Bean ist völlig unabhängig vom unterliegenden Persistenz-Mechanismus. • "Deployment"-Zeitpunkt: Festlegung der konkreten Datenbank – Sun Referenzumgebung: » Einfaches relationales Datenbanksystem "Cloudscape" » Vordefinierte Datenbanken und JNDI-Namen – Notwendige Informationen im Deployment Tool / Descriptor Technische Universität Dresden Prof. Hußmann Seite 10 Softwarekomponenten Und wer implementiert die "find"-Methoden? • Methoden findByPrimaryKey und findByOwner – tauchen im Quellcode der EJB Class nicht auf (da CMP verwendet)! – Aufruf der Methoden in der Referenzimplementierung: Fehler, z.B.: "javax.ejb.EJBException: No SQL statement for findByPrimaryKey" • Implementierungen der "find"-Methoden bei CMP: – Bei relationalen Datenbanken als Persistenzmechanismus: » Abbildung auf SQL-Abfragen – findByPrimaryKey: » automatisch erzeugbar aus den gegebenen Informationen – findByOwner (und alle anderen benutzerdefinierten find-Methoden): » Spezifikation mittels Deployment-Werkzeug in der plattformunabhängigen Sprache "EJB-QL" (EJB-Query Language) » Ablage im Deployment Descriptor (also "mit verpackt") » Übersetzung meist nach SQL, ggf. auch andere Behandlung je nach Laufzeitumgebung Technische Universität Dresden Prof. Hußmann Softwarekomponenten Beispiel: Erzeugung von SQL-Code Gleicher Mechanismus für Manipulation von Tabellen und findByPrimarykey() Technische Universität Dresden Prof. Hußmann Seite 11 Softwarekomponenten Beispiel: EJB-QL für "findByOwner" FROM Account o WHERE o.owner = ?1 Technische Universität Dresden Prof. Hußmann Softwarekomponenten Enterprise Java Beans Query Language (EJB QL) • Abfragen über Entity Beans mit Container-Managed Persistence • Stark angelehnt an SQL, aber: – optimierbar bei Übersetzung auf SQL – portierbar jenseits proprietärer SQL-Dialekte, sogar jenseits RDBMS • Syntax: [ <select_clause> ] <from_clause> [ <where_clause> ] – <select_clause>: unnötig, wenn <from_clause> nur eine freie Variable enthält – <from_clause>: » Navigation über Referenzen (d.h. über Kollektionen): FROM OrderBean o, l IN o.lineItems » Navigation zu entfernten Objekten: =>-Operator – <where_clause>: » Eingabeparameter: ?n für n-ten Parameter (Anfang bei 1) » Arithmetische Ausdrücke, Bereiche, Mustervergleich von Zeichenreihen, ... Technische Universität Dresden Prof. Hußmann Seite 12 Softwarekomponenten Client-Programm für Account EJB (Auszug) import javax.naming.Context; import javax.naming.InitialContext; import java.rmi.RemoteException; import javax.rmi.PortableRemoteObject; public class SimpleAccountClient { private static void printAccount(Account acc) throws RemoteException { System.out.println("Account no "+acc.getAccountNo()+" status "+"(owner = "+acc.getOwner()+")"); System.out.println("balance = "+acc.getBalance()); } public static void main(String[] args) { try { Context ictx = new InitialContext(); Object acctRef = ictx.lookup("hh14Account"); AccountHome acctHome = (AccountHome)PortableRemoteObject.narrow (acctRef,AccountHome.class); Account acc1 = acctHome.create("Hussmann",55); printAccount(acc1); acc1.credit(1000); printAccount(acc1); ... }}} Technische Universität Dresden Prof. Hußmann Softwarekomponenten Der Persistenz-Effekt • Mehrfacher Aufruf des einfachen Client-Programms führt zu verschiedenen Ergebnissen: – Erster Aufruf: OK – Weitere Aufrufe: javax.ejb.DuplicateKeyException: Duplicate primary key • Mehrere unabhängige Programme können auf der gleichen Entity Bean arbeiten ! • Entity Beans bleiben sogar über Systemabschaltungen, die meisten "Abstürze" etc. hinweg erhalten ! Technische Universität Dresden Prof. Hußmann Seite 13 Softwarekomponenten Beispiel: Client-Programm zur Abfrage import javax.naming.Context; import javax.naming.InitialContext; import java.rmi.RemoteException; import javax.rmi.PortableRemoteObject; import java.util.*; public class FindAccountClient { private static void printAccount(Account acc) {…} public static void main(String[] args) { try { Context ictx = new InitialContext(); Object acctRef = ictx.lookup("hh14Account"); AccountHome acctHome = (AccountHome)PortableRemoteObject.narrow (acctRef,AccountHome.class); Iterator it = (acctHome.findByOwner("Hussmann")).iterator(); while (it.hasNext()) printAccount((Account)it.next()); } catch (Exception ex) {...} } } Technische Universität Dresden Prof. Hußmann Softwarekomponenten Persistente Beziehungen zwischen EJBs • Eine EJB kann dauerhafte Beziehungen (relationships) zu anderen EJBs und abhängigen Klassen besitzen. – eins-zu-eins, eins-zu-viele, viele-zu viele – einseitig oder beidseitig navigierbar • Prinzipielle Realisierung bei CMP: – Container-managed persistent fields mit Referenzen auf Remote Interface » "container managed relationships" – Für "zu-viele"-Beziehungen: java.util.Collection – Referentielle Integrität und Multiplizität werden vom Container sichergestellt » Auffinden von referenzierten Objekten (auch remote) » Redundante Referenzen in lokalen Feldern werden automatisch synchron gehalten » Typüberprüfung von Kollektionen, die Beziehungen realisieren Technische Universität Dresden Prof. Hußmann Seite 14 Softwarekomponenten Bean Managed Persistence (BMP) • Wichtigste Unterschiede zur Container Managed Persistence: – – – – EJB Class greift direkt auf Speichermedium zu (z.B. Datenbank via JDBC) Datenbankschema muß explizit angelegt werden Aufwendigere Codierung; u.U. schlechtere Portabilität Keine automatische Verwaltung von Beziehungen • Keine Unterschiede in Home/Remote Interface ! – Client-Programm kennt die Realisierungsvariante (CMP/BMP) nicht. • Ausführliches Beispiel zu Bean Managed Persistence: – Sun J2EE Developer's Guide (siehe Vorlesungs-Homepage) Technische Universität Dresden Prof. Hußmann Softwarekomponenten Beispiel: EJB Class mit BMP "AccountEJB" (1) import java.sql.*; import javax.sql.*; import java.util.*; import javax.ejb.*; import javax.naming.*; public class AccountEJB implements EntityBean { Lokale Variablen zum private int accountNo; private String owner; Zwischenspeichern persistenter private double balance; Informationen private Connection con; private String dbName = "java:comp/env/jdbc/AccountDB"; public Integer ejbCreate(String owner, int accountNo) { try { insertRow(accountNo, owner, balance); } catch (Exception ex) { throw new EJBException(); } this.accountNo = accountNo; this.owner = owner; this.balance = 0; Bei BMP: return new Integer(accountNo); Primärschlüsselwert zurückgeben } ... Technische Universität Dresden Prof. Hußmann Seite 15 Softwarekomponenten Beispiel: EJB Class mit BMP "AccountEJB" (2) // Beispiel einer lokalen Hilfsmethode (JDBC) // Hier werden die Daten persistent abgelegt private void insertRow (int accountNo, String owner, int balance) throws SQLException { String insertStatement = "insert into account values ( ? , ? , ? )"; PreparedStatement prepStmt = con.prepareStatement(insertStatement); prepStmt.setInteger(1, accountNo); prepStmt.setString(2, owner); prepStmt.setInteger(3, balance); prepStmt.executeUpdate(); prepStmt.close(); } ... Technische Universität Dresden Prof. Hußmann Softwarekomponenten Beispiel: EJB Class mit BMP "AccountEJB" (3) // Fachliche Methoden (credit, debit) kaum anders als bei CMP: // Hier weggelassen ! public int getAccountNo() { return accountNo; } ... Get- und Set-Methoden des Remote Interface explizit programmiert public Integer ejbFindByPrimaryKey(Integer primaryKey) throws FinderException { boolean result; try { result = selectByPrimaryKey(primaryKey); } catch (Exception ex) { throw new EJBException(); Suchmethoden explizit programmiert } (Ergebnis Primärschlüssel, if (result) { return primaryKey; nicht Remote Interface) } else { throw new ObjectNotFoundException ("Row for id " + primaryKey + " not found."); } } ... Technische Universität Dresden Prof. Hußmann Seite 16 Softwarekomponenten Beispiel: EJB Class mit BMP "AccountEJB" (4) public void setEntityContext(EntityContext context) { try { makeConnection(); } catch (Exception ex) { throw new EJBException(); } } public void ejbLoad() { // ejbStore() analog! try { loadRow(); EJB Lifecycle Methoden } catch (Exception ex) { throw new EJBException(); explizit programmiert } (nicht nur "Callback-Methoden") } ... // makeConnection(), loadRow(): // Explizite Datenbankzugriffe mit JDBC Technische Universität Dresden Prof. Hußmann Softwarekomponenten Life Cycle einer Entity Bean does not exist 1. newInstance() 2. setEntityContext() unSetEntityContext() pooled 1. ejbCreate() 2. ejbPostCreate() ejbActivate() ejbPassivate() ready Technische Universität Dresden ejbFind... ejbSelect... ejbHome... Prof. Hußmann Seite 17 ejbRemove() ejbLoad() ejbStore() fachliche Methoden Softwarekomponenten