Gliederung Kapitel 3 Java-Komponenten

Werbung
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
Herunterladen