Portierung ausgewählter Dienste einer proprietären

Werbung
Portierung ausgewählter Dienste einer proprietären
Serveranwendung auf einen J2EE-Applikationsserver
Studienarbeit
bei der SAP AG, Sankt-Leo Rot/Baden
Von
cand. Inform.
Lan Liu
Betreuer:
Prof. Dr. J. Calmet
Dipl.-Inform. Regine Endsuleit
Tag der Anmeldung: 01. October 2003
Tag der Abgabe:
31.Dezember 2003
0
Ich erkläre hiermit, dass ich die vorliegende Arbeit selbständig verfasst und keine
anderen als die angegebenen Quellen und Hilfsmittel verwendet habe.
Karlsruhe den 31. Dezember 2003
1
Inhaltsverzeichnis
1
2
Einleitung ......................................................................................... 3
1.1
Problemstellung ......................................................................................... 3
1.2
Zielsetzung ................................................................................................ 3
1.3
Gliederung der Arbeit ................................................................................ 4
Grundlagen ....................................................................................... 5
2.1
Remote Method Invocation (RMI) ............................................................. 5
2.2
Java Naming and Directory Interface (JNDI) ............................................. 6
2.3
JDBC......................................................................................................... 7
2.4
Die Datenbank MaxDB.............................................................................. 7
2.5
Enterprise JavaBeans [4] [8] ...................................................................... 8
2.5.1 Einführung [3]........................................................................................................... 8
2.5.1.1
EJB Container....................................................................................................... 9
2.5.2 Session Beans.......................................................................................................... 12
2.5.3 Entity Beans ............................................................................................................ 13
2.6
2.6.1
2.6.2
2.6.3
2.6.4
2.7
3
JBoss IDE mit Eclipse [5] [6]....................................................................15
Installation von JBoss IDE ..................................................................................... 16
Konfiguration in JBoss IDE ................................................................................... 16
XDoclet ................................................................................................................... 17
Packaging ................................................................................................................ 17
HotSpot VM .............................................................................................18
Implementierung ............................................................................ 20
3.1
Struktur der Implementierung ...................................................................20
3.2
RMI ..........................................................................................................20
3.3
3.4
3.5
3.5.1
3.5.2
3.6
3.7
JNDI ........................................................................................................................ 21
Datenbank................................................................................................................ 22
EJB .......................................................................................................................... 23
Session Beans.......................................................................................................... 24
Entity Beans ............................................................................................................ 25
Anwendung der Entwurfsmuster............................................................................ 27
Effektives Java..........................................................................................27
4
Evaluation und Dokumentation der Ergebnisse ............................... 28
5
Zusammenfassung und Ausblick..................................................... 38
6
Appendix ........................................................................................ 40
7
Literatur .......................................................................................... 49
2
1 Einleitung
1.1
Problemstellung
Innerhalb der SAP existiert eine Vielzahl von Entwicklungsabteilungen, die hochkomplexe und oft vielgestaltige Softwarekomponenten produzieren. Dabei kommen
unterschiedliche Programmiersprachen und Technologien (hauptsächlich ABAP, C,
C++ sowie Java) zum Einsatz.
Mit Softwarelogistik wird die Disziplin bezeichnet, die von der Entwicklung angelieferten Softwarekomponenten in lauffähige Systeme auf Kundenseite zu überführen.
Dies erfordert eine Vielzahl eng miteinander verzahnter und grösstenteils zeitkritischer Prozesse. Zu diesen Prozessen gehören:
• Die Übernahme der Komponenten (in Form von Datenbankexporten, Quell- oder
Binärdateien) von den Entwicklungsabteilungen
• Das Zusammenstellen dieser Komponenten zu Produkten und Lösungen
• Die Validierung der Komponenten, Produkte und Lösungen
• Die Bereitstellung zur Auslieferung auf Datenträgern (CD, DVD) oder zum
Download
• Die Entwicklung von Werkzeugen, mit denen Installation und Wartung
komplexer, heterogener Systemlandschaften auf Kundenseite erst möglich werden
Das sogenannte Kit-Konzept sorgt durch die Einführung sogenannter Kits und Data
Units für eine neue vereinheitlichte Sichtweise auf diese Komponenten. Insbesondere
wird die bisherige Bindung von Komponenten an konkrete physikalische Medien aufgebrochen und die Auslieferung redundanter Komponenten drastisch reduziert. Das
MID-Projekt zielt darauf ab, durch flächendeckende Einführung des Kit-Konzepts
sowie eine Redefinition oben genannter Prozesse die Softwarelogistik flexibler,
kostengünstiger und kundenfreundlicher zu gestalten. Die vorliegende Studienarbeit
soll nun bei der Klärung der Frage mithelfen, ob für die Produktversion des MID
Servers ein standardkonformer J2EE-Server oder ein entsprechend modifizierter
J2EE-Server zum Einsatz kommen soll.
1.2
Zielsetzung
Dazu sollen folgende Aufgaben durchgeführt werden:
1. Einarbeitung in das Kit-Konzept und die verfügbaren Entwicklungswerkzeuge.
2. Erstellung eines Frameworks, mit dem ausgewählte Dienste des MID Servers auf
funktionelle Korrektheit und Performance geprüft werden können.
3. Ein quantitativer Vergleich alternativer Implementierungen in Bezug auf deren
Datendurchsätze und Antwortzeiten unter mehreren Laststufen.
4. Daneben soll auch beleuchtet werden, inwiefern sich ein Paradigmawechsel hin zu
J2EE auf die Produktivität und Codequalität bei der Entwicklung auswirkt.
3
1.3
Gliederung der Arbeit
Zuerst werden im Kapitel 2 die Grundlagen für diese Studienarbeit erläutert. Dabei
werden auf die Grundprinzipien von Remote Method Invocation (RMI), Java Naming
and Directory Interface (JNDI), JDBC und Enterprise Beans eingegangen und die
Datenbank, MaxDB, der J2EE Server JBoss und die Entwicklungsumgebung (IDE)
für EJBs, Eclipse, beschrieben.
Das Kapitel 3 beinhaltet die Implementierungsbeschreibung eines Frameworks, mit
dem ausgewählte Dienste des MID Servers auf die funktionelle Korrektheit und
Performance geprüft werden können. Weiter werden die benötigten Entwurfsmuster
und effektive Java Programmierungstechniken kurz erwähnt, die auch für die
Performance eine Rolle spielen.
Die Auswertung und die Dokumentation der Ergebnisse werden anschließend im
Kapitel 4 erklärt. Dort werden die Ergebnisse bei verschiedenen Profilen präsentiert
und ausgewertet.
Im Kapitel 5 wird schließlich diese Studienarbeit kurz zusammengefasst und ein
Ausblick auf zukünftige Arbeit gegeben.
4
2 Grundlagen
2.1
Remote Method Invocation (RMI)
Auf Daten wird nicht nur lokal sondern auch von entfernten Rechnern zugegriffen.
Entfernte Datenaufrufe sehen typischerweise bei Client/Server Architekturen. Die
Client/Server Architektur wurde entwickelt, um Daten von mehreren Computer
gemeinsam zu benutzen. Entfernte Prozedur Aufrufen (RPCs, Remote Procedure
Calls) oder eine normale Abfrage Sprache, SQL, werden zwischen Client und Server
angewendet. [3]
Ein Remote-Methodenaufruf (Remote Method Invocation, RMI) ist einer der
Eckpfeiler der Enterprise JavaBeans und eine ausgesprochen praktische Möglichkeit,
verteilte Java Anwendungen zu erstellen. Durch RMI wird nicht eine Methode auf
einem anderen Java-Objekt aufgerufen, das in derselben Java Virtual Machine (JVM,
d.h. in demselben ausführenden Programm) läuft, sondern wird eine Methode auf
einem Java-Objekt aufgerufen, das in einer anderen JVM auf demselben oder einen
anderen Rechner existiert.
Man braucht nicht viel zu machen, um eine Klasse RMI-fähig azu machen, und auch
das Aufrufen von Methoden ist einfach. Der Angelpunkt von RMI sind die RemoteInterfaces, also, Interfaces, die alle Remote-Methoden für ein Objekt defineiern.
Wenn man mit einem Remote-Interface eine Remote-Methode aufrufen, verbirgt RMI
mit Hilfe des Interfaces die Tatsche, dass man eine Methode remote, also aus der
Ferne, aufrufen. Dahinter steht der Gedanke, dass RMI ein Stub Objekt erzeugt, das
das Remote-Interface implementiert und in der JVM des Clients ausführt. Wenn der
Client eine Remote-Methode aufruft, übermittelt die Methodenimplementierung des
Stubs den Methodenaufruf über die JVM des Servers, wo ein weiteres besonderes
Objekt namens Skeleton die Anfrage interpretiert und die richtige Methode aufruft.
Wenn die Methode des Servers einen Wert zurückgibt oder eine Exception auslöst,
verpackt der Skeleton die Ergebnisinformationen und sendet sie an den Stub zurück.
Der Stub gibt die Informationen dann an den Client zurück. Der Stub und das
Skeleton kommunizieren über ein Protokoll namens Java Remote Method Protocol
(JRMP).
Wir schauen noch mal die ganze Architektur von RMI. RMI besteht aus drei
Schichten: Stub-/Skeletonschicht, entfernte Referenzschicht und Transportschicht.
Jede Schicht ist unabhängig von den anderen Schichten und beeinflusst die anderen
Schichten nicht. (Abbildung 2.1)
5
Abbildung 2.1: RMI-Architektur
Die entfernte Referenzschicht verwaltet alle Operationen der entfernten Objekte,
beispielsweise ist das Kopieren der Objekte.
Die Transportschicht hört die Anfrage des Methodeaufrufs ab und baut die
Verbindung für diesen Aufruf auf. Außerdem verwaltet und kontrolliert sie diese
Verbindungen. Um den entfernten Aufruf zu lokalisieren verwaltet Transportschicht
auch eine Datentabelle entfernter Objekte, die in diesem Adressraum existieren.
Bei den Objekttypen, die man in Remote-Methodenaufrufen (als Paratmeter oder
Ergebniswerte) verwenden können, erzwingt RMI eine bedeutende Restriktion, dass
alle Objekte, die man übergibt, java.io.Serializable oder java.rmi.Remote
implementieren. Objekt-Serialisierung ist ein Prozess, mit dem der Zustand eines
Objekts in einer Abfolge von Bytes gespeichert wird und diese Bytes in der Zukunft
wieder in ein Objekt zusammengefasst werden kann.
Wenn man ein serialisierbares (lokales) Objekt als RMI-Parameter übergibt, wird
dieses Objekt als Nicht-Remote-Objekt bezeichnet. Dies bedeutet, dass das ganze
Objekt vom Client zum Server oder vom Server zum Client geht. Wenn man hingegen
ein Remote-Objekt als RMI–Parameter übergibt, dann übergibt RMI nur eine
Remote-Referenz. Dies bedeutet, dass RMI nicht das ganze Objekt übergibt, sondern
nur etwas, was letztlich zu einem Stub wird. Das Remote-Objekt selbst bewegt sich
nicht von der Stelle.
2.2
Java Naming and Directory Interface (JNDI)
Ein Namensdienst verbindet einen einzelnen Namen mit einer bestimmten Ressource.
Eine RMI-Registrierungsdatenbank ist beispielsweise ein Namensdienst, der nur
RMI-Objekte speichert. Ein Verzeichnisdienst verbindet einen Namen mit einer
Gruppe von Attributen und Ressourcen. Wenn man einen Namensdienst durchsucht,
kann man nur nach einem speziellen Namen suchen. Wenn man ein Verzeichnis
durchsucht, kann man nach Elementen suchen, die einer bestimmten Gruppe von
Attributen entsprechen. Das Java Naming and Directory Interface (JNDI)
unterscheidet sich zwischen Namens- und Verzeichnisdiensten. JNDI ist eine Menge
von Schnittstellen, mit denen man auf Namensdienst und Verzeichnisdienst innerhalb
von Java Applikationen zugreifen kann.
Die Klasse Context ist der Kern des JNDI-APIs. Man benutzt Context, wenn man
etwas nachschlagen oder neue Name-/Wert-Verbindungen hinzufügen möchte. [4][8]
6
2.3
JDBC
Auf die Datenbank wird mittels des API Java Database Connectivity (JDBC)
zugegriffen. Ein JDBC-System besteht aus vier Teilen: Applikationsprogramm,
Treiberprogrammverwaltung, Treiberprogramm und Datenquelle. Mit JDBC hat man
ein Standard-API, das zum Großteil Datenbank unabhängig ist. Das heißt, mit JDBC
kann man auf die Datenbank wie zum Beispiel Oracle, Sybase, oder Informix
zugreifen. Es braucht nicht für jede Datenbank eine eigene Schnittstelle.
Eine Datenbank erlaubt normalerweise eine bestimmte Anzahl geöffneter
Anweisungen. Wenn der Speicherbereiniger die alten Verbindungen nicht löscht,
welche bereits abgeschlossen sind, kann es geschehen, dass die Anzahl der maximal
zulässigen Anweisungen überschritten wird. Dies führt zur eine Kollision bei dem
Zugreifen der Datenbankressourcen. Hierdurch kommt es zu einer Leistungssinken
der Anwendung. Um eine Anweisung zu schließen, ruft man die Methode close()
dieser Anweisung auf.
2.4
Die Datenbank MaxDB
Eine Datenbank ist in einem konsistenten Zustand, wenn die Daten korrekt
gespeichert sind und alle Bedingungen für die Daten und zwischen den korrelierten
Daten erfüllt sind. Hierzu zählen z.B. korrekte Zugriffspfade, Wertebereiche für
Attribute, Übereinstimmung von Fremdschlüsseln in einer anderen Relation,
Eindeutigkeit des Primärschlüssels. Die Konsistenzprüfung wird zum Teil von der
Datenbank selbstständig vorgenommen, teils muss dies z. B. durch eine CheckKlausel vom Programmierer explizit angestoßen werden.
Die hier benutzte Datenbank ist die SAP Datenbank Max DB. Die MaxDB ist eine
erweiterte Version von SAP DB, eine open Source Datenbank. Diese Datenbank ist
für große mySAP ERP (Enterprise Resource Planning ) Umgebungen geeignet. Die
MaxDB bietet schnelle Erreichbarkeit des Zugriffs auf die Datenbank und hohe
Skalierbarkeit, was für diese Studienarbeit geeignet ist.
Die MaxDB-Administration bietet unterschiedliche Programmierungsschnittstellen
und passende Terms für Java, Perl, PHP, Python usw. Datenbank Manager ist ein
Tool für Verwaltung der MaxDB Datenbank. Es wird benutzt, um die Datenbank
Instanz auf lokalen und entfernten Rechnern zu erstellen, sie zu kontrollieren, zu
überwachen, im Bedarfsfall zurückzusetzen und wiederherzustellen.
Für jede Datenbank erstellt die MaxDB eine LogDatei und eine Konfigurationsdatei.
Das Datenbanksystem unterstützt verschiedene Applikationsbereiche. Die Instanz
jedes Bereiches hat einen eigenen Typ. Hier wird OLTP (online transaction
Processing) benutzt. OLTP wird optimiert, um individuelle Transaktionen in einer
Datenbank mit hoher Anzahl an Benutzern schneller verarbeiten zu können. Es gibt
außerdem OLTP, den live Cache Typ, der nur für SAP-Applikationen zur Verfügung
steht, sowie den Archive Typ. Die Auswahl des geeigneten Typs erhöht die
Performance.
Die MaxDB hat viele Datenbankparameter, die man vor dem Zugreifen auf eine
Datenbank eingegeben werden können. Diese Parameter können zum Beispiel die
Cache-Größe, der Instanztyp, die Log-Segmentgröße, die MaxCPU usw. sein.
7
Um mit einer Datenbankinstanz zu arbeiten, eine Datenbankanfrage zu schicken oder
eine Datenbankinstanz zu verwalten, muss der Benutzter anhand eines
Benutzernamens und eines Passworts mit einer Datenbankinstanz kommunizieren.
Solange noch Transaktionen offen sind, zeigt die Verwaltung der Datenbank, dass es
noch Sessions gibt, die noch nicht abgeschlossen sind.
Ein wichtiger Punkt in einer Client-Server-Programmierung ist die Skalierbarkeit. Um
die Skalierbarkeit zu erreichen, sollen folgende Hinweise beachtet werden:
• Angemessenen Index für die Daten erstellen, um die Anzahl der gesuchten
Datensätze zu reduzieren.
• Kein gleiches Selektieren, um mehrere Zugriffe derselben Daten innerhalb einer
Transaktion zu vermeiden.
• Vollständige WHERE Klauseln, um die Anzahl der transferierten Datensätze zu
reduzieren.
• Parallele Abläufe einhalten
• Lineare Abhängigkeit von Datensätzen, um die interne Datentabelle optimal zu
benutzen [1]
2.5
2.5.1
Enterprise JavaBeans [4] [8]
Einführung [3]
Die Grundstruktur einer Drei-Schicht-Datenbankanwendungen besteht aus einer
Präsentationsebene, einer Geschäftslogikebene und einer Datenebene. In einer
typischen Geschäftsanwendung wird für die Datenbankebene eine Datenbank und für
die Präsentationsebene entweder ein GUI-Font-End oder ein Webserver verwendet.
Am schwierigsten ist die Geschäftslogikebene zu entwerfen. Hier muss
herausgefunden werden, wie die Zusammenarbeit zwischen die Datenbank und die
Clients ist, und wie die Clients auf die Remote-Geschäftsobjekte zugreifen. Außerdem
muss es sich entschieden werden, ob ein Objekt zwischen Methodenaufrufen die
Zustandsdaten speichern soll.
Enterprise Beans sind Server Seite Java. Es gibt 2 Arten von Server Seite Java, die
sind Folgendes:
1. .Java, die als Server arbeiten sind zum Beispiel EJB Container, Servlet Container,
http Server, Applikation Server usw.
2. Java, die als Komponenten in einer Java-Applikation arbeiten. Sie sind zum
Beispiel EJB, JavaBeans, JSP, Servlet.
Die Nutzung liegt häufig am Aufbau einer Web-Applikation durch die Komponenten.
[2]
In einer typischen Datenbankanwendung gibt es oft Änderungen an der Datenbank,
die ein Teil einer Transaktion darstellen. In der Vergangenheit war es schwierig,
Operationen auf verteilten Objekten zu einer einzigen Transaktion
zusammenzufassen. Java unterstützt durch die Server-seitige Programmierung und
seine hervorragenden Netzwerkfähigkeit einen Mechanismus für die Durchführung
verteilter Transaktionen. Die J2EE-Spezifikation bietet für verteilte Objekte, verteilte
Transaktionen an. Die Transaktionen sind normalerweise mit Datenbankoperationen
verbunden, obwohl das Konzept auch allgemein auf Objekte angewandt werden kann.
8
Um Transaktionen auf Java-Objekte auszudehnen, hat Sun eine Klasse von JavaObjekten, die so genannten Enterprise JavaBeans, definiert. Dabei handelt es sich
um Beans, die in einer Datenbank gespeichert sein können, aber nicht müssen, und an
Transaktionen teilnehmen können.
Enterprise Java Beans können Daten darstellen, die in einer Datenbank gespeichert
sind. Sie können sogar mit einem EJB-Server Datenbankdaten automatisch in einer
Bean einlesen und Bean-Daten automatisch in die Datenbank zurückschreiben. Bei
einer großen Datenbankanwendung kann dies enorm viel Zeit sparen.
Eine Enterprise JavaBean ist eine besondere Art von JavaBean, die der Durchführung
Server-seitiger Geschäftslogikoperationen dient. Hier werden Session-Bean und
Entity Bean angewendet.
EJBs sind J2EE Komponente. Sie sind Komponenten für die Erstellung von verteilten
Anwendungen. Die mit Enterprise JavaBeans erstellten Anwendungen sind
multiuserfähig, skalierbar, verteilbar und plattformunabhängig.
Eine Enterprise JavaBean hat mindestens drei obligatorische Java-Klassen:
• Das Interface Remote definiert die Methoden, die ein Client-Programm auf der
Bean geschäftliche Methode aufrufen kann.
• Das Interface Home definiert Methoden, um eine Bean zu erstellen und zu
suchen.
• Eine Java-Klasse implementiert sowohl das Interface Home als auch das
Interface Remote. Diese Klasse ist das, was man normalerweise mit der EJB
meint.
Ein Client erstellt eine EJB mit dem Interface Home und kommuniziert über das
Interface Remote die EJB Klasse. Die Abbildung 2.3 zeigt, wie ein Client mit den
Interfaces Home und Remote einer EJB integrieren.
erzeuge
und finde
Interface
Home
Client
BeanMethoden
EJBBehälter
BeanImplementierung
Interface
Remote
Abbildung 2.3 Enterprise JavaBean
2.5.1.1 EJB Container
Enterprise Beans sind Software-Komponenten, die in einem spezial Behälter,
Enterprise Container, existieren. In J2EE ist ein Behälter fast so etwas wie ein Mini-
9
Server: Er stellt die Laufzeitunterstützung für die Elemente bereit, die er enthält. Ein
EJB-Behälter erhält Enterprise JavaBeans und sorgt für die Bildung eines
Verbindungs-Pools wie zum Beispiel entferntes Zugreifen nach einem Bean, die
Sicherheit vom Zugreifen, Persistenz der Daten und die Transaktionsverarbeitung. So
kann der Bean Entwickler sich nur auf die geschäftliche Logik konzentrieren.
Hierdurch ermöglicht der EJB Container den schnellen Aufbau und Einsatz von
Enterprise Beans. Enterprise Bean ist von seinem Container abhängig. Durch den
Container kann ein Bean eine JDBC-Verbindung bekommen oder mit anderen Beans
kommuniziern.
Ein Container kann gleichzeitig mehrere Beans verwalten. Container verwaltet die
Ressourcen und den Lebenszyklus von allen Beans sehr sorgfältig, um
Speicherverbrauch und Verarbeitung zu reduzieren. Zum Beispiel wird der Container
ein Bean in ein Pool verschieben, wenn dieses Bean gerade nicht benutzt wird. Beans
werden aus dem Speicher geräumt und wieder zurück verlagert, wenn die Beans
wieder gebraucht werden. Der Client weiß von diesem Prozess nichts, weil er nicht
direkt auf die Beans zugreifen kann.
Abbildung 2.4: EJB Container
Enterprise Bean kommuniziert mit seinem Container durch drei Mechanismen:
Callback Methoden, EJBContext Interface oder JNDI (Java Naming and Directory
Interface):
•
Jede Bean Klasse implementiert die Callback Methoden, die durch das
entsprechende Interface definiert werden. Jede Callback Methode alarmiert die
Bean bei unterschiedlichem Ereignis in seinem Lebenszyklus. Der Container ruft
dabei die Methoden auf um sich bei der Bean zu melden, wenn der Container
diese Bean aktiviert, wenn die Datenzustände in der Datenbank gespeichert
10
•
•
werden sollen, wenn eine Transaktion beendet oder wenn diese Bean aus dem
Speicher geräumt werden soll.
Jeder Bean erhält ein EJBContext-Objekt, was den Container direkt referenziert.
EJBContext Interface bietet Methoden, durch die die Bean mit dem Container
kommunizieren kann, damit die Bean Informationen aus seiner Umgebung
abfragen kann.
JNDI wurde bereits in Kapitel 2.2 erklärt. Jede Bean hat automatisch einen
Zugang zu einem spezialen Naming System—ENC (Enviroment Naming
Context). Der ENC wird vom Container verwaltet und von Beans durch JNDI
zugegriffen. JNDI ENC ermöglicht das Zugreifen der Bean auf die Ressourcen
wie zu Beispiel eine JDBC Verbindung und die Kommunikation zwischen
mehreren Beans.
2.5.1.2 EJB-Transaktionen
Es muss darauf geachtet werden, dass eine Transaktion auf dem Server schnell
bearbeitet wird und es zu keinen gegenseitigen Beeinflussungen der einzelnen
Transaktionen kommt. Mit einer Transaktion kann man mehrere Operationen zu einer
einzigen alle-oder-keine Operation zusammenfassen. Anders ausgedrückt: Entweder
verlaufen alle Operationen erfolgreich oder alle scheitern. Transaktionsoperation
werden normalerweise danach beurteilt, ob sie den ACID-Test bestehen. Dabei
handelt es sich um vier Kriterien, die die gewünschten Eigenschaften einer
Transaktion beschreiben: Unteilbarkeit, Konsistenz, Isoliertheit und Dauerhaftigkeit.
Im Bereich der EJBs ist eine Transaktion normalerweise nicht mit einer Eintity-,
sondern mit einer Session-Bean verbunden.
2.5.1.2 wichitge Verfahren
Enterprise JavaBeans verwenden mehrere wichtige Verfahren. Die drei wichtigsten
Verfahren bei der EJB-Entwicklung sind RMI, JDBC und JNDI.
Jede Remote-Methode muss so deklariert werden, dass sie eine
java.rmi.RemoteException auslöst. Remote-Methoden müssen Ergebnistypen und
Parameter haben, die mit RMI kompatibel sind. Vor allem müssen die Objekte, die
mit RMI hin und her gegeben werden, das Interface java.io.Serializable
implementieren. Wenn man BMP verwendet, wird JDBC benötigt. Mit dem
Namensdienst JNDI werden Objekte im System gesucht. Die Abbildung 2.5 zeigt, wie
sich die verschiedene Kernverfahren in EJB-Anwendung einfügen.
11
finde
Dienste
JNDI
Clients
RMI
finde
Dienste
EJBKomponente
JDBC
Datenquelle
Datenbank
k
Abbidung 2.5 JDBC, RMI und JNDI sind die wichtigsten Verfahren bei der
Implementierung und Verwendung von EJBs
2.5.1.3 Die Bean bereitstellen
Ein weiterer Aspekt der Enterprise JavaBeans, der etwas gewöhnungsbedürftig sein
kann ist, dass EJBs nicht ausgeführt, sondern bereitgestellt werden. Hier wird durch
das JBoss anbietende Packwerkzeug eine JAR-Datei angelegt, welche die EJBKlassen, einige XML-Dateien für den Bereitstellungs-Deskriptor und einige
Helferklassen enthält, welche nur für den gerade verwendeten Behälter bestimmt sind.
Das Bereitstellungswerkzeug das von JBoss mitgeliefert wird, ist einfach
anzuwenden. Bereitstellungswerkzeuge sollen garantieren, dass alle Ressourcen die in
der Datei des Werkzeugs (Deployment Deskriptor) deklariert werden, benutzbar sind.
Das Bereitstellungswerkzeug erstellt einige Klassen und Schnittstellen anhand der
Werkzeuge von EJB Container, damit der EJB Container später EJB anhand der
Klassen und Schnittstellen in der Ausführungszeit verwalten kann.
Der EJB-Server sollte laufen, bevor etwas bereitstellt wird.
2.5.2
Session Beans
Session Beans repräsentieren normalerweise Geschäftslogikfunktionen und werden
nicht in der Datenbank gespeichert. Eine Session-Bean kann dennoch auf die
Datenbankzugreifen. Session-Beans arbeiten bei der Durchführung einer Operation
häufig mit mehreren Entity-Beans zusammen, müssen aber nicht unbedingt eine
12
Entity-Bean verwenden. In dieser Arbeit wird zuerst eine zustandslose Session-Bean
implementiert, dann arbeitet diese Session-Bean durch die Fassade Methode mit einer
Entity-Bean zusammen, was in 2.5.3 genauer erklärt wird.
Eine Session-Bean kann zwischen Methodenaufrufen Daten speichern, wenn es nötig
ist, muss dies aber nicht machen. Eine Session-Bean wird als zustandshältige?
Session-Bean bezeichnet, wenn sie Daten speichert. Wenn sie keine Daten speichert,
wird sie als zustandslose Session-Bean bezeichnet.
Jeder Client hat seine eigene Session-Bean. Aber wenn die Session-Bean zustandslos
sind, kann es geschehen, dass eine Session-Bean für mehrere Clients arbeitet, da sie
sich zwischen Methodenaufrufen nichts merkt. Deswegen besitzt auch eine
zustandslose Session-Bean wenige Ressourcen vom Server. Die gemeinsame
Benutzung von Ressourcen von Stateless Session reduziert die Belastung des Servers
und erhöht so die Skalierbarkeit der Anwendung.
Eine Datenbank ist eine typische, gemeinsam benutzte Ressource. Um Dienste der
Datenbank in Anspruch zu nehmen, braucht man zuerst die Verbindungen mit der
Datenbank zu bauen. Diese Verbindungen sind beschränkt. Deswegen ist es wichtig
für die Datenbankverwaltung, die Verbindungen zu koordinieren. Es ist wichtig, dass
jeder Client schnell die Verbindung freilässt. Die Verbindung wird nur während einer
Transaktion benutzt. Um die Verbindungen gut zu nutzen, sollte einerseits die
Transaktion so schnell wie möglich bearbeitet werden, andererseits sollten so wenige
Verbindungen wie möglich benutzt werden. [1] [4]
2.5.3
Entity Beans
Entity-Beans sind Enterprise JavaBeans, die Datenobjekte in ihrer Anwendung
darstellen und normalerweise in einer Datenbank gespeichert werden. Ein Client kann
Methoden auf einer Entity-Bean ebenso wie auf einer Session-Bean aufrufen.
Allerdings können in manchen Anwendungen nur Session-Beans auf Entity-Beans
zugreifen.
Im Gegensatz zu Session-Beans sind Entity-Beans zustandshaltig. Außerdem
unterscheiden sich Entity- von Session-Beans dadurch, dass mehrere Clients
gleichzeitig auf dieselbe Entity-Bean zugreifen können. Der EJB-Behälter kümmert
sich um alle Transaktionskonflikte, die eventuell aus der gemeinsamen Nutzung der
Entity-Beans entsehen. Der EJB-Behälter entscheidet, wann er Entity-Beans lädt und
speichert. Je nach dem Persistenzmodell der Bean kann der Behälter sogar die
Aufgabe übernehmen, die Bean in die Datenbank zu schreiben.
Entity-Beans können das Laden oder Speichern der Daten in die Datenbank entweder
selbst verwalten oder sie vom Behälter verwalten lassen. Wenn eine Bean ihre
Persistenz selbst verwaltet, verwendet sie die Bean-Verwaltete Persistenz (Bean
Managed Persistence, BMP). Wenn der Behälter die Persistenz der Bean verwaltet,
verwendet die Bean die Behälter-verwaltete Persistenz (Container Managed
Persistence, CMP).
13
Es ist manchmal nicht gut, eine Transaktion nur durch ein Entity Bean auszuführen.
Ein Beispiel dafür ist eine Transaktion wie Geldabheben. Bei dieser Transaktion sollte
die Eingabe geprüft und Geld dem Kunde gegeben werden. Wenn alle Aktionen nur
in einem Entity ausgeführt werden, kann es passieren, dass die Eingabe nicht richtig
ist, aber Geld schon dem Kunde gegeben wird. Wenn die Aktionen in mehreren Entity
Beans beschrieben werden, dauert die Ausführung der Aktionen sehr lang. Die
Nachteile, wenn man nur Entity-Beans verwendet, sind folgende.
1. hohe Kosten des Internets, was der Performance schadet. Es sei denn, dass wir
lokale Interface benutzen.
2. schlechtes Parallel laufen.
3. hohe Abhängigkeit zwischen Client und Entity Bean. Falls sich die
Anforderungen des Clients ändern, ändern die Funktionen in einer Entity Bean
auch sehr stark.
4. schlechte Wiederverwendbarkeit von Entity Bean.
5. schlechte Trennung der Arbeit zwischen Programmier, Entwicklung und Business
Logik. [1] [4]
2.5.3.2 Session Fassade
Aus der Gründe der Nachteile der nur Entity-Bean benutzde Anwendung wird eine
Session Fassade zwischen Client und Entity-Bean gebraucht. Session Fassade dient
als Vermittler und Puffer für Entity-Bean. Sie kann als ein Vermittler zwischen
Clients und Entity-Beans sein, durch sie Clients die Entity-Beans über Session-Beans
zugreifen können. Die Clients können auch nur auf Session-Bean zugreifen.
Session Fassade verwendet das Entwurfsmuster der Fassade. Das Entwurfsmuster der
Fassade bietet eine einheitliche Schnittstelle zu einer Menge von Schnittstellen eines
Subsystems. Die Fassadeklasse definiert eine abstrakte Schnittstelle, welche die
Benutzung des Subsystems vereinfacht. Diese einheitliche Schnittstelle ist hier diese
Session Fassade, die Entity Beans verbirgt. Die Clients können nur auf die Session
Fassade zugreifen, wobei sich die Session Fassade überlegt, auf welche entsprechende
Entity Bean zugegriffen werden sollte. Diese Session Fassade sind Stateless Session.
Gelegentlich werden eine große Klasse an Session Bean geschrieben, wobei alle
Aktivitäten in die Session-Fassade geschrieben werden. Sie ist jedoch nicht effektiv
für das Programm. Diese Session Beans sollten in unterschiedlichen Gruppen
aufgeteilt werden.
Fassade hat mehrere Vorteile:
1. Niedrige Netzverbindungskosten: Der Client benutzt nur ein Mal die
Netzverbindung vom Server bei einer Methodeaufruf. Die übliche Aufrufe spielen
sich zwischen Session Bean und Entity Bean in einer lokalen Interface ab, was
keine Netzverbindungen braucht. Die meisten Server können auch die
Kommunikation zwischen Session Bean und Entity Bean optimieren.
2. Klare und saubere Trennung zwischen geschäftlicher Logik und präsentierender
Schicht: Alle geschäftliche Logik ist hinter der Fassade verborgen.
3. Zusammenfassung der Aktivitäten in Session Bean: Aktivitäten werden in Session
Bean abgegrenzt und durch deployment descriptor (Dislozieren Deskriptor)
eingesetzt.
14
4. Lockere Abhängigkeit zwischen Client und Entity Bean: Falls die Entity Bean
geändert wird, muss der Client nicht entsprechend geändert werden.
5. Gute Wiederverwendbarkeit: Das in Session Bean zusammengefasste Session
Bean kann von jedem Typ Client (JSP, Servlet, Applikation oder Applet)
verwendet werden.
6. Die deployment discriptor deklariert die Aktivitäten klar in Session Bean, dadurch
hat man eine klare Trennung von Session Bean und Aktivitäten. Dies verringert
Fehlern.
Die Methoden die mit „find“ anfangen, heißen find-Methoden. Clients sucht die
Entitiy-Beans nach Suchkriterien mittels der find-Methoden. Es gibt keine StandardAbfragesprache für die find-Methoden. In CMP werden die find-Methoden nicht in
der Bean Klasse implementiert. Container implementieren diese find-Methoden, wenn
das Bean eingesetzt wird. Deployer benutzt Anbieter spezifischer Tools, um dem
Container mitzuteilen, wie sich eine bestimmte find-Methode verhält.
2.5.3.2 CallBack Methoden
Ein Entity Bean verfügt über Callback Methoden, durch die der Container den
Ereignisse die Bean benachrichtigt. Die Callback Methoden für Entity Bean sind in
der Interface: javax.ejb.EntityBean definiert und in allen Entity Klasse implementiert.
Es gibt folgende Definitionen der Callbackmethoden:
SetEntityContext(), unsetEntityContext(), ejbLoad(), ejbStore(), ejbActivate(),
ejbPassivate(), ejbRemove().
Die setEntityContext() Methode bietet dem Bean eine Interface, durch die das Bean
mit dem Container kommuniziert, es ist also ein EntityContext. Die Entitycontext
Interface verfügt über eine Methode, durch die Informationen über den Kontext
übermittelt werden. Durch die EntityContext Interface kann man die
Sicherheitsinformation über die Aufrufer bekommen, den Stand der aktuellen
Transaktion überprüfen, eine Transaktion zurücksetzen und eine Referenz von Bean
selber bzw. seine Home-Interface oder seinen Hauptschlüssel bekommen. Der
EntityContext wird nur ein Mal im Lebenszyklus einer Beaninstanz aufgesetzt. Die
unsetEntityContext() Methode wird am Ende eines Lebenszykluses von Bean benutzt,
um die Referenz eines EntityContextes zu löschen und aufzuräumen.
Die ejbLoad() und ejbStore() Methoden in einem CMP Entity werden aufgerufen,
wenn der Entity Bean mit der Datenbank synchronisiert wird. Die ejbLoad() Methode
wird aufgerufen, bevor der Container die Daten von der Datenbank holt. Die
ejbStore() Methode wird aufgerufen, bevor der Container die von ihm verwalteten
Felder in die Datenbank schreibt. Diese Methoden werden benutzt, um zum Beispiel
die Daten zu komprimieren, bevor sie in die Datenbank eingelagert werden, und um
die Daten zu dekomprimieren, wenn die Daten von der Datenbank abgerufen werden.
Die ejbPassivate() und ejbActivate() Methoden werden vom Container aufgerufen,
bevor das Bean deaktiviert und nach dem das Bean aktiviert wird.
2.6
JBoss IDE mit Eclipse [5] [6]
15
Die Eclipse Platform ist entwicklet, um IDE (integrated development environment)
zu bauen. Mittels des Eclipse IDEs können Applikationen in Java, C++ und
Enterprise JavaBeans erstellt werden. Diese Studienarbeit wird in der
Programmierumgebung JBoss IDE mit Eclipse entwickelt. JBoss–IDE bietet eine
Menge von IDE Klasse für JBoss und basiert auf einer Integration mit Eclipse.
JBoss-DIE bietet die folgende Funktionen:
• Debugging und Kontrollieren des JBoss Servers und Kontrollieren des
Lebenszykluses des Servers
• Funktionen von Xdoclet
• Eine einfach Methode der Konfiguration des Packetarichivierens
JBoss EJB Container ist der Kern von JBoss Server. JBoss EJB-Container erstellt
einerseits automatisch Stub und Skeleton Dateien während des Programmablaufs,
andererseits unterstützt er die Technik Hot Deplyment. Mittels der Technik Hot
Deployment können neue Komponente wie zum Beispiel Enterprise Beans, kleine
Service Programme und JSP Dateien während des Server Ablaufprozesses
hinzugefügt werden, ohne die Server Applikation zu beenden und neu zu starten.
2.6.1
Installation von JBoss IDE
Weitere Software wird benötigt um JBoss zu installieren:
• Sun`s SDK (Software Development Kit). SDK ist eine Schnittstelle, mit der
eigene Softwaren an bestehende Programmen, Applikationen und
Betriebssysteme angehängt werden können.
• org.jboss.ide.ecllipse_1.2.1.bin.dist.zip. Diese Datei sollte in Eclipse
Hauptverzeichnis verpackt werden.
• Ant. Es ist ein Java Build Tool. Ant basiert auf XML und wird benutzt, um
Jakartas Tomcat Web Server aufzubauen.
2.6.2
Konfiguration in JBoss IDE
Bevor das Projekt entwickelt wird, sollte die folgende JAR Dateien von JBoss
Bibliothek ins Projekt importiert werden:
• jnp-client.jar,
• jbossall-client.jar,
• jboss-j2ee.jar,
• jboss-transaction-client.jar,
• log4j.jar. (Diese Datei findet man unter dem Verzeichnis Client in der JBoss
Package)
• jboss-j2ee.jar (Diese Datei findet man unter server\default\lib in der JBoss
Package)
Konfigurieren von Client
Um das Projekt in JBoss zu starten, müssen einige Konfigurationsinformation
eingetragen werden:
-Djava.naming.factory.initial=org.jnp.interfaces.NamingContextFactory (siehe 3.3)
-Djava.naming.provider.url=jnp://localhost:1099
-Djava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
16
2.6.3
XDoclet
Eine wichtige Eigenschaft des JBoss-IDEs ist die Benutzung des Xdoclet Plug-ins.
Ein Plug-in ist ein Programm, das sich als Teil eines anderen Programms einfügt, um
zusätzliche Funktionen zur Verfügung zu stellen. Diese zusätzliche Funktionen, die
Xdoclet anbietet, sind:
• Ein Kode Assistent mit Kontext-abhängigen Angeboten
• Ermöglichung der vom Benutzter definierten Schablone
• Anbieten einer graphischen Oberfläche, um XDoclet Konfigurationen zu machen
• Ermöglichung der Aktivieren/Deaktivieren Konfigurationen
In der Implementierung schreibt der Entwickler die Informationen über die Bean
Klasse, diese Beschreibung nennt man hier tags. Diese tags werden in Xdoclet
konfiguriert und dadurch werden die Informationsdateien erstellt.
Wenn Xdoclet fehlerfrei ausgeführt wurde, bekommt man folgende Information
(Beispiel für die Session Bean).
Buildfile: C:\lan\eclipse-SDK-2.1win32\eclipse\workspace\mid\xdoclet-build.xml
N400004:
[ejbdoclet] Generating EJB deployment descriptor (ejb-jar.xml).
[ejbdoclet] Generating jboss.xml.
[ejbdoclet] Generating Remote interface for
'mid.ejb.MIDSampleServicesSessionBean'.
[ejbdoclet] Generating Home interface for
'mid.ejb.MIDSampleServicesSessionBean'.
_generation_:
BUILD SUCCESSFUL
Total time: 14 seconds
Durch die Information sieht man, dass Xdoclet automatisch für das Projekt die
Information von deployment descriptor ejb-jar.xml, die jboss.xml Datei und die
Interfaces für die Session Bean Klasse erzeugt.
2.6.4
Packaging
In JBoss-IDE lässt sich einfach und schnell das Archiv von Package erstellen.
In dieser Arbeit gibt es drei Packages:
• Eine für EJB.Jar. Sie beinhaltet EJB Klassen, Interface und Deployment
Deskriptor.
• Eine für EJB Client Jar. Sie hat EJB Schnittstellen.
• Eine für die J2EE Applikation Ear. Sie besteht aus EJB Jar und die Deployment
Deskriptor.
Klick “Ok” in der Konfigurationsoberfläche, um die Konfiguration von
Verpackungen zu speichern. Diese erzeugt das Ant Build File „packaging-build.xml”
für dieses Projekt. Somit hat die ganze J2EE Applikation eine Verpackungkonfiguration.
17
Wenn eine Packaging erfolgreich in JBoss ausgeführt ist, wird die folgende
Information geliefert:
Buildfile: C:\lan\eclipse-SDK-2.1win32\eclipse\workspace\mid\packaging-build.xml
N400004:
[jar] Building jar: C:\lan\eclipse-SDK-2.1win32\eclipse\workspace\mid\MIDSampleServicesEJB.jar
N400024:
[jar] Building jar: C:\lan\eclipse-SDK-2.1win32\eclipse\workspace\mid\MIDSampleServicesEJB-client.jar
N400034:
[jar] Building jar: C:\lan\eclipse-SDK-2.1win32\eclipse\workspace\mid\MIDSampleServicesApp.ear
_generation_:
BUILD SUCCESSFUL
Total time: 1 second
Aus der Information sieht man, dass die packaging-build.xml Datei automatisch
erstellt wird. Außerdem sind die JAR Package, Client Package und EAR Package, die
für dieses Projekt erforderlich sind, automatisch erzeugt wurden.
Die application.xml Datei erzeugt man manuell (Diese Datei siehe bitte in Appendix
B).
2.7
HotSpot VM
HotSpot VM ist eine Java virtuelle Maschine, in dem der Java Code dynamisch
kompiliert wird. Im Gegensatz zu der klassischen JVM (Java virtuelle Maschine)
werden die Programme effektiver in HotSpot VM ausgeführt, indem die
Müllsammlung und Thread Bearbeitung in HotSpot VM erweitert werden. Außerdem
hat HotSpot einen Profil Monitor, der während des Ausführens eines Programms
erkennt, welche Teile öfter benutzt werden, die dann als hot spot bezeichnet werden.
Darüber hinaus wird erkannt, wie die Performanz beeinflusst wird. Es wird die
entsprechende Optimierungstechnologie angewendet, um die Programme schneller
arbeiten zu lassen. Der klassische JVM fällt es schwer zu erkennen, welche Teile am
meisten optimiert werden sollen. HotSpot VM kann durch die Erkennung von hot spot
das Programm besser optimieren. Die unnötigen Kode, die für das Ausführen von
Daten nicht benötigt werden, werden nicht kompiliert.
Es gibt zwei HotSpot VM: Java HotSpot Client VM und Java HotSpot Server VM.
Die Beide sind zueinander kompatibel. Die Gründe warum es zwei HotSpot VM gibt
sind, dass die auf der Client Seite und auf der Server Seite laufende Applikationen
unterschiedlich sind. Auf der Client Seite konzentrieren sich die Benutzter auf die
Oberfläche, ob sie bedienerfreundlich und übersichtlich ist. Auf der Server Seite sind
die Effektivität und die Ressourcen Benutzbarkeit wichtiger als die Oberflächen.
Deswegen sind die Optimierungsstrategien auf der Client Seite und auf der Server
Seite unterschiedlich.
18
19
3 Implementierung
3.1
Struktur der Implementierung
Es gibt drei Basis Klassen in der Implementierung: mid.ejb.MIDSampleKey,
mid.ejb.MIDSampleObject und mid.ejb.MIDSampleServeices.
In der Klasse MIDSampleServices werden die fünf Methoden: add(), get(), update(),
delete() und find(), definiert, die den Datentyp MIDSampleObject haben. In dieser
Arbeit werden anhand der genannten Methoden die Aufrufantwortzeit gemessen.
Ablauf des Projekts
Zuerst wird in dieser Arbeit getestet, ob alle diese Methode richtig funktionieren.
Dann werden die Antwortzeit für lokale und entfernte Methodenaufrufe ohne
persistente Daten, die in J2SE implementiert sind, gestestet. Danach werden die lokale
und entfernte Methodeaufrufe, die die persistente Daten bearbeiten, getestet. Am
Ende sollte die Antwortzeit für lokale und entfernte Methodeaufrufe, die in J2EE
implementiert sind, getestet werden.
3.2
RMI
Um die Antwortzeit von Remote-Methodenaufrufe zu testen, müssen wir RMI
realisieren.
Die wichtigsten Sachen in RMI sind Stub und Skeleton. Diese braucht man in RMI
nicht zu schreiben. Stub und Skeleton werden in dem Remote-Interface mit einem
Programm namens rmic (dem RMI-Kompilierer) erzeugt.
Bevor ein Stub und ein Skeleton generieren werden kann, muss man das Interface
Remote zuerst definieren. Ein Remote-Interface erweitert einerseits java.rmi.Remote
und enthält andererseits einige Methoden, die eine java.rmi.RemoteException
auslösen können. Diese Eigenschaften werden in der Klasse
mid.ejb.MIDSampleServices.java realisiert. Das Interface Remote kennzeichnet ein
Objekt als Remote-Objekt, d.h. wenn ein Objekt das Interface
mid.ejb.MIDSampleServices.java implementiert, weiss RMI dass das Objekt ein
remote Objekt ist. Diese Implementierung ist in der Klasse
mid.impl.basic.MIDSampleServicesImpl.java geschrieben. In Remote Interface kann
man auch die Methode definieren, die nicht Remote-Methoden sind. Diese Methoden
werden aber nicht remote sein, auch wenn das Interface remote ist. Deswegen kann
das Interface mid.ejb.MIDSampleServices.java für lokale Methodenaufrufe benutzt
werden. Wenn man eine Methode remote aufrufen möchten, dann muss die Methode
in der Lage sein, eine RemoteException auszulösen.
Stub und Skeleton können jetzt noch nicht generiert werden. Das Programm rmic
generiert Stub und Skeleton mit der Implementierung des Remote-Objekts, nicht mit
dem Interface Remote.
20
Um ein Remote-Objekt zu implementieren, muss die Klasse
mid.impl.basic.MIDSampleServicesImpl.java erstellt werden, die eine Unterklasse
von java.rmi.server.UnicastRemoteObjekt ist und die Remote-Methoden add(), get()
usw. implementiert.
Weil RMI Klassen dynamisch geladen werden, benötigt man hier einen besonderen
Sicherheitsmanager, um zu gewährleisten, dass keine falsche Klassendatei geschickt
wird. Dieser Sicherheitsmanager ist in der main-Methode eingerichtet.
if (System.getSecurityManager() == null){
System.setSecurityManager(new RMISecurityManager());
}
Um Remote-Objekte zu aktivieren (d.h. zur Verwendung bereitzustellen), sollten die
Remote-Objekte durch die Klasse java.rmi.Naming in der RMIRegistrierungsdatenbank registriert werden.
Naming.rebind("rmi://localhost:1099/MIDSampleServices", m);
Nun kann man mit dem rmic Programm den Stub und das Skeleton generieren.
rmic mid.ejb. MIDSampleServicesImpl
Bevor man mid.impl.basic.MIDSampleServicesImpl.java ausführt, muss man die
RAI-Registrierungsdatenbank mit dem Befehl rmiregistry starten.
Die RMI-Registrierungsdatenbank ist ein Verzeichnisdienst, mit dem Clients RemoteObjekte durch ihre Namen finden können. Diese wird in der Klasse
test.MIDSampleClient.java implementiert.
System.out.println("basic remote:");
multi_clientTest((MIDSampleServices)Naming.lookup("rmi://localh
ost/MIDSampleServices"), "remote client", clientCount,
readCount, writeCount, addTimeSet, getTimeSet, updateTimeSet,
deleteTimeSet, findTimeSet);
Die Objekte, die übergegeben werden, sind Objekte von der Klasse
MIDSampleKey.java und MIDSampleObjekt.java. Die beiden Klassen
implementieren die Klasse java.io.Serializable. Dann werden die Objekte, die bei den
Remtoe-Methodenaufrufen übergegeben werden, als Nicht-Remote-Objekt
bezeichnet.
3.3
JNDI
Bei der Anwendung von JNDI sollte zuerst ein Initial Context-Objekt erzeugt werden.
Hier wird das InitialContext–Objekt als Eingangspunkt für JNDI verwendet. Dies
wird in der folgenden Implementierung des Clients einer Session-Bean gezeigt:
Properties props = System.getProperties();
Context context = new InitialContext(props);
21
Der Konstruktor InitialContext sucht nach der Systemeigenschaft
java.naming.factory.initial, die den Namen der Klasse enthält, die InititalContext
erzeugt. Manchmal muss man diesen Wert selbst bereitstellen. Bei einigen EJBBehältern wie z.B. den von Suns J2EE SDK ist diese Eigenschaft bereits gesetzt.
Wenn das Programm ausgeführt werden soll, wird mit der Option –D die Factory für
den Anfangskontext angegeben. Diese macht man in der JBoss Konfiguration
folgendermaßen:
-Djava.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
Nachdem nun ein Context-Objekt erzeugt ist, kann man mit der Methode lookup das
Objekt, MIDSampleServices suchen. Mit der folgenden Aufruf wird die EJB gesucht:
Object objref = context.lookup("ejb/mid/MIDSampleServices");
Es gibt mehrere Namensdienste von JNDI. Durch den Namen rmi in der Bean
Implementierungsklasse weiß man, dass der hier benutzende Namensdienst eine RMIRegistrierungsdatenbank ist:
multi_clientTest((MIDSampleServices)Naming.lookup("rmi://localh
ost/MIDSampleServices"), "remote client", clientCount,
readCount, writeCount, addTimeSet, getTimeSet,
updateTimeSet,
deleteTimeSet, findTimeSet);
3.4
Datenbank
Vier Datenbanktabellen werden in dieser Arbeit erstellt: Midsampleobject,
object_attribute, sub_object, objectKey. Man sollte bei der Erstellung der Datenbank
darauf achten, ob das Datenschema vollständig und korrekt ist.
Durch die Implementierung von mid.impl.basic.MIDSampleServicesJDBC.java greift
man auf die Objekte zu, die in Datenbank gespeichert sind. In dieser Implementierung
wird der Datenbanktreiber "com.sap.dbtech.jdbc.DriverSapDB" für die
Datenbankverbindung benutzt. Die hier benutzte Datenbank wird durch unteren Code
angezeigt:
url = "jdbc:sapdb:///db1";
Um die erlaubte Anzahl offener Datenverbindung nicht zu überschreiten, sollte man
abgeschlossene Datentransaktionen schließen. Diese erreicht man durch die Methode
releaseConnection() in dieser Klasse.
In der Klasse wird die Methode getNextKey() implementiert, die die Datentabelle
objectKey benutzt. Diese Tabelle enthält nur einen einzigen Spalte: object_key.
Dieses Datenfeld erzeugt für jede neue Objekt einen neuen Schlüssel. Die Add()
Methode ruft dann diese Methode auf, wenn neue Objekte in der Datenbank angelegt
werden sollen. Durch getNextKey() hat jedes neuerstellte Objekt automatisch einen
neuen Schlüssel, der durch Inkrementieren erzeugt wird. Die neuen Objekte haben
dann den Schlüssel in allen Datentabellen. Die Daten in der Datenbank sind dadurch
eindeutlich identifiziert.
22
Beispielsweise durch Aufbauen der Datenbankverbindung, Schlüssel Erstellung usw.
sind die Antwortzeiten der Methodenaufrufe mit persistenten Daten im allgemeinen
langsamer als die Methodenaufrufe ohne persistente Daten.
3.5
EJB
Jede Bean Klasse hat zwei Interfaces: Ein entferntes (Remote) Interface und ein Heim
(Home) Interface. Home Interface definiert die Lebenszyklus-Methode einer Bean
(Erzeugen, Löschen und Finden einer Bean) und hat die Eigenschaften des Interfaces
javax.ejb.EJBObject, das java.rmi.Remote erweitert. Remote Interface definiert die
Geschäfts Methode einer Bean und erbt das Interface javax.ejb.EJBHome, das auch
das Interface java.rmi.Remote erweitert.
EJB Container
remote
Client
Session Bean
Entity Bean
home
Abbildung 3.1: Konzeptionell Ansicht von EJB Architektur
Die Abbildung 3.1 zeigt die Struktur von EJBs. Ein Client bekommt einen Referenz
von dem Remote Interface durch ein Home Interface. In dieser Arbeit wird der Client
in der Klasse test.SessionBeanTester implementiert. Durch folgenden Code eines
Session-Bean Clients wird die Arbeit eines EJB-Cleints besser verstanden:
//bekommt eine Referenz, die home Interface implementiert
MIDSampleServicesSessionHome home =
(MIDSampleServicesSessionHome)
PortableRemoteObject.narrow(objref,
MIDSampleServicesSessionHome.class);
//benutzen home Interface, um ein neue Instanz von
//MIDSampleServicesSession Bean zu erzeugen
MIDSampleServicesSession session =
MIDSampleServicesSession)home.create();
//benutzen die geschäftliche Methode von
//MIDSampleServicesSession
multi_clientTestSession(session, "session test", clientCount,
readCount, writeCount, addTimeSet, getTimeSet,
updateTimeSet,
deleteTimeSet, findTimeSet);
23
Remote Interface und Home Interface werden jeweils in den Kapiteln Session Beans
und Entity Beans genauer erklärt.
3.5.1
Session Beans
Das Remote und Home Interface der Session Bean sind
mid.interfaces.MIDSampleServicesSession und
mid.interfaces.MIDSampleServicesSessionHome. Im Remote Interface werden die
geschäftlichen Methoden: add(), get(), update(), delete(), find() definiert.
Die Bean Klasse ist in der Klasse MIDSampleServicesSessionBean.java
implementiert. Diese Session Bean hat keine direkte Verbindung mit der Datenbank.
Die Verbindung von Bean zu einer Datenbank wird in der Entity-Bean implementiert.
Diese Session-Bean ist eine zustandslose Session-Bean. In der Bean werden die
Callback Methoden: ejbCreate(), ejbActivate(), ejbPassivate(), ejbRemove()
implementiert. Durch diese Methoden alarmiert der Bean-Container die Bean bei
Ereignissen. Durch SessionContext kann die Bean mit anderen Beans und dem
Container kommunizieren.
JBoss bietet XDoclet an, durch das man leichter Beans bereitstellen kann. Die tags in
Beans, die man für die Bereitstellung benötigt, sehen Folgendes aus:
/**
*
* @ejb.bean name = "MIDSampleServicesSession"
*
display-name = "MIDSampleServicesSession EJB"
*
description = "MIDSample Session Bean"
*
view-type = "remote"
*
jndi-name = "ejb/mid/MIDSampleServicesSession"
*
*/
Die ejb-jar.xml Datei mit diesen Informationen wird durch das Ausführen des
Xdoclets erzeugt.
Der Client der Session-Bean wird in der Klasse test.SessionBeanTester.java
implementiert.
3.5.1.1 Bereitstellung der Session-Bean
Zuerst wird eine EJB-JAR Datei erstellt. Diese Datei enthält die Bean Klasse
MIDSampleServicesBean.java und deren Interfaces: MIDSampleServices.java und
MIDSampleServicesHome.java. Außerdem hat diese JAR-Datei auch die
Beschreibung von deploytool (deployment descriptor), die den Typ der Bean und
andere Konfigurationsinformationen enthält.
Dann wird eine EJB-JAR Datei erstellt, die EJB Interfaces enthält.
Danach wird eine EAR-Datei (Enterprise Archive) erstellt. Eine EAR-Datei ist eine
JAR-Datei für J2EE-Anwendungen. Diese Datei enthält EJB-JAR und deployment
descriptor.
24
Schließlich muss man deploytool noch mitteilen, welcher JNDI-Name für die EJB
gegeben wird. Die Bereitstellung der Bean wird in dieser Arbeit anhand des JBoss
Tools „Packing Configurations“ erstellt.
3.5.2
Entity Beans
3.5.2.1 CMP
Der EJB-Behälter bei Container-verwalteter Persistenz (CMP) weiß, wie die Bean
sowie die verbundenen Datenelemente geladen und gespeichert werden. Die CMP
behandelt die Datenbankoperationen für den Entwickler und befreit ihn von einem
Großteil der unangenehmen Seiten von Entity-Beans. Hier wird keinen SQL-Code
mehr gebraucht. Diese CMP Klasse verwendet die Version 2.0 der EJB-Spezifikation,
die grundlegend die Version 1.1 geändert hat. Eine gute CMP-Implementierung kann
bewirken, dass die Anwendung mit weniger Arbeit wesentlich schneller läuft als eine
typische BMP-Anwendung. Eine der größten Verbesserungen, die man bei einer
CMP-Implementierung sehen kann, ist der neu hinzu gekommene Cache. Wenn eine
CMP-Maschine Objekte im Cache zwischenspeichern kann, kann sie bewirken, dass
man wesentlich seltener mit der Datenbank zusammenarbeiten muss. Bei Objekten,
die häufig gelesen werden, bringt das Zwischenspeichern im Cache noch weitere
Vorteile. Dies gilt besonders bei Objekten, die regelmäßig verwendet werden.
Die Klasse MIDSampleServices02Bean.java ist eine CMP Klasse der Version EJB
2.0. Diese Klasse einer CMP-Bean muss abstrakt sein. Darüber hinaus deklariert sie
für keines der persistenten Felder Elementvariablen, sondern nur die abstrakten
Zugriffsmethoden. Die verschiedenen Feldwerte sind auch nicht vorhanden. Die
Home und Remote Interfaces der CMP Bean sind: MIDSampleServices02.java und
MIDSampleServices02Home.java.
Im Home Interface der Entity Bean Klasse ist außer der create Methode noch eine
Suchmethode vorhanden:
public mid.interfaces.MIDSampleServices02
findByPrimaryKey(mid.interfaces.MIDSampleServices02PK pk)
throws javax.ejb.FinderException,java.rmi.RemoteException;
Anhand der finder-Methoden, die mit dem Wort find beginnen und die
FinderException auslöst, wird CMP nach den Suchkriterien--den Hauptschlüsseln des
MIDSampleObjekts--gesucht.
Um eine neue Instanz von CMP Entity Bean zu erzeugen und folglich Daten in die
Datenbank hinzuzufügen, wird die create() Methode des Home Interfaces aufgerufen.
Ein Home Interface kann keine, eine oder mehrere create() Methoden deklarieren.
create() Methode hat auch eine entsprechende ejbCreate() und ejbPostCreate()
Methode in der Bean Klasse. Wenn eine create() Methode im Home Interface
aufgerufen wird, delegiert der Container die create() Methode eine Instanz zu der
entsprechenden ejbCreate() Methode. Die create Methode und die entsprechende
ejbPostCreate() in dieser CMP Klasse sehen folgendermaßen aus:
public MIDSampleKey ejbCreate()throws CreateException{
25
try{
setMIDKey(getNextKey());
return null;
}
catch(SQLException exc){
throw new CreateException("Unable to access
database" +
exc.toString());
}
}
public void ejbPostCreate() throws CreateException{
}
Die Bean Implementierungsklasse besteht außerdem aus den Callback Methoden
ejbActivate(),ejbPassivate(),ejbLoad(),ejbStore(),ejbRemove(). Die Geschäfts
Methoden dieser CMP sind wie in Session-Bean.
Die abstrakten Zugriffsmethoden in CMP sind:
public abstract int getVersion();
public abstract void setVersion(int aVersion);
public abstract String getName();
public abstract void setName(String aName);
Die CMP Klasse muss für alle Felder, die in der Datenbank gespeichert sind
Zugriffsmethoden enthalten, obwohl einige Zugriffsmethoden dem Client über das
Remote Interface verfügbar gemacht werden können.
Die Bereitstellung der CMP ist ähnlich wie bei Session-Bean. Die Anfragen für die
finder-Methoden in der EJB 2.0-Version der CMP sind nicht mehr in der
herstellerspezifischen Konfigurationsdatei enthalten, sondern in der Datei ejb-jar.xml.
Um das besser zu verstehen, sehen wir die Beschreibung von CMP in der Datei ejbjar.xml.
<entity >
<description><![CDATA[MIDSample CMP]]></description>
<display-name>MIDSampleServices02 EJB</display-name>
<ejb-name>MIDSampleServices02</ejb-name>
<home>mid.interfaces.MIDSampleServices02Home</home>
<remote>mid.interfaces.MIDSampleServices02</remote>
<ejb-class>mid.ejb.MIDSampleServices02CMP</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>mid.interfaces.MIDSampleServices02PK</primkey-class>
<reentrant>False</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>MIDSampleServices02</abstract-schemaname>
</entity >
26
3.6
Anwendung der Entwurfsmuster
Das Entwurfsmuster--Fabrik Methode--wird häufig in der Klasse
MIDSampleClient.java verwendet. Die Methode multi_clientTest() ist ein Beispiel.
Diese Methode wird auf unterschiedliche Weise genutzt: lokale Aufrufe, entfernte
Aufrufe, Methodenaufrufe ohne Datenbank oder mit Datenbank usw.. Man übergibt
dieser Methode bei unterschiedlicher Anwendung nur verschiedene Parameter.
3.7
Effektives Java
Durch effiziente Java Programmierung wird ein Performancezuwachs erreicht und
dadurch die Antwortzeit der Ergebnisse reduziert. Effektiv Java Programmierung ist
zum Beispiel Minimieren der Zugreifbarkeit von Klassen und Attributen, durch die
das Programm schnell ausgeführt wird. [9]
27
4 Evaluation und Dokumentation der Ergebnisse
Diese Arbeit ergibt die Antwortzeiten der Messungsergebnisse der Methodenaufrufe.
Die Antwortzeiten werden als normale durchschnittliche Zeit, maximale Antwortzeit
und Durchschnitt durch Standardabweichung der Methodenaufrufen dargestellt. Dabei
ist für einen Single Client die durchschnittliche Zeitmessungen nicht interessant. Die
Standardabweichung für einen Single Client hat als Ergebnis in NaN.
In dieser Studienarbeit beschreibt jedes Profil eine Laststufe, da sich die
Antwortzeiten in den Profilen dramatisch unterscheiden.
profil 0:
•
•
•
Please
0
number
number
number
number
1000 lesende Transaktionen (zum Beispiel get- und find-Methoden)
500 schreibende Transaktionen (zum Beispiel add-, update- und deleteMethoden)
Single Client
give the number of the group(from 0 to 5):
of
of
of
of
objects for single client = 1000
multiple clients = 1
objects to read = 1000
objects to write = 500
basic local:
The average, maximum and deviation time of the call for 1 local
client multiple clients (in msec)
add:
0.01,
0.01,
NaN
get:
0.0,
0.0,
NaN
update:
0.04,
0.04,
NaN
delete:
0.02,
0.02,
NaN
find:
0.03,
0.03,
NaN
basic remote:
The average, maximum and deviation time of the call for 1 remote
client multiple clients (in msec)
add:
4.236,
4.236,
NaN
get:
3.575,
3.575,
NaN
update:
5.208,
5.208,
NaN
delete:
3.104,
3.104,
NaN
find:
1.573,
1.573,
NaN
JDBC local:
The average, maximum and deviation time of the call for 1 local
client of JDBC multiple clients (in msec)
add:
86.134,
86.134,
NaN
get:
48.279,
48.279,
NaN
update:
93.574,
93.574,
NaN
delete:
104.07,
104.07,
NaN
find:
33.478,
33.478,
NaN
JDBC remote
The average, maximum and deviation time of the call for 1 remote
client of JDBC multiple clients (in msec)
add:
81.397,
81.397,
NaN
28
get:
update:
delete:
45.145,
83.22,
90.51,
find: 43.833,
45.145,
83.22,
90.51,
NaN
NaN
NaN
43.833,
NaN
session bean:
The average, maximum and deviation time of the call for 1 session
test multiple clients (in msec)
add:
11.417,
11.417,
NaN
get:
11.426,
11.426,
NaN
update:
13.38,
13.38,
NaN
delete:
10.292,
10.292,
NaN
find:
5.278,
5.278,
NaN
Add ()
Find()
Lokal Aufruf Remote
Aufruf
0.01 ms
4.23 ms
0.03 ms
1.573 ms
JDBC
Lokal
86.134 ms
33.478
Session
Bean
11.417 ms
5.278
Tabelle 1 Ergebnisse-Vergleich von Profile 0
Aus den obigen Ergebnissen kann man erkennen, dass entfernte schreibende
Methodenaufrufe wie zum Beispiel der add Methode 4.23 ms dauern, was wesentlich
langsamer ist als ein lokaler Methodeaufruf. Der Methodenaufruf der find Methode
braucht auch viel mehr Zeit bei einem entfernten Methodenaufruf als bei einem
lokalen Methodenaufruf.
Die Methodenaufrufe durch JDBC erfordern zusätzliche Zeit. Zum Beispiel braucht
die add Methode bei einem JDBC lokal Aufruf ca. 84 ms länger als bei einem
entfernten Methodenaufruf, dessen Daten nicht persistent sind.
Außerdem zeigen uns die Ergebnisse von Profil 0, dass die Methodenaufrufe durch
eine Session-Bean länger als bei einem entfernten Methodenaufruf dauern. Diese
kann man auch deutlich in der Tabelle 1 erkennen.
Nach dem direkten hintereinander Ausführen eines gleichen Profils unterscheiden
sich die Ergebnisse manchmal. Die Antwortzeiten im zweiten Ablauf sind meistens
kürzer als die des ersten Ablaufs. Der Grund dafür ist, dass die Daten beim ersten
Zugreifen in den Hauptspeicher gelagert werden.
29
Die unteren Ergebnisse sind vom zweiten Ablauf des Profil 0.
Profil 0
Please
0
number
number
number
number
give the number of the group(from 0 to 5):
of
of
of
of
objects for single client = 1000
multiple clients = 1
objects to read = 1000
objects to write = 500
basic local:
The average, maximum and deviation time of the call for 1 local
client multiple clients (in msec)
add:
0.0,
0.0,
NaN
get:
0.0,
0.0,
NaN
update:
0.02,
0.02,
NaN
delete:
0.02,
0.02,
NaN
find:
0.01,
0.01,
NaN
basic remote:
The average, maximum and deviation time of the call for 1 remote
client multiple clients (in msec)
add:
4.036,
4.036,
NaN
get:
3.485,
3.485,
NaN
update:
4.726,
4.726,
NaN
delete:
2.864,
2.864,
NaN
find:
1.523,
1.523,
NaN
JDBC local:
The average, maximum and deviation time of the call for 1 local
client of JDBC multiple clients (in msec)
add:
78.824,
78.824,
NaN
get:
41.95,
41.95,
NaN
update:
75.93,
75.93,
NaN
delete:
84.0,
84.0,
NaN
find:
33.078,
33.078,
NaN
JDBC remote
The average, maximum and deviation time of the call for 1 remote
client of JDBC multiple clients (in msec)
add:
77.572,
77.572,
NaN
get:
44.404,
44.404,
NaN
update:
89.75,
89.75,
NaN
delete:
90.328,
90.328,
NaN
find:
36.773,
36.773,
NaN
session bean:
The average, maximum and deviation time of the call for 1 session
test multiple clients (in msec)
add:
10.596,
10.596,
NaN
get:
10.555,
10.555,
NaN
update:
13.038,
13.038,
NaN
delete:
10.336,
10.336,
NaN
find:
4.807,
4.807,
NaN
30
Profil 1:
•
•
•
Please
1
number
number
number
number
1000 lesende Transaktionen
1000 schreibende Transaktionen (Unterschied zu Profil 0)
Single Client
give the number of the group(from 0 to 5):
of
of
of
of
objects for single client = 1000
multiple clients = 1
objects to read = 1000
objects to write = 1000
basic local:
The average, maximum and deviation time of the call for 1 local
client multiple clients (in msec)
add:
0.01,
0.01,
NaN
get:
0.02,
0.02,
NaN
update:
0.01,
0.01,
NaN
delete:
0.01,
0.01,
NaN
find:
0.04,
0.04,
NaN
basic remote:
The average, maximum and deviation time of the call for 1 remote
client multiple clients (in msec)
add:
4.787,
4.787,
NaN
get:
4.426,
4.426,
NaN
update:
2.684,
2.684,
NaN
delete:
1.492,
1.492,
NaN
find:
1.623,
1.623,
NaN
JDBC local:
The average, maximum and deviation time of the call for 1 local
client of JDBC multiple clients (in msec)
add:
89.358,
89.358,
NaN
get:
49.742,
49.742,
NaN
update:
38.355,
38.355,
NaN
delete:
41.68,
41.68,
NaN
find:
32.997,
32.997,
NaN
JDBC remote
The average, maximum and deviation time of the call for 1 remote
client of JDBC multiple clients (in msec)
add:
77.852,
77.852,
NaN
get:
44.544,
44.544,
NaN
update:
44.444,
44.444,
NaN
delete:
46.237,
46.237,
NaN
find:
36.813,
36.813,
NaN
session bean:
The average, maximum and deviation time of the call for 1 session
test multiple clients (in msec)
add:
12.548,
12.548,
NaN
get:
8.352,
8.352,
NaN
update:
6.058,
6.058,
NaN
delete:
5.928,
5.928,
NaN
find:
5.799,
5.799,
NaN
In diesem Profil werden mehr schreibende Transaktionen als in Profil 0 bearbeitet.
Aber man sieht, dass die benötigte Zeit von einem Methodeaufruf nicht deutlich
31
länger als in Profil 0 ist. Der Grund ist die Skalierbarkeit. Skalierbarkeit heißt, dass
die Leistung mit wachsender Datenbank-Größe und wachsender Nutzungsintensität
(Anzahl und Komplexität der Transaktionen) nicht kollabiert und stetes Wachstum
ohne Einbußen der Funktionalität und Leistung möglich ist. Maßzahlen für Leistung
sind Durchsatz und Antwortzeit. Als Durchsatz bezeichnet man die Anzahl
abgeschlossener Transaktionen pro Sekunde, als Antwortzeit die Zeitspanne zwischen
Beginn und Ende einer Transaktion. Gemessen werden hier die Antwortzeiten der
Methodenaufrufen. Es gibt enge Wechselwirkung zwischen Skalierbarkeit und
Leistung und es gibt normalerweise die gemeinsame Betrachtung: Performanz. [1]
Andererseits sieht man hier, dass manche Methodeaufrufe im Profil 1 sogar schneller
sind als in Profil 0. Gründe dafür sind schnellerer Zugriff auf Daten im
Hauptspeicher und die Verwendung der Technologie Hotspot JVM (siehe 2.7).
Profil 2
Please
2
number
number
number
number
give the number of the group(from 0 to 6):
of
of
of
of
objects for single client = 1000
multiple clients = 10
objects to read = 1000
objects to write = 500
basic local:
The average, maximum and deviation time of the call for 10 local
client multiple clients (in msec)
add:
0.7667999999999999,
0.931,
0.1969505296035304
get:
0.293,
0.781,
0.17216271373325875
update:
0.36419999999999997,
0.462,
0.036859492972940125
delete:
0.5519999999999999,
0.6,
0.057503623074260844
find:
0.3128,
0.351,
0.02527537229091679
basic remote:
The average, maximum and deviation time of the call for 10 remote
client multiple clients (in msec)
add:
35.0133,
37.204,
1.5290277993258041
get:
36.4233,
39.037,
2.015076896795753
update:
62.233999999999995,
69.58,
7.434630679013809
delete:
31.901799999999998,
39.036,
7.775446736719091
find:
14.693099999999998,
17.015,
1.80937063643688
JDBC local:
The average, maximum and deviation time of the call for 10 local
client of JDBC multiple clients (in msec)
add:
944.3681,
944.929,
0.31595057630374423
get:
0.6679999999999999,
1.001,
0.17537578700227308
update:
0.609,
0.782,
0.11415875885021796
delete:
0.7709999999999999,
0.94,
0.10848963084092415
find:
359.32789999999994,
359.477,
0.07960520641822923
JDBC remote
The average, maximum and deviation time of the call for 10 remote
client of JDBC multiple clients (in msec)
add:
1172.9918999999998,
1177.734,
3.262470789992724
get:
0.5919,
0.761,
0.14452716007726712
update:
1.2396,
1.862,
0.4516771708495645
delete:
0.9408,
1.762,
0.42384609366031806
32
find:
489.22079999999994,
491.127,
1.3495303545225519
session bean:
The average, maximum and deviation time of the call for 10 session
test multiple clients (in msec)
add:
86.743,
89.509,
2.0075877177459627
get:
49.956700000000005,
52.755,
2.5867217369567306
update:
100.52279999999999,
113.464,
7.049060407048745
delete:
96.84880000000001,
112.822,
13.17962745047573
find:
65.33489999999999,
69.42,
4.063168097542715
In diesem Profil laufen gleichzeitig 10 Clients. Aus den Ergebnissen kann man
erkennen, dass ein Methodenaufruf bei gleicher Anzahl von Objekten länger als bei
Single Client dauert (hier im Vergleich mit Profile 0). Zum Beispiel: in Profil 2
braucht das Ausführen einer Add Methode bei lokalem Aufruf durch JDBC 944.3681
ms und in Profil 0 dauert es nur 86.134 ms (durchschnittlichen Antwortzeit). Die
Messergebnisse zeigen uns, dass die Skalierbarkeit bis zu einer Grenze funktioniert
(Hier ist die Anzahl von Clients von 1 bis 10 gestiegen, unter der Bedienungen, dass
1000 Objekten, 1000 lesende Transaktionen und 500 schreibende Transaktionen
bearbeitet werden).
Den Unterschied zwischen den Antwortzeiten von Profil 3 und Profil 4 kann man in
den unteren Ergebnissen sehen. Zum Beispiel dauert ein entfernter Add Aufrufe
9.92ms im Profil 3 und im Profil 4 347.49 ms (Im Profil 4 laufen gleichzeitig 10
Clients und im Profil 3 gibt es nur einen Client).
Profil 3
Please
3
number
number
number
number
give the number of the group(from 0 to 6):
of
of
of
of
objects for single client = 100
multiple clients = 1
objects to read = 100
objects to write = 50
basic local:
The average, maximum and deviation time of the call for 1 local
client multiple clients (in msec)
add:
0.0,
0.0,
NaN
get:
0.1,
0.1,
NaN
update:
0.0,
0.0,
NaN
delete:
0.2,
0.2,
NaN
find:
0.0,
0.0,
NaN
basic remote:
The average, maximum and deviation time of the call for 1 remote
client multiple clients (in msec)
add:
9.92,
9.92,
NaN
get:
6.41,
6.41,
NaN
update:
12.42,
12.42,
NaN
delete:
5.6,
5.6,
NaN
find:
2.5,
2.5,
NaN
JDBC local:
The average, maximum and deviation time of the call for 1 local
client of JDBC multiple clients (in msec)
add:
435.03,
435.03,
NaN
33
get:
update:
delete:
find:
4.5,
8.02,
4.4,
89.33,
4.5,
8.02,
4.4,
89.33,
NaN
NaN
NaN
NaN
JDBC remote
The average, maximum and deviation time of the call for 1 remote
client of JDBC multiple clients (in msec)
add:
482.89,
482.89,
NaN
get:
0.6,
0.6,
NaN
update:
3.42,
3.42,
NaN
delete:
5.8,
5.8,
NaN
find:
34.35,
34.35,
NaN
session bean:
The average, maximum and deviation time of the call for 1 session
test multiple clients (in msec)
add:
28.34,
28.34,
NaN
get:
14.72,
14.72,
NaN
update:
23.44,
23.44,
NaN
delete:
16.42,
16.42,
NaN
find:
12.02,
12.02,
NaN
Aus Profil 4 und Profil 5 sieht man, dass die Antwortzeit deutlich länger dauert, wenn
die Anzahl der gleichzeitig laufenden Clients von 10 bis 100 gestiegen ist. Ein lokale
Add Methodenaufruf dauert 10.61 ms in Profil 5 und 0.56 ms im Profil 4. Die Anzahl
der gleichzeitig laufende Clients im Profil 4 ist 10 und im Profil 5 100.
Profil 4
Please
4
number
number
number
number
give the number of the group(from 0 to 5):
of
of
of
of
objects for single client = 100
multiple clients = 10
objects to read = 100
objects to write = 50
basic local:
The average, maximum and deviation time of the call for 10 local
client multiple clients (in msec)
add:
0.56,
0.8,
0.32386554137309653
get:
0.37,
0.5,
0.2002775851439974
update:
0.38,
0.6,
0.19888578520235062
delete:
0.69999999,
1.2,
0.21602468994692864
find:
0.81,
1.0,
0.2330951164939612
basic remote:
The average, maximum and deviation time of the call for 10 remote
client multiple clients (in msec)
add:
47.49000000000001,
50.27,
1.583105246729422
get:
47.236000000000004,
52.57,
6.415930174183631
update:
45.20800000000001,
69.1,
22.574385090677936
delete:
11.798,
25.04,
7.515763877788249
find:
9.564,
20.63,
6.008603461334052
JDBC local:
The average, maximum and deviation time of the call for 10 local
client of JDBC multiple clients (in msec)
add:
959.741,
1017.06,
88.07398108030166
34
get:
update:
delete:
find:
515.463,
926.3699999999999,
913.4540000000001,
359.606,
526.16,
975.4,
920.74,
441.33,
13.34176570856429
18.07150796142923
8.241569699463277
34.276528477143714
JDBC remote
The average, maximum and deviation time of the call for 10 remote
client of JDBC multiple clients (in msec)
add:
936.6379999999999,
958.28,
10.792798833790355
get:
448.87299999999993,
450.05,
1.0372725989075622
update:
908.99,
912.72,
3.834953280897525
delete:
885.3700000000001,
890.08,
2.281544311304196
find:
362.062,
367.93,
6.399525676867688
session bean:
The average, maximum and deviation time of the call for 10 session
test multiple clients (in msec)
add:
135.044,
147.21,
8.894472940477
get:
105.42,
109.96,
3.045535895189692
update:
146.612,
164.62,
8.3152935406194
delete:
119.588,
177.66,
26.180194719588233
find:
75.251,
94.14,
14.095711286297924
Profil 5
Please
5
number
number
number
number
give the number of the group(from 0 to 6):
of
of
of
of
objects for single client = 100
multiple clients = 100
objects to read = 100
objects to write = 50
basic local:
The average, maximum and deviation time of the call for 100 local
client multiple clients (in msec)
add:
10.618099999999995,
18.63,
5.008228924439852
get:
9.071900000000012,
11.72,
0.9998340215791177
update:
6.437600000000012,
18.42,
1.722723425277549
delete:
6.892599999999999,
7.0,
0.15201422049375268
find:
4.302500000000003,
4.41,
0.1609590888481553
basic remote:
The average, maximum and deviation time of the call for 100 remote
client multiple clients (in msec)
add:
393.3281000000001,
445.85,
42.10712026678642
get:
434.8442999999997,
521.45,
111.0262990344307
update:
614.5062,
692.58,
104.85652657422959
delete:
193.12580000000014,
273.18,
33.9286503043482
find:
58.137699999999995,
110.16,
35.04229674726291
JDBC local:
The average, maximum and deviation time of the call for 100 local
client of JDBC multiple clients (in msec)
add:
11789.593300000006,
11854.35,
24.89338628871515
get:
45.350300000000004,
57.08,
3.1338801763302886
update:
104.83519999999999,
116.36,
9.453150880831087
delete:
85.50200000000001,
98.34,
4.862697011147438
find:
3782.4773000000014,
3794.16,
16.97253936912106
DBC remote
35
The average, maximum and deviation time of the call for 100 remote
client of JDBC multiple clients (in msec)
add:
12510.748699999998,
12563.77,
27.493341440164365
get:
73.3544,
83.12,
3.858274937708496
update:
139.96359999999996,
151.42,
7.758900463599231
delete:
114.57819999999994,
148.02,
10.805423664329709
find:
5633.636299999997,
5640.11,
4.342817512801481
session bean:
The average, maximum and deviation time of the call for 100 session
test multiple clients (in msec)
add:
1091.2162000000003,
1127.52,
40.94591016391643
get:
587.2357,
670.76,
35.118357634425244
update:
1396.6582000000008,
1542.22,
61.17624567682388
delete:
1227.6518,
1387.8,
93.59879529981012
find:
806.5785,
911.21,
61.09476420184292
Es können auch weitere Laststufen getestet werden, die noch mehr bearbeitende
Objekten oder Transaktionen haben. Die Antwortzeiten werden noch länger dauern,
da die Skalierbarkeit bis zu einer Grenze nicht mehr stabil bleibt. Es können keine
Messergebnisse mit Entity Bean aufgezeigt werden. Da JBoss die Beschreibung von
Entity Bean in Namensumgebung nicht findet.
Die Antwortzeiten der Methodenaufrufe sind sehr abhängig von der Anzahl der
gleichzeitig laufenden Clients, von der Anzahl der bearbeitenden Clients, von der
Anzahl der bearbeitenden Lese und Schreibe-Transaktionen. Dies stellt hohe
Anforderungen an die Ressourcen wie Prozessor, Speicherplatz, Netzverbindung
usw..
Um die Performanz zu erreichen gibt es einige Methoden. In der Implementierung
kann man PreparedStatement statt Statement benutzten, wenn eine Funktion
mehrmals in der Datenverarbeitung ausgeführt wird, da die SQL-Anfrage mittels
PreparedStatement vor-kompiliert werden. PreparedStatement ist auch besser zu
benutzen, wenn man viele Argumenten für einen besonderen SQL Befehl spezifiziert.
Um Skalierbarkeit zu erreichen, benutzt man auch Objekt Pool und Thread Pool im
Java System. Einige Objekten werden initialisiert, wenn das System gestartet ist. So
wird ein Objekt aus dem Objekt Pool abgeholt, wenn ein Objekt gebraucht wird. Ein
Objekt wird auch in den Objekt Pool zurückgegeben, wenn das Objekt nicht mehr
gebraucht wird. Ein Thread wird benutzt, um Objekte parallel aus dem Objekt Pool zu
holen und Objekte können dann gleichzeitig laufen. Um einen Thread zu erstellen
oder zu löschen, wird viel Zeit gebraucht. Wenn es einen Thread Pool gibt, wird ein
Thread vom Thread Pool abgeholt, wenn dieser gebraucht wird. Ein Thread bekommt
dann die benötigte Objekte direkt vom Objekt Pool. Nach der Benutzung eines
Threads, wird der Thread auch in den Thread Pool zurückgegeben. Durch Objekt Pool
und Thread Pool wird die Anwendung schneller ausgeführt. Instance Pool ist ein
Objekt Pool. Objekt Pool hat Lebenszyklus. Kurzgefasst ist EJB = Objekt Pool +
Entfernte Objekt Pool. Die Abbildung 4.1 erklärt die Realisierung des Objekt- und
Thread-Pools.
36
EJB Container/Server
Instanz Pool
1. druch home Interface
entfernte Objekt erstellen
Home
Objekt
Client
3.durch entfernte
Interface Bean aufrufen
Entfernte
Objekt
Abbildung 4.1: EJB Architektur
37
EJB
4.Bean
vom Pool
abrufen
5 Zusammenfassung und Ausblick
Aus den Ergebnissen kann folgendes zusammengefasst werden.
Ein entfernter Methodenaufruf dauert länger als ein lokaler Methodenaufruf. Das
Zugreifen von persistenten Daten, dauert länger als das Zugreifen von Daten, die nicht
persistent sind.
Bei der Programmierung von Datenbankanwendung und Serveranwendung sollte die
Skalierbarkeit eingehalten werden. Die Skalierbarkeit wird jedoch durch die Anzahl
der bearbeitenden Objekte und die Anzahl der gleichzeitig laufenden Clients
beeinflusst. Zum Beispiel ist die Antwortzeit der Add Methodenaufrufe durch JDBC
im Profil 2 944.3681 ms und im Profil 0 86.134 ms. In Profil 0 und Profil 2 sind
gleich Anzahl von Objekten bearbeitet. Nur gibt es im Profil 2 10 gleichzeitig
laufende Clients und im Profil 0 nur Single Client.
Jede Profil ist eine Laststufe, unter der Datendurchsätze und Antwortzeiten von
Methodeaufrufen stabil bleiben.
Um die Skalierbarkeit zu erreichen, gibt es mehrere Ansätze (und Hinweise).
Erster Ansatz:
Die gemeinsame Nutzung der Ressourcen durch Stateless Session reduziert die
Belastung des Servers. Hierdurch können die Funktionen von gleichzeitig laufenden
Clients schneller auf dem selben Server bearbeitet werden.
Zweiter Ansatz: die EJB-Leistung verbessern
Einige der wichtigen Verfahren zur Verbesserung der EJB-Leistung
Wenn die Anzahl der Interaktionen zwischen dem Client und dem Server reduziert
wird, sollte Anwendungen wesentlich schneller werden. Darüber hinaus gibt es noch
einige weitere Bereiche, in denen man die Leistung verbessern kann. Unter anderem
sind dies die folgenden Bereiche:
•
Mehr Caching von Eintity-Beans und Session-Beans
•
Bildung von Datenbankverbindungs-Pools
•
Schnellere Datenbank-Interface-Bibliotheken
•
Optimiertes Verfahren für lokale Aufrufe
•
Caching von Daten
Die meisten dieser Eigenschaften sollten in einem kommerziellen EJB-Behälter zur
Verfügung stehen. Eine der wichtigsten Eigenschaften, das Caching von Daten, ist in
EJB-Behälter nicht sehr verbreitet.
Manche Produkte von CMP-Maschine speichern die Daten im Cache, damit der
Behälter dann, wenn man erneut auf eine Bean zugreifen muss, die Bean-Daten nicht
38
von der Datenbank zu holen braucht, da sie bereits geladen sind. Diese Art von
Caching kann die Leistung erheblich verbessern, weil es einen Großteil der Zeit nicht
mit dem Schreiben, sondern dem Lesen von Daten verbringt.
Dritter Ansatz: Datenbankverbesserung
Auf der Datenbank Seite ist es notwendig, dass angemessene Indexe erstellt werden,
um die Anzahl gesuchter Datensätze zu reduzieren. Weitere Optimierungen der
Datenbank können durch die Vermeidung von gleichen Selektieren, Optimierung von
dem Datenbank Puffer, Vervollständigung von WHERE Klauseln, Ermöglichung
paralleler Abläufe, Erhöhung Linearer Abhängigkeit von Datensätze usw. erreicht
werden.
EJB ist für eine Client / Server Anwendung geeignet, wenn es kein
Zugangsschutzsystem zwischen Client und Server gibt. RMI ermöglicht nicht nur die
einfache Realisierung für verteilte Programmierung sondern erhöht die
Anwendungsleistung durch seine spezielle Struktur.
Session Fassade von J2EE Struktur ist wie eine Klammern in EJB. Sie hat mehrere
Vorteile: Wenige Netzverbindungskosten, Zusammenfassung der Aktivitäten in
Session Bean, Lockere Abhängigkeit zwischen Client und Entity Bean, Klare und
saubere Trennung zwischen Geschäftslogik und präsentierende Schicht, deswegen
erhöht Session Fassade die Effektivität der Anwendung, verstärkt die
Wiederverwendbarkeit und trennt Client, Geschäftslogik (Session Fassade) und Daten
Logik (Entity-Bean usw.).
J2EE ist nach den Ergebnissen und der passenden Theorie dieser Arbeit für eine
Client und Server Programmierung geeignet.
39
6 Appendix
A. Teil von der JAVA Implementierung
A.1 MIDSampleServices.java
package mid.ejb;
import java.rmi.RemoteException;
import java.rmi.Remote;
public interface MIDSampleServices extends Remote {
/**
* Adds a single MIDSampleObject.
*
* @param object the specified MIDSampleObject
* @return a generated key for the sepcified object
*/
public MIDSampleKey add(MIDSampleObject object) throws
RemoteException;
/**
* Retrieves the MIDSampleObject with the given key.
*
* @param key the given key
* @return the MIDSampleObject with the given key
*/
public MIDSampleObject get(MIDSampleKey key) throws
RemoteException;
/**
* Updates the MIDSampleObject with the given key.
*
* @param key the given key
* @param object the specified object
*/
public void update(MIDSampleKey key, MIDSampleObject object)
throws RemoteException;
/**
* Deletes the MIDSampleObject with the given key.
*
* @param key the given key
*/
public void delete(MIDSampleKey key) throws RemoteException;
/**
* Retrieves all MIDSampleObjects with the given attribute.
*
* Each attribute is a key-value pair of strings. All
MIDSampleObjects having an
* attribute entry matching the given attribute are returned.
*
* @param attributeKey the given attribute key
* @param attributeValue the given attribute value
40
* @return an array of all MIDSampleObjects with the given
attribute
*/
public MIDSampleKey[] find(String attributeKey, String
attributeValue) throws RemoteException;
}
A.2 MIDSampleServicesImpl.java
package mid.impl.basic;
import java.util.*;
import java.rmi.*;
import java.rmi.server.UnicastRemoteObject;
import mid.ejb.*;
/**
* @author d042318
*/
public class MIDSampleServicesImpl extends UnicastRemoteObject
implements MIDSampleServices/*, Remote*/ {
public MIDSampleServicesImpl()throws RemoteException {
super();
}
private
private
private
private
Map l = new HashMap(5000, 0.1f);
Set s = l.keySet();
Iterator keyIterator = s.iterator();
long currentId = 1;
/**
* Adds a single MIDSampleObject.
*
* @param object the specified MIDSampleObject
* @return a generated key for the sepcified object
*/
public synchronized MIDSampleKey add(MIDSampleObject object) {
MIDSampleKey key =
MIDSampleKey.createMIDKey(currentId++);
l.put(key, object);
return key;
}
/**
* Retrieves the MIDSampleObject with the given key.
*
* @param key the given key
* @return the MIDSampleObject with the given key
*/
public synchronized MIDSampleObject get(MIDSampleKey key) {
Object o = new Object();
o = l.get(key);
41
return (MIDSampleObject)o;
}
/**
* Updates the MIDSampleObject with the given key.
*
* @param key the given key
* @param object the specified object
*/
public synchronized void update(MIDSampleKey key,
MIDSampleObject object) {
l.remove(key);
l.put(key, object);
}
/**
* Deletes the MIDSampleObject with the given key.
*
* @param key the given key
*/
public synchronized void delete(MIDSampleKey key) {
Set subObjectsKey = new HashSet();
MIDSampleObject mo = null;
MIDSampleKey supKey, subKey;
while(keyIterator.hasNext()){
supKey = (MIDSampleKey)keyIterator.next();
mo = (MIDSampleObject)l.get(supKey);
int subZahl = mo.getSubObjectCount();
if( subZahl!= 0){
for(int i =0; i<subZahl; i++){
subKey = mo.getSubObject(i);
subObjectsKey.add(subKey);
}
}
}
if(!subObjectsKey.contains(key)){
l.remove(key);
}
}
/**
* Retrieves all MIDSampleObjects with the given attribute.
*
* Each attribute is a key-value pair of strings. All
MIDSampleObjects having an
* attribute entry matching the given attribute are returned.
*
* @param attributeKey the given attribute key
* @param attributeValue the given attribute value
* @return an array of all MIDSampleObjects with the given
attribute
*/
public synchronized MIDSampleKey[] find(String attributeKey,
String attributeValue) {
42
List keys = new ArrayList();
MIDSampleObject mo = null;
MIDSampleKey key = null;
while(keyIterator.hasNext()){
key = (MIDSampleKey)keyIterator.next();
mo = (MIDSampleObject)l.get(key);
String moValue =
mo.getAttributeValue(attributeKey);
if(moValue == null){ /*"do nothing";*/ }
else if(moValue.equals(attributeValue)){
keys.add(key);
}
}
MIDSampleKey[] keysArray = new MIDSampleKey[keys.size()];
keys.toArray(keysArray);
return keysArray;
}
public static void main(String[] args){
System.out.println("do nothing");
String motdService = System.getProperty("service",
"MIDSampleServicesImpl");
if (System.getSecurityManager() == null){
System.setSecurityManager(new
RMISecurityManager());
}
try
{
MIDSampleServicesImpl impl = new
MIDSampleServicesImpl();
Naming.rebind("//localhost/"+motdService, impl);
}
catch (Exception exc){
exc.printStackTrace();
}
}
}
A.3 MIDSampleServicesSessionBean.java
/*
* Created on 23.10.2003
*/
package mid.ejb;
import
import
import
import
import
import
import
import
java.rmi.RemoteException;
java.util.ArrayList;
java.util.HashMap;
java.util.HashSet;
java.util.Iterator;
java.util.List;
java.util.Map;
java.util.Set;
import javax.ejb.CreateException;
43
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
/**
* @author d042318
*
* @ejb.bean name = "MIDSampleServicesSession"
*
display-name = "MIDSampleServicesSession EJB"
*
description = "MIDSample Session Bean"
*
view-type = "remote"
*
jndi-name = "ejb/mid/MIDSampleServicesSession"
*
*/
public class MIDSampleServicesSessionBean implements
MIDSampleServices, SessionBean {
private SessionContext context;
public MIDSampleServicesSessionBean()
throws RemoteException {
super();
}
/**
* @throws CreateException
* @ejb.create-method
*/
public void ejbCreate() throws CreateException {
}
public void ejbActivate() throws EJBException, RemoteException
{
}
public void ejbPassivate() throws EJBException, RemoteException
{
}
public void ejbRemove() throws EJBException, RemoteException {
}
public void setSessionContext(SessionContext aContext)
throws EJBException, RemoteException {
context = aContext;
}
private Map l = new HashMap();
private long currentId = 1;
/**
* Adds a single MIDSampleObject.
*
* @param object the specified MIDSampleObject
* @return a generated key for the sepcified object
*
* @ejb.interface-method view-type = "remote"
*/
public MIDSampleKey add(MIDSampleObject object) {
44
MIDSampleKey key =
MIDSampleKey.createMIDKey(currentId++);
l.put(key, object);
return key;
}
/**
* Retrieves the MIDSampleObject with the given key.
*
* @param key the given key
* @return the MIDSampleObject with the given key
*
* @ejb.interface-method view-type = "remote"
*/
public MIDSampleObject get(MIDSampleKey key) {
Object o = new Object();
o = l.get(key);
return (MIDSampleObject)o;
}
/**
* Updates the MIDSampleObject with the given key.
*
* @param key the given key
* @param object the specified object
*
* @ejb.interface-method view-type = "remote"
*/
public void update(MIDSampleKey key, MIDSampleObject
object) {
l.remove(key);
l.put(key, object);
}
/**
* Deletes the MIDSampleObject with the given key.
*
* @param key the given key
*
* @ejb.interface-method view-type = "remote"
*/
public void delete(MIDSampleKey key) {
Set subObjectsKey = new HashSet();
Set s = l.keySet();
MIDSampleObject mo = null;
MIDSampleKey supKey, subKey;
Iterator keyIterator = s.iterator();
while(keyIterator.hasNext()){
supKey = (MIDSampleKey)keyIterator.next();
mo = (MIDSampleObject)l.get(supKey);
int subZahl = mo.getSubObjectCount();
if( subZahl!= 0){
for(int i =0; i<subZahl; i++){
subKey = mo.getSubObject(i);
45
subObjectsKey.add(subKey);
}
}
}
if(!subObjectsKey.contains(key))
l.remove(key);
else{
}
}
/**
* Retrieves all MIDSampleObjects with the given
attribute.
*
* Each attribute is a key-value pair of strings. All
MIDSampleObjects having an
* attribute entry matching the given attribute are
returned.
*
* @param attributeKey the given attribute key
* @param attributeValue the given attribute value
* @return an array of all MIDSampleObjects with the given
attribute
*
* @ejb.interface-method view-type = "remote"
*/
public MIDSampleKey[] find(String attributeKey, String
attributeValue) {
List keys = new ArrayList();
Set s = l.keySet();
MIDSampleObject mo = null;
MIDSampleKey key = null;
Iterator keyIterator = s.iterator();
while(keyIterator.hasNext()){
key = (MIDSampleKey)keyIterator.next();
mo = (MIDSampleObject)l.get(key);
String moValue =
mo.getAttributeValue(attributeKey);
if(moValue == null){
}
else if(moValue.equals(attributeValue)){
keys.add(key);
}
}
MIDSampleKey[] keysArray = new
MIDSampleKey[keys.size()];
keys.toArray(keysArray);
return keysArray;
}
}
46
B. META-INF(von Session Bean)
B.1. Ejb-jar.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise
JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd">
<ejb-jar >
<description><![CDATA[No Description.]]></description>
<display-name>Generated by XDoclet</display-name>
<enterprise-beans>
<!-- Session Beans -->
<session >
<description><![CDATA[MIDSample Session ean]]></description>
<display-name>MIDSampleServicesSession EJB</display-name>
<ejb-name>MIDSampleServicesSession</ejb-name>
<home>mid.interfaces.MIDSampleServicesSessionHome</home>
<remote>mid.interfaces.MIDSampleServicesSession</remote>
<ejb-class>mid.ejb.MIDSampleServicesSessionBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
<!-- To add session beans that you have deployment descriptor
info for, add a file to your XDoclet merge directory called
session-beans.xml that contains the <session></session> markup
for those beans.-->
<!-- Entity Beans -->
<!-- To add entity beans that you have deployment descriptor
info for, add a file to your XDoclet merge directory called
entity-beans.xml that contains the <entity></entity> markup for
those beans.-->
<!-- Message Driven Beans -->
<!-- To add message driven beans that you have deployment
descriptor info for, add a file to your XDoclet merge directory
called message-driven-beans.xml that contains the <messagedriven></message-driven> markup for those beans.-->
</enterprise-beans>
<!-- Relationships -->
<!-- Assembly Descriptor -->
<assembly-descriptor >
<!--To add additional assembly descriptor info here, add a file to
your XDoclet merge directory called assembly-descriptor.xml that
contains he <assembly-descriptor></assembly-descriptor> markup.-->
<!-- finder permissions -->
<!-- transactions -->
<!-- finder transactions -->
</assembly-descriptor>
</ejb-jar>
47
B.2 jboss.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 3.0//EN"
"http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd">
<jboss>
<enterprise-beans>
<!-To add beans that you have deployment descriptor info for, add
a file to your XDoclet merge directory called jboss-beans.xml
that contains
the <session></session>, <entity></entity> and <messagedriven></message-driven>
markup for those beans.
-->
<session>
<ejb-name>MIDSampleServicesSession</ejb-name>
<jndi-name>ejb/mid/MIDSampleServicesSession</jndi-name>
</session>
</enterprise-beans>
<resource-managers>
</resource-managers>
</jboss>
B.3 application.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE
Application 1.3//EN" "http://java.sun.com/dtd/application_1_3.dtd">
<application>
<display-name>mid</display-name>
<module>
<ejb>MIDSampleServicesEJB.jar</ejb>
</module>
</application>
48
7 Literatur
[1] Datenbanksysteme
Konzepte und Techniken der Implementierung
Theo Härder Erhard Rahm
Springer-Verlag 1999
[2] Über JBoss
http://www.jboss.org
[3]Über Client/Server
http://www.sei.cmu.edu/str/descriptions/clientserver_body.html
[4] Über J2EE
Developer’s Guide
JSP, Servletes, EJB 2.0, JNDI, JMS, JDBC, Corba, XML, RMI
.Mark Wutka
Markt + Technik Verlag 2002
[5] über JBoss IDE
JBoss-DIE 1.2.2- Tutorial Guide (http://www.jboss.org)
[6] Über JBoss
JBoss-DIE 1.2.2 Tutorial Guide
[7] Enterprise JavaBeans Technology Fundmentals
http://developer.java.sun.com/developer/onlineTraining/EJBIntro/EJBIntro.html
[8] Java Enterprise in a nutshell
Farley, Jim
O’Reilly, 2003
[9] Effective Java
Programming Language Guide
Joshua Bloch
[10] Entwurfsmuster-- Elemente wiederverwendbarer objektorientierter Software
Erich Gamma
1. Aufl., 5., korrig
49
Herunterladen