Integration der Object Server Suite von Poet in Scone

Werbung
Vergleich von Objektpersistenzmechanismen
für Java: Integration der Object Server Suite
von Poet in Scone
Björn Stephan
Betreuer:
Prof. Dr. W. Lamersdorf
Universität Hamburg
Fachbereich Informatik
Vogt-Köll-Straße 30
22527 Hamburg
18. April 2002
ii
Studienarbeit:
Vergleich von Objektpersistenzmechnismen in Java:
Integration der Object Server Suite von Poet in Scone
Autor:
Björn Stephan
Morgensternsweg 5
22305 Hamburg
E-Mail: [email protected]
Betreuer:
Prof. Dr. Winfried Lamersdorf
Arbeitsgruppe Verteilte Systeme und Informationssysteme (VSIS)
Dipl. Inform. Harald Weinreich
Arbeitsgruppe Verteilte Systeme und Informationssysteme (VSIS)
Universität Hamburg
Fachbereich Informatik
Vogt-Kölln-Straße 30
22527 Hamburg
Inhaltsverzeichnis
1 Einleitung
1
2 Scone
2.1 Architektur . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Problemstellung . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3
8
3 Grundlagen der Persistenz
3.1 Persistenzmechanismen . . . . . . . . . . .
3.2 Datenbankarchitekturen . . . . . . . . . .
3.3 Grundkonzepte von Datenbankensystemen
3.4 Das relationale Datenmodell . . . . . . . .
3.5 Das objektorientierte Datenmodell . . . .
3.6 Objektrelationale Datenbanken . . . . . .
3.7 Java Serialisierung . . . . . . . . . . . . .
3.8 EJB, JDO und XML . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11
12
13
14
16
17
19
20
21
4 Integration der Objektdatenbank
4.1 Änderung der Paketstruktur . . . . . .
4.2 Persistenzfähige Klassen . . . . . . . .
4.3 Orphaned Objects . . . . . . . . . . .
4.4 Konzept der Schattenobjekte . . . . . .
4.4.1 Integration der Schattenobjekte
4.5 Konzept der Info-Objekte . . . . . . .
4.5.1 Integration der Info-Objekte . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
23
24
26
28
31
32
37
38
5 Resümee
.
.
.
.
.
.
.
.
.
.
.
.
.
.
41
iii
iv
INHALTSVERZEICHNIS
Kapitel 1
Einleitung
Sieht man sich heutzutage das World Wide Web an, so ist festzustellen, dass
sich auf Seiten des Browsers seit den Tagen von Mosaic (s. Abb 1.1) nicht viel
verändert hat: Einer wachsenden Informationsmenge steht ein Navigationsinterface gegenüber, dass nur geringfügigen Änderungen unterzogen wurde.
Abbildung 1.1: Mosaic Web Browser (1994/1995)
Vor diesem Hintergrund und des daraus enstehenden Lost In HyperspaceProblems, existieren zwar viele Lösungsansätze, aber jedes Projekt zur Verbesserung bzw. Erweiterung von Webbrowsern muss dabei von vorn anfangen: Es fehlt ein Fundament auf das Prototypen aufgesetzt werden können,
1
2
KAPITEL 1. EINLEITUNG
ohne dass z.B. eigene Persistenzmechanismen implementiert werden müssen.
Hier steht mit Scone eine Prototyping-Plattform zur Verfügung, die es
ermöglicht Navigationsprototypen schnell umzusetzen. Erreicht wird dies
durch ein Plugin-Konzept. Ein Navigationsprototyp, der mit Hilfe von Scone
implementiert wird, wird als ein Scone-Plugin realisiert und kann auf alle
Komponenten von Scone zu greifen. Scone wurde unter Leitung von Harald
Weinreich [20] entwickelt und ist vollständig in Java implementiert.
Das Konzept von Scone als Prototyping-Plattform hat sich als erfolgreich
herausgestellt. Aktuelle Projekte sind u.a. Hyperscout [21] von Harald Weinreich oder BrowsingIcons [13] von Matthias Mayer. Weiterhin wurde Scone
erfolgreich in einigen kleineren Projekten am Fachbereich Informatik der Universität Hamburg eingesetzt.
Um die Navigation im WWW zu verbessern, wird die zur Verfügung stehende Information angereichert. Damit diese Information auch in einer späteren
Sitzung wieder zur Verfügung steht, ist ein Persistenzmechanismus notwendig. Eine große Menge an gleich strukturierten Daten – wie die von Scone
gesammelten Informationen – wird in aller Regel in Datenbanken gesichert.
Aktuelle Datenbanksysteme lassen sich hauptsächlich in zwei Arten unterteilen: zum einem in die relationalen Datenbanken (RDBMS, Relational
Database Management Systems), zum anderen in die objektorientierten Datenbanken (OODBMS, Object Oriented Database Management Systems).
Thema dieser Studienarbeit ist der Persistenzmechanismus von Scone: Dieser
basierte bislang auf der relationalen Datenbank MySQL [10] und wurde im
Rahmen dieser Arbeit durch die objektorientierte Datenbank Object Sever
”
Suite“ von Poet [15] ersetzt. Dabei fand eine komplett neue Implementierung
des Persistenzmechanismuses statt, wobei die die vorhandene API soweit als
möglich beibehalten oder gar vereinfacht wurde.
Zunächst wird in Kapitel 2 die Architektur von Scone beschrieben. In Kapitel
3 werden wichtige Persistenzmechanismen für Java vorgestellt und verglichen.
Kapitel 4 beschreibt dann die vollzogenen Schritte bei der Umstellung von
Scone und geht auf dabei aufgetretene Probleme ein. Ein Resümee schließt
die Arbeit ab.
Kapitel 2
Scone
Scone wird im Rahmen des Hyperscout-Pojektes [21] unter der Leitung
von Harald Weinreich entwickelt. Scone ist eine Protyping-Plattform, die
es ermöglicht verschiedenste Navigationsprototpen für das World Wide Web
umzusetzen.
Da das Thema dieser Studienarbeit der Persistenzmechanismus von Scone
ist, wird in Abschnitt 2.1 die Architektur von Scone vorgestellt. Die fünf
Komponenten von Scone werden jeweils kurz erläutert. Abschnitt 2.2 geht
dann auf die Problemstellung der Arbeit ein.
2.1
Architektur
Im folgenden stelle ich die Architektur (Abb. 2.1) von Scone vor. Die fünf
Komponenten
• Proxy: Paket scone.proxy,
• Persistenz: Paket scone.netobjects,
• Robot: Paket scone.robot,
• Usertracking: Paket scone.accesstracking und
• RAS - Remote Access Server: Paket scone.ras
werden kurz beschrieben.
3
4
KAPITEL 2. SCONE
Scone
Proxy
Generator
Applets, Images...
Browser
Modified HTML/XML
User Tracking
Database
Cache
Web
Events
RAS
Handler
Robot
Task
Custom
data
Applet
Abbildung 2.1: Scone-Architektur aus [21]
Proxy Anstatt einen eigenen Proxy zu implementieren, wird der Proxy
WBI [8, 2] (sprich: Webbi) von IBM Almaden verwendet. WBI steht für
Web Based Intermediary. Da WBI nicht direkt den Anforderungen von Scone entsprach, wurde WBI in Kooperation mit IBM an Scone angepasst. WBI
arbeitet mit dokumentenbasierten Regeln und basiert auf einer BytestromAuswertung. Die Möglichkeit eigene Plugins für WBI zu implementieren,
machen WBI zu einem flexibel konfigurierbaren Proxy. Diese Plugins werden aus MEGs (Monitor Editor Generator) zusammengesetzt. Diese MEGs
sind Java Klassen, die auch vom Pluginprogrammierer selbst implementiert
werden können. WBI kennt folgende vier MEGs:
• Request Editor: Ändere Anfragen
• Generator: Erzeuge Rückgabe
• Document Editor: Bearbeite Antwort
• Monitor: Beobachte Übertragung
2.1. ARCHITEKTUR
5
Aufbauend auf dieser Architektur stellt Scone einen Standard-Tokenhandler
zur Verfügung. Dieser Handler arbeitet auf einem Tokenstream, der gezielt Token für alle Html-Tags und Links berücksichtigt. Implementiert
ist der Handler in der Klasse scone.proxy.ParsingMeg. Die Methode
handleRequest der Klasse ParsingMeg analysiert WWW-Dokumente und
extrahiert eine Reihe von Meta-Daten. Dies sind unter anderem:
• Titel
• Meta-Tags (Autor, Keywords, etc.)
• Strukturinformationen (Linkliste, etc.)
Die extrahierten Daten werden dann, über die Klassen des Paketes
scone.netobjects persistent gemacht.
Persistenz Abb. 2.2 zeigt das Entity-Relationship-Modell von Scone für
die relationale Datenbank MySQL. Das Paket scone.netobjects stellt Objekte bereit, die tatsächliche Objekte aus dem Internet und dem WWW repräsentieren. Diese Objekte werden in der Scone-Datenbank persistiert. Abb.
4.1 auf Seite 25 zeigt die Klassenstruktur des Paketes scone.netobjects.
Das Paket scone.netobjects persistiert Informationen über
• Objekte des WWW,
• Links (Link),
• eingebundene Objekte (Inclusion),
• Server (Server),
• zur Benutzung (Access) und den Benutzern (User).
Objekte des WWW werde unterteilt in Netzknoten (NetNode) und HTMLKnoten (HtmlNode). Ein Netzknoten repräsentiert beliebige Objekte im
WWW. Ein HTML-Knoten ist ein Knoten, der explizit eine HTML-Seite repräsentiert. Die Klasse SimpleUri entspricht der Definition nach RFC 2396
[12] und repräsentiert Internetadressen.
Ich stelle hier nun kurz vor, wie Netzknoten mit MySQL als Datenbank persistiert werden. Die Methode handleRequest der Klasse
scone.proxy.ParsingMeg implementiert den Standard-Tokenhandler. Die
6
KAPITEL 2. SCONE
LinkTable
InclusionTable
parentNodeId
childNodeId
tag
n
linkId
n
n
fromNodeId
n
toNodeId
fragment
...
Node2KeyTable
n
nodeId
keywordId
NetNodeTable
HtmlDocumentTable
nodeId
0..1
1
AccessTable
userId
n
nodeId
keyword
n
1
keywordId
ServerTable
1
nodeId
uri
...
titel
...
KeywordTable
1
1
host
titel
...
UserTable
n
n
time
...
userId
personId
...
PersonTable
1
personId
firstName
...
GroupTable
Person2GroupTable
1
n
1
personId
groupId
groupId
n
Abbildung 2.2: ER-Diagramm von Scone
Methode arbeitet auf einem Tokenstream, der von der Klasse SconePipe
zur Verfügung gestellt wird. Die Klasse SconePipe befindet sich im Paket scone.util.tokenstram. Den Klassen der Form xxxCache kommt neben der Cache-Funktionalität noch eine spezielle Rolle zu: Die Cache Klassen kapseln die Datenbankanbindung, d.h. ein Instanz von NetNode wird
nicht direkt instanziert sondern über die get-Methode von NetNodeCache.
Mit NetNode node = NetNodeCache.get("http://www.informatik.unihamburg.de") wird ein Netzknoten angefordert. Die get-Methode von
NetNodeCache durchsucht den Cache, ob der angeforderte NetNode bereits
im Cache gespeichert ist. Ist dies nicht der Fall, so erzeugt NetNodeCache
eine neue Instanz von NetNode und puffert diesen. Der neu erzeugte NetNode
2.1. ARCHITEKTUR
7
lädt, sofern er schon in der Datenbank existiert, seine Daten, anderenfalls
erzeugt er einen neuen Datenbankeintrag. Dabei wird das Laden der Daten
oder das Erzeugen eines neuen Datenbankeintrages von der Klasse DBTable
übernommen, damit obliegt ihr die Konsistenzwahrung der Datenbank. Dadurch wird gewährleistet, dass jede Instanz von NetNode zu einem Datenbankeintrag korrespondiert und diese Korrespondenz nicht manuell erzeugt
werden muss. Durch diesen Mechanismus braucht der Nutzer sich nicht mehr
um datenbankspezifische Probleme wie Konsistenzwahrung etc. zu kümmern.
Er kann mit persistenten Objekten umgehen wie mit transienten Objekten.
Dieser Mechanismus wird auch als transparente Persistenz bezeichnet [18].
Die Klassen Link, HtmlNode, Server etc. werden in derselben Art wie
NetNode gespeichert.
Robot Der Robot von Scone wurde im Rahmen einer Studienarbeit
von Frank Wollenweber entwickelt. Der Robot basiert konzeptionell auf
WebSphinx (Specific Processors for HTML INformation eXtraction) von
der Carnegie Mellon University [3, 14]. Konzipiert ist der Robot als ein WebAgent, der einen kleinen Ausschnitt des Web schnell erfassen kann und flexibel konfigurierbar ist. Er verfügt unter anderem über folgende Eigenschaften:
• multi-threaded,
• in Scone integriert, nutzt z.B. die Möglichkeiten des Parsing, StandardTokenhandlers etc.,
• einfache, aber mächtige API,
• flexibel konfigurierbar über Filter- und Classifier-Modell.
Für mehr Informationen über den Robot und seine Architektur verweise ich
auf die Studienarbeit von Frank Wollenweber [22].
Usertracking Mit dem Usertracking kann das Navigationsverhalten eines
Benutzers protokolliert werden, folgende Navigationsaktionen z.B. können
aufgezeichnet werden:
• Link angewählt,
• Formular ausgefüllt,
8
KAPITEL 2. SCONE
• Back-Button gedrückt.
Die Protokollierung ermöglicht es angebotene Information an den Nutzer anzupassen. Das Usertracking unterstützt auch auch die Evaluation von SconePlugins. Evaluierbarkeit ist ein wichtiges Kriterium bei der Entwicklung von
neuen Navigationswerkzeugen.
RAS Das Remote Access System ermöglicht die Kommunikation zwischen
verschiedenen Scone-Instanzen und mit Applets, die in Seiten eingebunden
sind. Dieser Mechanismus wird beispielsweise in Hyperscout 2 eingesetzt.
Durch die Möglichkeit mit Applets zu kommunizieren, werden die eingeschränkten Fähigkeiten von DHTML um die Möglichkeiten von Java Applets
erweitert.
Weitere Paktete Neben den vorgestellten fünf Komponenten von Scone,
die durch jeweils ein Paket realisiert sind, gibt es noch drei weitere Pakete:
• Das Paket scone stellt die Hauptklassen zum Starten von Scone zur
Verfügung.
• Das Paket scone.util stellt Hilfs- und Werkzeugklassen zur Konfiguration von Plugins und Scone, sowie zur Verarbeitung von Dokumenten
zur Verfügung.
• Das Paket scone.util.tokenstream stellt die Tokenstreams für die
Tokenhandler zur Verfügung.
2.2
Problemstellung
Ausgangspunkt dieser Studienarbeit sind zwei Beobachtungen:
• Die eingesetzte relationale Datenbank ermöglicht keine komplexen Abfragen auf Objektstrukturen.
• Der Paradigmenbruch zwischen eingesetztem Persistenzmechanismus
und Programmiersprache sollte vermieden werden.
Letzteres wird als Impedance Mismatch bezeichnet und genauer in [16] beschrieben:
2.2. PROBLEMSTELLUNG
9
Damit ist die Kluft zwischen der deklarativen, mengenorientier”
ten Anfragesprache SQL eines RDBMS und dem prozeduralen,
satzorientierten Paradigma der in der Regel zur Implementierung
von Anwendungen genutzten Programmiersprachen gemeint, die
durch unterschiedliche Typsysteme noch vergrößert wird.“
In SQL existiert nur ein sehr begrenzter Satz an vordefinierten Typen und
es ist nicht möglich eigene Typen zu definieren. Die Kluft zwischen den Paradigmen muss also vom Entwickler selbst überbrückt werden.
Ziel dieser Studienarbeit war es einen Persistenzmechanismus zu finden, der
komplexe Abfragen ermöglicht und den Impedance Mismatch vermeidet. Es
wurden mehrere Persistenzmechanismen für Java untersucht, von denen dann
einer ausgewählt und integriert wurde.
10
KAPITEL 2. SCONE
Kapitel 3
Grundlagen der Persistenz
In [7] wird Persistenz als Bestehenbleiben eines Zustandes über einen länge”
ren Zeitraum“ definiert. Wenn im folgenden von Persistenz die Rede ist, so
ist darunter genauer zu verstehen:
Persistenz ist ein Mechanismus, der es erlaubt, die Lebenszeit von Daten über
die Blockstruktur eines Programms und Gültigkeitsbereiche von Variablen
hinaus zu verlängern. Hiermit verbunden ist auch die Sicherheit, die Daten
auch bei Ausfall von Software und Hardware zu erhalten.
In einem persistenten System werden Daten also über das Programmende
hinaus gespeichert. Sie stehen damit bei einem erneuten Start des Programms
wieder zur Verfügung. Zudem fungiert ein Persistenzmechanismus bei großen
Datenmengen als Erweiterung des knappen Arbeitsspeichers. Mit großen Datenmengen sind hier Daten im Giga- oder sogar im Terabyte Bereich gemeint.
In Abschnitt 3.1 wird eine Unterteilung von Persistenzmechanismen in drei
Kategorien vorgenommen. In Abschnitt 3.2 werden zwei Datenbankarchitekturen vorgestellt. Abschnitt 3.3 geht dann auf die grundlegenden Konzepte von Datenbanksystemen ein. Danach wird in den Abschnitten 3.4, 3.5
und 3.6 nacheinander das relationale, objektorientierte und objektrelationale
Datenmodell erläutert. In Abschnitt 3.7 wird die Java eigene Serialisierung
vorgestellt und im letzten Abschnitt 3.8 werden EJB, JDO und XML als
Persistenzmechanismen kurz erläutert.
11
12
KAPITEL 3. GRUNDLAGEN DER PERSISTENZ
3.1
Persistenzmechanismen
Es stehen mehrere Mechanismen zur Verfügung um Daten persistent zu machen. Für Java lassen sich die zur Verfügung stehenden Persistenzmechanismen grob in drei Kategorien unterteilen und zwar Dateien, Datenbanken und
orthogonal persistente Systeme.
Dateien Die Speicherung in Dateien lässt sich weiter in
• eigene Formate,
• oder standardisierte Formate, z.B. GIF, MP3
unterteilen. Eine Mischform stellt die Neuentwicklung XML dar.In diese Kategorie fällt auch die Java eigene Serialisierung. Sie wird kurz in
Abschnitt 3.7 vorgestellt.
Datenbanken Datenbanken unterscheidet man nach dem eingesetzten Datenmodell in
• Netzwerk-Datenbanken,
• hierarchische Datenbanken1 ,
• relationale Datenbanken,
• objektorientierte Datenbanken oder
• objektrelationale Datenbanken.
Orthogonal persistente Systeme Orthogonal persistente Systeme sind
Systeme, die die Anforderungen der orthogonalen Persistenz erfüllen.
Orthogonalen Persistenz ist wie folgt definiert (nach [16]):
• Typ-Orthogonalität: Persistenz ist für alle Objekte der Programmiersprache verfügbar.
• Transitive Persistenz : Alle Objekte, die von einem persistenten
Wurzelobjekt erreichbar sind, werden ebenfalls persistiert.
• Persistenz-Unabhängigkeit: Es ist irrelevant, ob Programmcode
mit persistenten oder transienten Objekten arbeitet. Der Code
für beide Fälle ist identisch.
1
Die Netzwerk- und Hierarchischen Datenbanken haben nur noch historische Bedeutung, deshalb werden sie hier nicht näher besprochen. Bei näherem Interesse verweise ich
auf das Buch von P.C. Lockemann und J.W. Schmidt [11].
13
3.2. DATENBANKARCHITEKTUREN
Benutzerschnittstelle
Benutzerschnittstelle
Anwendungslogik
Client
Corba, RMI, JDO, EJB, ...
Client
Anwendungslogik
Applikations−
server
DB−Schnittstelle
DB−Schnittstelle
DBMS−Protokoll
DBMS−Protokoll
DB−Server
a 2-Schichten-Architektur
DB−Server
b 3-Schichten-Architektur
Abbildung 3.1: Client-Server-Architekturen aus [16]
Ein Beispiel für ein orthogonal persistentes System ist das von M. Atkinson et. al. (University of Glasgow) und M. Jordon et. al. (Sun Microsystems) implementierte PJama-System [6, 16].
3.2
Datenbankarchitekturen
Die meisten modernen Datenbankanwendungen sind als Client-ServerArchitekturen realisiert. Dies bietet unter anderem die Möglichkeit, Daten
mehreren Clients zur Verfügung zu stellen und Datenredundanz zu vermeiden. Bei einer Client-Server-Architektur spielt dann noch die Frage eine Rolle,
wie eng Anwendungsprogramm und Speicherung gekoppelt sein sollen. Hier
kann man sich entweder für eine 2-Schichten-Architektur (Abb. 3.1a) oder
eine 3-Schichten-Architektur (Abb. 3.1b) entscheiden.
Jeder der in Abschnitt 3.1 vorgestellten Persistenzmechanismen läßt sich in
beiden Architekturen einsetzen. Im Falle von Dateien wird allerdings zumeist kein Datenbankserver eingesetzt; dies ist aber ohne weiteres möglich.
Soll das Anwendungsprogramm eng mit dem Persistenzmechanismus ge-
14
KAPITEL 3. GRUNDLAGEN DER PERSISTENZ
koppelt sein, so wird man eine 2-Schichten-Architektur wählen. Eine 2Schichten-Architektur hat den Vorteil, dass sie vergleichsweise einfacher zu
entwickeln ist als eine 3-Schichten-Architektur. In Scone wird die 2-SchichtenArchitektur eingesetzt. Die 3-Schichten-Architektur hat den Vorteil, dass die
komplette Anwendungslogik im Applikationsserver implementiert ist. Dadurch wird unter anderem die Wartungs- und Installationskomplexität erheblich reduziert.
3.3
Grundkonzepte von Datenbankensystemen
Ein wesentlicher Aspekt, der für den Einsatz von Datenbanksystemen spricht,
ist die von ihnen umgesetzte Datenunabhängigkeit. Durch die Datenunabhängkeit werden Anwendungsprogramm und Datenbank voneinander entkoppelt. Das hat den Vorteil, dass Anwendungsprogramm und Datenbank
unabhängig voneinander Änderungen unterzogen werden können. Mit Datenbanksystemen hängt weiterhin noch der Begriff der Transaktion zusammen.
Transaktionen werden aber nicht von allen Datenbanksystemen angeboten.
Datenunabhängigkeit Das Konzept der Datenunabhängigkeit läßt sich
nach [9, 16] in zwei Aspekte aufteilen:
• Physische Datenunabhängigkeit: Die physische Datenunabhängigkeit
entkoppelt die Speicherung der Daten von der logischen Sicht auf die
Daten. Somit ist es möglich Optimierungen an der physischen Basis der
Daten unabhängig vom Datenbankschema durchzuführen. Die Änderungen haben damit nur Einfluß auf die Effizienz der Datenbank.
• Logische Datenunabhängigkeit: Die logische Datenunabhängigkeit koppelt die Datenbank von den Anwendungsprogrammen ab. Dadurch
bleibt das Datenbankschema von Änderungen der Anwendungsschnittstellen unberührt.
Diese zwei Ebenen der Datenunabhängigkeit werden durch das Konzept der
Datenabstraktion gewährleistet.
Datenabstraktion Nach [9, 16] werden in einem Datenbanksystem drei
Abstraktionsebenen unterschieden (s. Abb. 3.2):
3.3. GRUNDKONZEPTE VON DATENBANKENSYSTEMEN
15
• Die physische Ebene: Hier wird festgelegt, wie die Daten gespeichert
werden. Dies ist im Normalfall der Hintergrundspeicher, der in der Regel als Festplattenspeicher realisiert ist.
• Die logische Ebene: Auf dieser Ebene wird festgelegt, welche Daten abgespeichert sind. Das hier beschriebene integrierte Modell der gesamten
Informationsmenge wird auch Datenbankschema genannt.
• Die Sichten: Während das Datenbankschema der logischen Ebene die
gesamte Informationsmenge enthält, werden in den Sichten Teilmengen dieser Informationsmenge bereitgestellt. Diese Sichten sind auf die
Bedürfnisse der jeweiligen Benutzer bzw. Benutzergruppen zugeschnitten.
Sicht 1
Sicht 2
Sicht n
logische Ebene
physische Ebene
Abbildung 3.2: Drei Abstraktionsebenen eines Datenbanksystems aus [9]
Transaktionen Einen Transaktion ist eine Folge von Operationen auf einer Datenbank, die die Datenbank von einem konsistenten Zustand in einen
neuen konsistenten Zustand überführt. Um dies zu gewährleisten, ist die
Einhaltung der ACID-Eigenschaften für eine Transaktion wichtig. Der Name
ACID steht dabei für die vier Prinzipien, die von Transaktionen gefordert
werden:
16
KAPITEL 3. GRUNDLAGEN DER PERSISTENZ
• Atomicity
Ein Transaktion ist atomar d.h. sie wird entweder ganz oder gar nicht
ausgeführt.
• Consistency
Eine Transaktion gewährleistet, dass sie nach ihrer Ausführung die Datenbank in einem konsistentem Zustand hinterläßt. Die Datenbank wird
in den Zustand vor Ausführung der Transaktion zurückgesetzt, wenn
die Überführung in einen konsistenten Zustand nicht gewährleistet werden kann.
• Isolation
Das Ergebnis einer Transaktion muss einer isolierten Ausführung der
Transaktion entsprechen, d.h. als ob sie alleine ausgeführt wurde, unabhängig davon ob mehrere Transaktionen parallel oder verschränkt
laufen. Dies wird durch Serialisierbarkeit erreicht.
• Durability
Ein Transaktion garantiert, dass die in der Datenbank neu abgelegten
oder geänderten Daten dauerhaft gespeichert sind, d.h. die Daten sind
nicht an die Lebensdauer von Variablen oder Blöcken gebunden. Die
Daten werden zumindestens in den Sekundärspeicher geschrieben.
3.4
Das relationale Datenmodell
Relationale Systeme basieren auf der von Codd in [4] entwickelten Theorie,
die the relational model of data“ genannt wird. Drei wichtige Aspekte lassen
”
sich nach [5] an dieser Theorie festmachen und zwar:
• Struktureller Aspekt: Daten werden in Tabellen abgelegt. Der Nutzer
einer Datenbank nimmt ihren Datenbestand als eine Sammlung von
Tabellen wahr.
• Integritätsaspekt: Die Tabellen einer Datenbank erfüllen bestimmte Integritätseinschränkungen.
• manipulativer Aspekt: Die Operatoren die dem Nutzer zur Verfügung
stehen, um die Tabellen einer Datenbank zu manipulieren, sind ausschließlich Operatoren die Tabellen aus Tabellen generieren. Von diesen Operatoren sind drei besonders wichtig, dies sind restrict, project
3.5. DAS OBJEKTORIENTIERTE DATENMODELL
17
und join. Da das Ergebnis einer Manipulation wieder eine Tabelle ist,
lassen sich Operationen beliebig tief schachteln.
Die Speicherung von Daten in Tabellen und die mengenorientierten Verarbeitung hat diesen Systemen zum Durchbruch verholfen. Im Gegensatz zur
mengenorientierten Verarbeitung von Daten, wurden die Daten im Netzwerkmodell und hierarchischen Modell satzorientiert verarbeitet. Hinter einer Tabelle steht der mathematische Begriff der Relation, der diesen Systemen auch
ihren Namen gegeben hat. Die mathematische Untermauerung ermöglicht
es, Normalisierungen der Daten durchzuführen, um Redundanz und damit
Mehrfachspeicherung zu vermeiden.
Die Anbindung von relationalen Datenbanken an eine Programmiersprache
geschieht in aller Regel über eine standardisierte Schnittstelle. Die Schnittstelle für Java heißt JDBC (Java Database Connectivity).
3.5
Das objektorientierte Datenmodell
Das objektorientierte Datenmodell basiert auf Konzepten aus der Welt objektorientierter Programmiersprachen. Das zentrale Konzept des objektorientierten Datenmodells ist, wie bei den objektorientierten Programmiersprachen, der Begriff des Objektes. Ein Objekt integriert die strukturelle Repräsentation mit der operationalen Komponente in einem Objekttyp (auch
Klasse genannt). Ein Objekttyp spezifiziert also strukturell und operational ähnliche Objekte. Der Standard für das objektorientierte Datenmodell
ist der ODMG 3.0 (Object Database Management Group) Standard. Dieser Standard definiert ein Objektmodell und die Anbindung an verschiedene
Programmiersprachen. Der ODMG 3.0 Standard definiert Anbindungen an
die Sprachen C++, Smalltalk und Java. Der Standard definiert auch eine
deklarative Anfragesprache, die in Anlehnung an SQL, OQL (Object Query
Language) heißt.
Der ODMG 3.0 Standard schreibt Persistenz durch Erreichbarkeit vor, d.h.
alle von einem Objekt direkt oder indirekt referenzierten Objekte werden
zusammen mit diesem persistiert. Der Standard sieht auch sogenannte Wurzelobjekte vor, dies sind Objekte, die beim Persistieren einen Namen bekommen. Unter diesem Namen findet man sie in der Datenbank wieder; damit
fungieren sie als Einstiegspunkte für die Objektnavigation, d.h. ausgehend
von einem Wurzelobjekt erreicht man alle zu einem Objektnetz gehörenden
Objekte. Das Wiederfinden von Objekten ist aber auch über die Extension
18
KAPITEL 3. GRUNDLAGEN DER PERSISTENZ
einer Klasse – damit ist die Menge aller Instanzen einer Klasse gemeint –
möglich. Der Standard sieht Extensionen (noch) nicht vor [18].
Eigenschaften von Objekten Nach [9] hat ein Objekt im objektorientierten Modell drei Bestandteile:
• Typ: Die Struktur und das Verhalten werden durch den Objekttyp, also
die Klasse, festgelegt. Indivuelle Objekte werden durch Instanziierung
des Objekttyps erzeugt.
• Identität: Jedes Objekt hat eine eindeutige Objektidentität, die sich
während seiner Lebenszeit nicht ändert.
• Wert bzw. Zustand : Zu jedem Zeitpunkt seiner Lebenszeit hat ein Objekt einen bestimmten Zustand (auch Wert genannt). Der Zustand eines
Objektes ist durch die Werte seiner Attribute und durch die Beziehungen zu anderen Objekten gegeben.
Objektidentität Ein besonders wichtiger Aspekt ist die Identität von Objekten. Die Objektidentität ermöglicht es ein Objekt genau zu identifizieren
und zwar unabhängig vom Zustand des Objektes und seinem Aufenthalts”
ort“. Im Gegensatz zum relationalen Modell, wo Tupel über ihre Schlüsselattribute identifiziert werden, werden Objekte in objektorientierten Programmiersprachen durch Zeiger referenziert. Ein Objekt wird also durch seine
Adresse im Speicher identifiziert. Diese Methode der Objektidentifizierung
kann aber für persistente Objekte aus folgenden Gründen nicht benutzt werden [9]:
• Während seiner Lebensdauer, kann ein Objekt nicht verschoben werden. Dies ist bei transienten Hauptspeicherobjekten kein so großes Problem wie im Datenbankbereich, da man es hier mit persistenten Objekten zu tun hat.
• Weiterhin kann nicht sichergestellt werden, daß alle Referenzen auf ein
gelöschtes Objekt ihre Gültigkeit verlieren. Der ehemalige Speicherort
könnte unbemerkt durch neue, andere Objekte belegt werden.
Dieses Problem wird in objektorientierten Datenbanken durch Objektidentifikatoren(OIDs) gelöst. Diese OIDs sind zustands- und speicherungsortunabhängig und werden vom Datenbanksystem systemweit eindeutig generiert, sobald ein neues persistentes Objekt erzeugt wird. Sie stehen dann zur
3.6. OBJEKTRELATIONALE DATENBANKEN
19
Referenzierung der Objekte zur Verfügung. Die OIDs bleiben während der
ganzen Lebenszeit eines Objektes invariant. Weiterhin sorgt das Datenbanksystem dafür, daß ein OID nur einmal generiert wird, d.h. der OID eines
gelöschten Objektes wird nie wieder verwendet.
3.6
Objektrelationale Datenbanken
Für objektrelationale Datenbanken existiert noch kein einheitliches Datenmodell. Objektrelationale Datenbanken basieren auf der funktionalen Erweiterung des relationalen Datenmodells. Hierbei werden objektorientierte
Konzepte in das relationale Datenmodell integriert. Die meisten führenden
Hersteller von relationalen Datenbanken bieten heute schon einige der objektrelationalen Konzepte in ihren Produkten an, zumeist aber in uneinheitlicher Form. Die Erweiterung des relationalen Datenmodells beziehen sich
hauptsächlich auf folgende Aspekte (nach [9]):
Mengenwertige Attribute Es wird die flache Struktur des relationalen
Modells aufgegeben. Es wird also ermöglicht das ein Tupel nicht nur aus atomaren Entitäten bestehen kann, d.h. die erste Normalform des relationalen
Modells wird aufgegeben2 .
Typdeklarationen Wie im objektorientierten Datenmodell ist es möglich
eigene Typen zu definieren. Dadurch ist man nicht mehr an den begrenzten
Satz von vordefinierten SQL-Attributtypen gebunden.
Referenzen Es werden wie im objektorientierten Datenmodell Referenzen eingeführt. Fremdschlüssel zur Modellierung von Beziehungen sind damit unnötig. Die Einführung von Referenzen führt automatisch zum nächsten
Punkt.
Objektidentität Durch die Einführung von Referenzen wird die
Einführung von Objektidentität notwendig. Denn Referenzen sind nur dann
sinnvoll, wenn Objekte (Tupel) eindeutig identifiziert werden können.
2
Dieses Modell wird auch geschachteltes relationales Modell oder kurz NF2 (Non First
Normal Form) genannt.
20
KAPITEL 3. GRUNDLAGEN DER PERSISTENZ
Pfadausdrücke Die Unterstützung von Pfadausdrücken in der Anfragesprache wird durch die Einführung von Referenzen notwendig. Denn welchen
Vorteil hat man durch die Einführung von Referenzen, wenn diese nicht in
der Anfragesprache genutzt werden.
Vererbung Durch die Einführung von Vererbung ist es möglich eine Relation als einen Untertyp von einer oder mehreren Relationen zu definieren.
Operationen Im objektorientierten Datenmodell ist es möglich die den
Daten zugeordneten Operationen (Methoden) in der Anfragesprache zu nutzen. Das bedeutet, dass in der OQL die Methoden von Objekten ausgeführt
werden können, da diese im Datenbankschema ebenfalls persistiert werden.
D.h. man kann die volle Funktionalität der Objekte in einer anderen Anwendung nutzen, ohne die auf einen Objekt möglichen Operationen neu implementieren zu müssen. Dies ist im relationalen Modell nicht möglich.
3.7
Java Serialisierung
Das Paket java.io stellt grundlegende Klassen für Dateioperationen zur
Verfü-gung. Mit Hilfe dieser Klassen ist es möglich von einer beliebigen Quelle zu lesen und in eine beliebige Senke zu schreiben. Vor allem die beiden
Klassen java.io.ObjectOutputStream und java.io.ObjectInputStream
sind interessant. Mit ihnen ist das Serialisieren beliebiger Objektgraphen in
und aus Dateien möglich. Eine Klasse wird serialisierbar, wenn sie das Interface java.io.Serializable implementiert. Dies ist mit wenig Aufwand
verbunden, da das Interface keine Methoden hat, also nur als Indikator dient.
Zu beachten ist nur, das alle referenzierten Klassen auch serialisierbar sein
müssen. Die Serialisierung wurde mit dem Ziel entwickelt, entfernte Methodenaufrufe (RMI) zu unterstützen [16]. Dieser einfache Mechanismus erlaubt
es Daten schnell persistent zu machen. Durch die enge Integration der Serialisierung in die Sprache Java wird der Impedance Mismatch vermieden. Die
Serialisierung unterstützt aber
• keine Abfragen der persistenten Daten,
• keinen Mehrbenutzerzugriff und
• die Datenunabhängigkeit ist ebensowenig gegeben.
3.8. EJB, JDO UND XML
21
Aus diesen Gründen eignet sich Serialisierung nicht dafür, den Persistenzmechanismus in Scone zu ersetzen.
3.8
EJB, JDO und XML
Die hier vorgestellten Persistenzmechanismen sind insofern nicht in die Unterteilung von Kapitel 3.1 aufgenommen, da sie in der Mittelschicht von
3-Schicht-Architekturen (s.Abb. 3.1b) eingesetzt werden. Damit kapseln sie
den zugrundeliegenden Persistenzmechanismus.
EJB (Enterprise Java Beans) ist eine von Sun entwickelte Komponententechnologie für den serverseitigen Einsatz [1]. Mit EJB entwickelt man
hauptsächlich Applikationsserver für eine 3-Schichten-Architektur. EJB bietet eine Persistenzschnittstelle an, die auf einem der in Abschnitt 3.1 beschriebenen Persistenzmechanismen aufsetzt. EJB ist also nur scheinbar ein neuer
Persistenzmechanismus, tatsächlich aber kapselt EJB lediglich den zugrundeliegenden Persistenzmechanismus und bietet eine einheitlich Schnittstelle
an. In den meisten Fällen erledigt dann auch eine relationale Datenbank die
eigentliche Arbeit. EJB reduziert den Entwicklungsaufwand für Applikationsserver erheblich.
JDO (Java Data Objects) beschreibt wie Java Objekte gespeichert werde sollen [17]. JDO stellt eine einheitliche Schnittstelle für jede Art von
Persistenzmechanismus zur Verfügung. Somit ist JDO kein eigenständiger
Persistenzmechanismus, sondern kapselt wiederum nur den zugrunde liegenden Persistenzmechanismus. Durch JDO ist es möglich beliebige Persistenzmechanismen einzusetzen, ohne sich z.B. um Objektmapping kümmern zu
müssen.
Eine weitere Möglichkeit Java Objekte zu speichern ist XML (eXtensible
Markup Language). Wenn man Objekte in XML speichert, ist damit aber
noch nicht geklärt wie die XML-Daten tatsächlich gespeichert werden. Die in
XML codierten Objekte werden dann entweder in Dateien oder Datenbanken
abgelegt, wobei sich für die dauerhafte Persistierung nach [19] objektorientierte Datenbanken anbieten.
Alle hier beschriebenen Ansätze sind Mechanismen, die vom eingesetzten Persistenzmechanismus abstrahieren. Sie kapseln die Persistenz vor dem Benutzer, damit dieser sich nicht mit Konsistenzwahrung, Integritätseinschränkungen etc. beschäftigen muss. Alle hier beschriebenen Mechanismen speichern
ihre Daten entweder in Dateien oder in Datenbanken. Orthogonal persistente
22
KAPITEL 3. GRUNDLAGEN DER PERSISTENZ
Systeme als dritte Möglichkeit werden zur Zeit noch hauptsächlich im Forschungsbereich eingesetzt. Alle hier beschriebenen Persistenzmechanismen
erfordern die Implementierung eines Applikationsservers. Ein Applikationsserver entspricht aber nicht den in Abschnitt 2.2 auf Seite 8 beschriebenen
Anforderungen, somit wurde keiner dieser Mechanismen ausgewählt um den
Persistenzmechanismus von Scone zu ersetzen.
Kapitel 4
Integration der
Objektdatenbank
Die in Abschnitt 2.2 auf Seite 8 dargelegte Problemstellung und die in Kapitel 3 auf Seite 11 beschriebenen Sachverhalte legten nahe, eine objektorientierte Datenbank zur Problemlösung einzusetzen. Das objektorientierte
Datenbanksystem Object Server Suite (OSS)1 von Poet wurde ausgewählt
um die relationale Datenbank MySQL zu ersetzen.
Durch die Wahl einer objektorientierten Datenbank werden die Forderungen (s. Abschnitt 2.2 auf Seite 8) nach Vermeidung des Paradigmenbruchs
und nach komplexeren Anfragen erfüllt. Aufgabe war es nun die relationale Datenbank MySQL durch die objektorientierte Datenbank von Poet zu
ersetzen.
Die Architektur von Scone wurde bereits im Kapitel 2 auf Seite 3 beschrieben,
hier werde ich nun auf die vollzogenen Änderungen an Scone eingehen. Das
Paket scone.netobjects stellt den Persistenzmechanismus zur Verfügung.
Auf dieser bereits vorhandenen Paketstruktur setzte ich auf und modifizierte
diese, dabei wurde der Persistenzmechanismus komplett neu implementiert.
Die API des Paketes scone.netobjects wurde dabei soweit möglich erhalten.
Zunächst werden in Abschnitt 4.1 die Änderungen an der Paketstruktur
scone.netobjects vorgestellt. In Abschnitt 4.2 wird erläutert wie Klassen
mit der OSS von Poet gespeichert werden, danach werden in Abschnitt 4.3
die orphaned Objects von Poet erklärt. In Abschnitt 4.4 und 4.5 werden dann
1
In Scone kommt OSS 6.1 zum Einsatz, die neuere Version hat in der Zwischenzeit
ihren Namen geändert und heißt jetzt FastObjects t7 by Poet.
23
24
KAPITEL 4. INTEGRATION DER OBJEKTDATENBANK
abschließend die Konzepte der Schatten- und Info-Objekte vorgestellt. Diese Konzepte lösten eine Reihe von Problemen, die bei der Modifikation von
Scone auftraten. Die Implementierung der beiden Konzepte wird in den Abschnitten 4.4.1 und 4.5.1 erläutert.
4.1
Änderung der Paketstruktur
Als erstes wurde die Paketstruktur scone.netobjects (s. Abb. 4.1) von den
Klassen befreit, die durch den Wechsel des Persistenzparadigmas überflüssig
wurden. Durch die Vermeidung des Paradigmenbruchs ergibt sich sofort der
Wegfall der Klassen
• TableRecord,
• DBTableAdapter und
• FieldValueHashTable.
Diese drei Klassen sind für das Objektmapping der zu persistierenden Objekte auf relationale Tabellen zuständig. Da Objekte in objektorientierten
Datenbanken direkt gespeichert werden, ist die Transformation von Objekten in tabellentaugliche Daten und zurück nicht mehr nötig.
Eine weitere Vereinfachung der Paketstruktur scone.netobjects ergibt sich
aus der Definition von Klassen. Eine Klasse vereinigt die strukturelle Repräsentation (Eigenschaften von Objekten) und die verhaltensmäßigen Komponenten (Methoden von Objekten). Eine Klasse spezifiziert also strukturell
und verhaltensmäßig ähnliche Objekte. Aufgrund dieser Definition entschied
ich mich, die Datenbankanbindung in die zu persistierenden Objekte zu verlagern. Vorher war die Datenbankanbindung in den Klassen
• HtmlNodeCache,
• NetNodeCache,
• LinkCache,
• etc.
umgesetzt (vgl. Abschnitt 2.1). Durch die Verlagerung der Datenbankanbindung wurden die zu persistierenden Klassen befähigt, sich selbst zu speichern
25
4.1. ÄNDERUNG DER PAKETSTRUKTUR
Dictionary
HtmlTagToken
Hashtable
FieldValueHashTable
LinkToken
Frame
AccessCache
Observable
HtmlNodeCache
Cache
DBTableAdapter
NetNodeCache
AccessEvent
Access
CacheTable
HtmlNode
CacheTable$Entry
Inclusion
SimpleUri
Keyword
Link
NetNode
Object
TableRecord
Node2Key
PersonCache
LinkCache
Person
Person2Group
InclusionCache
PGroup
KeywordCache
Server
ServerCache
User
Person2GroupCache
Legende
aus externem Paket
PGroupCache
A
Node2KeyCache
B
B erweitert A
CacheTable$Cleaner
x$y
Thread
Cache$Notifier
y ist innere
Klasse von x
UserCache
Vector
LinkVector
Abbildung 4.1: Klassendiagramm mit MySQL als Datenbank
persistenz−
fähige Klassen
26
KAPITEL 4. INTEGRATION DER OBJEKTDATENBANK
und aus der Datenbank zu lesen. Aufgrund der Entfernung der Datenbankanbindung aus den Klassen der Form xxxCaches verblieb nur die Cachefunktionalität in diesen Klassen. Da POET einen Caching-Mechanismus zur
Verfügung stellt entfernte ich auch alle Cacheklassen. Abb. 4.2 zeigt die resultierende Paketstruktur.
HtmlTagToken
LinkToken
Inclusion
NetNode
NetNodeInfo
Object
Link
HtmlInfo
Legende
aus externem Paket
Server
A
B
B erweitert A
Frame
SimpleUri
persistenz−
fähige Klassen
Abbildung 4.2: Klassendiagramm mit OSS 6.1 als Datenbank
4.2
Persistenzfähige Klassen
Bevor persistente Objekte zur Verfügung stehen, muss dem Datenbanksystem zunächst einmal bekannt gemacht werden, welche Klassen überhaupt
persistenzfähig sind. Das Datenbankschema ergibt sich im objektorientierten Paradigma dann direkt aus der Klassenstruktur. Es kann also direkt aus
scone.netobjects gewonnen werden (Abb. 4.2) und muss nicht wie im relationalen Fall getrennt erzeugt werden (s. ER-Diagramm in Abb. 2.2 auf
Seite 6).
Der ODMG-Standard sieht vor, dass Klassen von außen als persistenzfähig
deklariert werde sollen [18]. Klassen werden also nicht mit Mitteln der Sprache Java persistenzfähig gemacht, sondern dies geschieht im Fall von Poet
über eine Konfigurationdatei und den Postprozessor ptj. Der Postprozessor
ptj verarbeitet die Konfigurationsdatei und erzeugt persistenzfähige Klassen.
Diese Konfigurationsdatei hat standardmäßig die Endung *.opt und enthält
4.2. PERSISTENZFÄHIGE KLASSEN
27
die Informationen über die persistent zu machenden Klassen. Im Falle von
Scone hat diese Datei den Namen scone.opt und folgenden Inhalt:
[schemata\NetSchema]
oneFile = false
name = ..\run\NetBase
[databases\NetBase]
schema = NetSchema
name = ..\run\NetBase
Die obenstehenden Zeilen legen fest, dass zwei Dateien erzeugt werden sollen, zum einen das Dictionary, zum anderen die Datenbank. Das Dictionary,
auch Klassenschema genannt, speichert alle Informationen über die Struktur der persistenzfähigen Klassen. In der Datenbank werden alle vom Nutzer
erzeugten Objekte gespeichert.
Die folgenden Zeilen der Datei scone.opt legen die Klassen fest, die vom
Postprozessor ptj persistenzfähig gemacht werden sollen.
[classes\scone.netobjects.NetNode]
persistent = true
[classes\scone.netobjects.SimpleUri]
persistent = true
[classes\scone.netobjects.NetNodeInfo]
persistent = true
[classes\scone.netobjects.HtmlInfo]
persistent = true
[classes\scone.netobjects.Link]
persistent = true
[classes\scone.netobjects.Inclusion]
persistent = true
28
KAPITEL 4. INTEGRATION DER OBJEKTDATENBANK
Der Postprozessor ptj generiert mit Hilfe dieser Informationen und der
*.class Dateien persistenzfähige Klassen, indem er sie mit Code, Methoden und Hilfsklassen erweitert. Wenn beim ersten Aufruf noch keine Datenbank existiert, legt der Postprozessor ptj automatisch die Datenbank und
das Dictionary (Datenbankschema) an.
Der Postprozessor wird mit folgendem Kommando gestartet:
ptj -enhance -create -inplace scone.opt
Mit diesem Kommando wird die Datenbank erzeugt, und die angegebenen
Klassen werden persistenzfähig gemacht. Soll jetzt ein Objekt persistiert werden, muß zunächst die Datenbank für Schreib-Lese-Zugriffe geöffnet werden.
Mit
package scone;
...
public class Scone{
...
//the POET-Database
public static Database db = new Database();
wird ein Datenbankobjekt erzeugt. Das Datenbankobjekt wird dann mit
//initialize the database
db.open("poet://LOCAL/NetBase",Database.OPEN_READ_WRITE);
für Lese- und Schreiboperationen geöffnet und zwar für die Datenbank
NetBase. Jetzt steht eine Datenbank unter dem Namen NetBase zur
Verfügung und die relevanten Klassen wurden persistenzfähig gemacht.
4.3
Orphaned Objects
Die beiden Datenbanken unterscheiden sich nicht nur im eingesetzten Persistenzmechanismus (relational vs. objektorientiert). Ein weiterer wesentlicher
4.3. ORPHANED OBJECTS
29
Unterschied zu MySQL besteht darin, dass MySQL keine Transaktionen unterstützt (s. hierzu [10]). Poet hingegen arbeitet vollständig transaktionsorientiert. Das bedeutet, dass jede Datenbankoperationen nur innerhalb eines
Transaktionkontextes ausgeführt werden kann.
Ist eine Transaktion beendet, werden alle mit ihr assoziierten Objekte
als schlafend bezeichnet. Poet bezeichnet diesen Zustand auch als orphaned (verwaist). Poet ermöglicht es aber, diese Objekte zu einem späteren
Zeitpunkt in einer neuen Transaktion wieder aufzuwecken. Dies geschieht
über die Methoden der statischen Klasse ObjectServices. Dieser Mechanismus erlaubt es, Objekte in einer späteren Transaktion wieder zu verwenden.
Der Code dafür sieht folgendermassen aus:
Transaction txn1 = new Transaction();
txn1.begin();
NetNode n = new NetNode();
txn1.commit();
Das Objekt n befindet sich nach dem commit() jetzt im schlafenden Zustand.
Mit
Transaction txn2 = new Transaction();
txn2.begin();
//awake the object in the current Transaction
ObjectServices.current().awake(n);
wird n wieder aufgeweckt. Jetzt ist es möglich das Objekt n in der zweiten
Transaktion txn2 weiter zu verwenden.
n.modify();
txn2.commit();
Dieser Mechanismus funktioniert aber nur sofern die benötigten Objektreferenzen sich noch im Sichtbarkeitsbereich befinden. Ist dies nicht der Fall
funktioniert das Aufwecken nicht mehr. Abb. 4.3 veranschaulicht diesen Zusammenhang noch einmal graphisch.
30
KAPITEL 4. INTEGRATION DER OBJEKTDATENBANK
Programm
Methode 1
Transaction txn1 = new Transaction();
txn1.begin();
NetNode n =new NetNode();
txn1.commit();
...
Transaction txn2 = new Transaction();
txn2.begin();
ObjectServices.current().awake(n);
n.modify();
txn2.commit();
Methode 2
Transaction txn3 = new Transation();
txn3.begin();
ObjectServices.current().awake(n);
Ausführung möglich, da n im
Sichtbarkeitsbereich von Methode 1
liegt.
Kann nicht ausgeführt werden,
da n nicht im Sichtbarkeits−
bereich von Methode 2 liegt.
Abbildung 4.3: Sichtbarkeitsbereich (Scope) von Objekten
4.4. KONZEPT DER SCHATTENOBJEKTE
4.4
31
Konzept der Schattenobjekte
Wie in (Kapitel) 2.1 dargestellt, stellt die Methode handleRequest(
SconePipe pipe) der Klasse ParsingMeg den Standard-TokenHandler zur
Verfügung. In dieser Methode werden die zu persistierenden Objekte erzeugt
und gespeichert. Da persistente Objekte nicht zugreifbar sind, wenn eine
Transaktion beendet ist (s. Kapitel 4.3), wäre es die einfachste Lösung die
ganze Methode handleRequest durch eine Transaktion einzurahmen.
public void handleRequest(SconePipe pipe){
try{
Transaction txn = new Transaction();
txn.begin();
// lade vorhandene Daten <- Daten werden gesperrt
// Dokument parsen
// aktualisiere und persistiere Daten
txn.commit();
}
catch(Exception exc){
//Ausnahmebehandlung
txn.abort();
}
}
Diese oben dargestellte Lösung hat aber die Nachteile, dass zum einen alle beteiligten persistenten Objekte gesperrt werden, und zum anderen die
Datenkonsistenz nicht sichergestellt ist. Der erste Nachteil resultiert daraus,
dass Scone multi-threaded ist und ein anderer Thread nicht auf benötigte
persistente Objekte zugreifen kann. Der zweite Nachteil resultiert aus der
Tatsache, dass bei einem Abbruch der Datenübertragung aus dem WWW
nicht sichergestellt ist, wie die Datenbank darauf reagiert. Diese Lösung hat
andererseits den Vorteil, dass auf alle persistenten Objekte zugegriffen werden kann.
Die favorisierte Lösung sollte zum einen die gesperrten Objekte schnell wieder freigeben, die Problematik des Datenübertragungsabbruchs entschärfen
und persistente Objekte ausserhalb eines Transaktionskontextes zugreifbar
machen. Wie in der Abb. 4.4 dargestellt besitzen die Objekte B und C jeweils eine Referenz auf das Objekt A in der Datenbank. Objekt B und C sind
32
KAPITEL 4. INTEGRATION DER OBJEKTDATENBANK
Kopien von A. Objekt B und C sind also Projektionen von Objekt A in den
Hauptspeicher. Aus dieser Sichtweise leitet sich der Name des Konzeptes ab,
ein Schattenobjekt ist also ein Objekt, welches im Hauptspeicher liegt und
eine Kopie von einem persistenten Datenbankobjekt ist. Ein Schattenobjekt
hat dabei folgende Eigenschaften:
• Die Datenbankanbindung ist im Objekt selbst umgesetzt.
• Es ist ausserhalb eines Transaktionskontextes zugreifbar.
• Es referenziert sich selbst in der Datenbank.
Hauptspeicher
C
User 1
Datenbank
transiente
Referenz
A
ente
transi
User 2
enz
Refer
B
B.equals.(A) = true
Abbildung 4.4: Schattenobjekte
4.4.1
Integration der Schattenobjekte
Die Integration der Schattenobjekte wird exemplarisch an der Klasse
NetNode vorgestellt. Die vollzogenen Änderungen gelten analog für die Klassen Link und Inclusion. Von diesen drei Klassen fungieren NetNode und
Link als Einstiegspunkte für die weitere Navigation. Einstiegspunkte nach
4.4. KONZEPT DER SCHATTENOBJEKTE
33
dem ODMG-Standard sind persistente Objekte die einen Namen erhalten, diese werden auch als Wurzel-Objekte bezeichnet. Unter diesem Name können sie später wieder in der Datenbank lokalisiert werden [18]. Der
Name für ein Wurzel-Objekt kann nur einmal vergeben werden. Im Falle
von NetNode ergibt sich der Name aus der Klasse SimpleUri. Die Klasse
SimpleUri ist kompatibel zu RFC 2396 [12]. Einen spezifischen NetNode findet man in der Datenbank also unter seiner URL. Der Name für einen Link
setzt sich aus den beiden URLs der verlinkten NetNodes zusammen.
Die Klasse NetNode hat folgende Eigenschaften:
package scone.netobjects;
public class NetNode{
protected SimpleUri sUri;
protected long
accessCounter;
protected long
size;
protected String mimeType;
protected String accessStatus;
protected Date
lastModified;
protected Date
firstAccess;
protected Date
lastAccess;
Eine Forderung des Konzeptes der Schattenobjekte ist es, dass sich ein Schattenobjekt selbst in der Datenbank referenzieren kann. Dies wird durch das
hinzufügen einer weiteren Eigenschaft erreicht. Mit
transient protected NetNode dbReferenz;
}
kann sich ein NetNode selbst in der Datenbank referenzieren. Dadurch dass
dbreferenz transient deklariert ist, wird diese Referenz beim Persistieren
nicht gespeichert. Das ist wichtig, da ein Datenbankobjekt ansonsten sein
eigener Schatten wäre. Die transiente Referenz ist nur für das Schattenobjekt
notwendig, sie ermöglicht es Änderungen am Schattenobjekt wieder auf das
Datenbankobjekt übertragen zu können. Dadurch ist es nicht notwendig eine
Datebankabfrage zu starten, um das korrespondierende Datenbankobjekt zu
einem Schattenobjekt zu finden.
34
KAPITEL 4. INTEGRATION DER OBJEKTDATENBANK
Die Klasse NetNode erhielt einen neuen Konstruktor, der sicherstellt, dass
ein Schatten- und ein Datenbankobjekt erzeugt wird.
public NetNode(SimpleUri sUri, Transaction txn){
txn.begin();
try{
this.dbReferenz = (NetNode)txn.lookup(sUri.getNodeUri());
Mit dieser Zeile überprüft der Konstruktor ob der neu zu erzeugende NetNode
nicht schon in der Datenbank existiert. Wenn der Lookup in der Datenbank
erfolgreich war, wird der NetNode aus der Datenbank gelesen.
readAttributes();
txn.abort();
}
Die Methode readAttributes() liest die Attribute und schreibt sie in das
Schattenobjekt.
protected void readAttributes() {
setSUri(new SimpleUri(dbReferenz.getSUri().toString()));
Da die Eigenschaft protected SimpleUri sUri eine Referenz auf ein
SimpleUri Objekt ist, muss das Objekt geklont werden, da es ansonsten
nach Beenden der Transaktion nicht mehr zur Verfügung stände. Das Konzept der Schattenobjekte fordert aber, dass persistente Daten außerhalb eines
Transaktionskontextes zur Verfügung stehen, also muss jede Objektreferenz
tief kopiert werden.
setAccessCounter(dbReferenz.getAccessCounter());
setSize(dbReferenz.getSize());
setMimeType(dbReferenz.getMimeType());
setAccessStatus(dbReferenz.getAccessStatus());
setLastModified(dbReferenz.getLastModified());
setFirstAccess(dbReferenz.getFirstAccess());
setLastAccess(dbReferenz.getLastAccess());
}
4.4. KONZEPT DER SCHATTENOBJEKTE
35
Die restlichen obenstehenden Zeilen lesen die einfachen Eigenschaften aus
der Datenbank in das Schattenobjekt ein.
Wird der Name nicht in der Datenbank gefunden, existiert also kein Wurzelobjekt, so wirft lookup(String) eine ObjectNameNotFoundException aus.
catch(ObjectNameNotFoundException exc){
Wenn kein Wurzelobjekt in der Datenbank existiert, wird vom Konstruktor
ein neues Datenbankobjekt angelegt.
this.sUri = sUri;
setMimeType(getMimeTypeFromExtension(this.sUri.getExtension()));
try{
dbReferenz = new NetNode();
Die obige Zeile legt einen leeren NetNode an.
dbReferenz.setSUri(new SimpleUri(toString()));
storeAttributes();
txn.bind(dbReferenz,sUri.getNodeUri());
}
Mit txn.bind(Object,String) wird dbReferenz in der Datenbank persistiert.
catch(ObjectNameNotUniqueException ex){
System.out.println("Error in NetNode: Name not Unique!");
}
txn.commit();}}
Mit dem abschließenden txn.commit steht nun ein Schattenobjekt zur
Verfügung. Alle Eigenschaften und Methoden von einem persistenten
NetNode stehen nun außerhalb eines Transaktionskontextes zur Verfügung.
Das gesamte Objektnetz kann nun nach belieben manipuliert werden, ohne dass die beteiligten persistenten Objekte gesperrt sind. Sollen die Änderungen gesichert werden, so geschieht das mit Hilfe der neuen Methode
store(Transaction txn).
36
KAPITEL 4. INTEGRATION DER OBJEKTDATENBANK
public void store(Transaction txn){
txn.begin();
ObjectServices.current().awake(dbReferenz);
Die Eigenschaft dbReferenz wird aufgeweckt (s. Kapitel 4.3). Der Zugriff
auf das Datenbankobjekt ist jetzt wieder möglich und mit
storeAttributes();
txn.commit();
}
werden die Änderungen an dem Schattenobjekt in der Datenbank persistiert.
Die Methode storeAttributes() liest dabei jede Eigenschaft des Schattenobjektes und verändert die Eigenschaften des Datenbankobjektes.
protected void storeAttributes() {
dbReferenz.setAccessCounter(getAccessCounter());
dbReferenz.setSize(getSize());
dbReferenz.setMimeType(getMimeType());
dbReferenz.setAccessStatus(getAccessStatus());
dbReferenz.setLastModified(getLastModified());
dbReferenz.setFirstAccess(getFirstAccess());
dbReferenz.setLastAccess(getLastAccess());
}
Beim Sichern der neugewonnen Informationen wird von einer optimistischen
Speicherungsstrategie ausgegangen, d.h. sollte eine Datenbankobjekt mehrfach manipuliert werden, so wird davon ausgegangen, dass die zuletzt gesicherten Informationen auch die aktuellsten sind. Neu zu sichernde Informationen werden also nicht auf ihre Aktualität überprüft.
Durch das Konzept der Schattenobjekte ist es nicht mehr nötig die Methode
handleRequest in eine einzige Transaktion einzurahmen. Stattdessen wird
am Anfang der Methode ein Transaktionsobjekt erzeugt, das dann den jeweiligen Methodenaufrufen von NetNode übergeben wird. Durch diesen Mechanismus wird auch die Problematik eines plötzlichen Übertragungsabbruches
entschärft, denn Transaktionen sind nur kurz zum Lesen oder Schreiben aktiv, d.h die Datenbank befindet sich immer nur für kurze Zeit im kritischen
Zustand.
4.5. KONZEPT DER INFO-OBJEKTE
37
Somit wird die Methode handleRequest wie folgt modifiziert:
public void handleRequest(SconePipe pipe){
try{
Transaction txn = new Transaction();
NetNode net = new NetNode(sUri,txn);
// Dokument parsen
...
// manipuliere Schattenobjekt
net.setMimeTyp("text/html"); //dies ist ein Beispiel
...
// aktualisiere und persistiere Daten
net.store();
}
catch(Exception exc){
//Ausnahmebehandlung
txn.abort();
}
}
4.5
Konzept der Info-Objekte
Durch die Verwendung einer objektorientierten Datenbank, bot es sich an
die Klasse HtmlNode von der Klasse NetNode abzuleiten. Wie in Abb. 4.1 zu
sehen, ist HtmlNode nicht von NetNode abgeleitet. NetNode sowie HtmlNode
waren jeweils auf eine relationale Tabelle abgebildet und standen in einer
1-0..1 Beziehungen (s. Abb. 2.2). HtmlNode ist somit eine spezieller NetNode.
Dadurch das zunächst einmal jedes Objekt, das von Scone geparst wird,
als eine Instanz von NetNode aufgefasst wird, ist es nicht möglich eine Instanz von NetNode einfach in eine Instanz von HtmlNode umzuwandeln. Wird
HtmlNode von NetNode abgeleitet, so kann man eine Instanz von NetNode
nur dann in explizit in eine Instanz von HtmlNode casten, wenn instanceof
HtmlNode von einer Instanz von NetNode wahr ist, ansonsten tritt eine
ClassCastException auf.
Da jede Instanz von NetNode als ein benanntes Wurzelobjekt in der Datenbank gespeichert ist, müßte die umzuwandelnde Instanz von NetNode durch
eine neu erzeugte Instanz von HtmlNode ersetzt werden. Dies ist aber mit
38
KAPITEL 4. INTEGRATION DER OBJEKTDATENBANK
implementiert
NetNodeInfo
HtmlInfo
nicht implementiert
MultimediaInfo
SoundInfo
WAVInfo
BildInfo
MP3Info
Abbildung 4.5: Mögliche Info-Objekthierarchie
erheblichen Aufwand von Datenbankoperationen verbunden.
Das Konzept der Info-Objekte reduziert die notwendigen Datenbankoperationen und ermöglicht es, dass erst zu einem späteren Zeitpunkt entschieden
wird um was für einen Netzknoten es sich handelt. Das Konzept sieht weiterhin vor, dass eigene Informationsstrukturen implementiert werden können.
Eine denkbare Informationsstruktur ist in Abb. 4.5 dargestellt.
Implementiert sind zur Zeit nur die Klassen NetNodeInfo und HtmlInfo.
HtmlInfo stellt die gleiche Funktionalität wie HtmlNode zur Verfügung. Ein
Info-Objekt ist im Sinne dieses Konzeptes, ein Objekt das spezialisierte Informationen enthält und damit eine Instanz von NetNode näher spezifiziert.
So erhält eine Instanz von NetNode quasi einen zusätzlichen Typ.
4.5.1
Integration der Info-Objekte
Die Integration der Info-Objekte gestaltet sich denkbar einfach. Zuerst wurde
die abstrakte Klasse NetNodeInfo implementiert. Diese ist folgendermaßen
implementiert:
package scone.netobjects;
public abstract class NetNodeInfo{
}
4.5. KONZEPT DER INFO-OBJEKTE
39
Diese Klasse ist völlig leer. Es wäre auch möglich gewesen ein Interface zu
implementieren, es war mir aber nicht möglich Interfaces in POET zu persistieren. Der ODMG-Standard sieht nicht vor, dass abstrakte Klassen und Interfaces persistenzfähig sind [18]. Alle Info-Objekte müssen von NetNodeInfo
abgeleitet werden, wie in Abb. 4.5 dargestellt. Zu beachten ist, dass nur
die Klassen NetNodeInfo und HtmlInfo implementiert sind. Die Klasse
HtmlInfo hat folgenden Eigenschaften:
package scone.netobjects;
public class HtmlInfo extends NetNodeInfo{
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
protected
...
}
int scannedDepth=0;
String title;
String author;
String keywords;
String description;
String language;
String body;
String thumbnail;
long numberOfLinks;
long numberOfExternalLinks;
long numberOfImages;
long spaceOfImages;
long numberOfWords;
long numberOfParagraphs;
boolean frames;
boolean forms;
boolean commercial;
boolean javascript;
boolean plugins;
boolean animation;
boolean sound;
40
KAPITEL 4. INTEGRATION DER OBJEKTDATENBANK
Info-Objekte können nun einfach als zusätzliche Eigenschaft mit get- und
set-Methode in die Klasse NetNode integriert werden.
package scone.netobjects;
...
public class NetNode{
...
protected NetNodeInfo netNodeInfo;
...
public NetNodeInfo getNetNodeInfo(){
return this.netNodeInfo;
}
/**
* Set and Store the Document Info to a NetNode.
*/
public void setNetNodeInfo(NetNodeInfo netNodeInfo,
Transaction txn){
...
}
}
Dadurch das die Klasse NetNodeInfo abstrakt ist, werden nie Instanzen von ihr erzeugt. Es werden nur Instanzen von Unterklassen von NetNodeInfo erzeugt, die dann mit der Methode
setNetNodeInfo(NetNodeInfo n, Transaction txn) von NetNode in
das Feld protected NetNodeInfo netNodeInfo geschrieben werden.
Dadurch ist es möglich erst zu einem späteren Zeitpunkt zu entscheiden
von welchem Typ eine Instanz von NetNode ist, d.h. ob ein NetNode
z.B. eine Html-Seite ist. Außerdem ist die Erweiterung um neue Informationstypen möglich. Durch die Info-Objekte ist es quasi möglich
den Typ einer Instanz von NetNode zu ändern, indem mit der Methode
setNetNodeInfo(NetNodeInfo n,Transaction txn) ein neues Info-Objekt
gesetzt wird, da sich verschiedene Arten von Netzknoten ja nur in ihren
Info-Objekten unterscheiden, und diese alle Subklassen von NetNodeInfo
sind.
Hiermit sind alle notwendigen Änderungen am Persistenzmechanismus beschrieben. Die Änderungen an den anderen persistenzfähigen Klassen entsprechen den Änderungen an der Klasse NetNode, d.h. sie wurden auch um
das Konzept der Schattenobjekte erweitert. Das Konzept der Info-Objekte
ist nur in der Klasse NetNode integriert.
Kapitel 5
Resümee
In der vorliegenden Studienarbeit wurden mehrere Persistenzmechanismen
für Java vergleichend betrachtet. Ziel war es einen neuen Persistenzmechanismus für die Scone-Plattform zu finden und zu implementieren. Von den
untersuchten Persistenzmechanismen
• relationales Datenmodell,
• objektorientiertes Datenmodell,
• objektrelationales Datenmodell,
• Java Serialisierung,
• PJAMA,
• EJB, JDO etc.
wurde das objektorientierte Datenmodell ausgewählt. Die relationale Datenbank MySQL, die Scones Persistenzmechanismus bisher zugrunde lag, wurde
durch die Object Server Suite von Poet ersetzt. Durch den Einsatz einer
objektorientierten Datenbank war ein Objektmapping auf relationale Tabellen nicht mehr erforderlich. Deshalb konnten alle Hilfsklassen aus dem
Paket scone.netobjects entfernt werden. Die resultierende Paketstruktur
ist dadurch stark vereinfacht worden (vgl. hierzu Abb. 4.1 auf Seite 25 und
Abb. 4.2 auf Seite 26). Auch der Code wurde durch den Wegfall des Objektmappings erheblich vereinfacht.
Das Konzept der Schattenobjekte wurde eingeführt. Schattenobjekte sind
Kopien von persistenten Objekten, die lokal im Speicher gehalten werden.
41
42
KAPITEL 5. RESÜMEE
Der Vorteil von Schattenobjekten liegt darin, dass zum einem Transaktionen auf der Datenbank nur kurz geöffnet werden, zum anderem darin, dass
sie ausserhalb eines Transaktionskontextes manipulierbar sind. Dadurch wird
zum einem den Instabilitäten des WWW Rechnung getragen, zum anderen
können beliebig viele Schattenobjekte erzeugt werden, da das persistente Objekte nicht dauerhaft von einem Nutzer gesperrt ist. Beim Zurückschreiben
der Informationen wird von einer optimistischen Strategie ausgegangen, d.h.
es wird angenommen, dass der Nutzer, der zuletzt seine Informationen sichert, über die aktuellsten verfügt. Die Schattenobjekte heben den Vorteil
des einfacheren Codes teilweise wieder auf. Da es notwendig ist, die transitive Hülle eines Netzknotens zu kopieren, wird der Code wieder komplizierter. Dies ist wohl auch der Hauptgrund dafür, dass Scone mit diesem
Persistenzmechanismus langsamer ist. Für die Zukunft wäre eine Beschleunigung des neu implementierten Persistenzmechanismuses wünschenswert, da
er eine deutlich schlechtere Performanz als die Implementation in MySQL
bietet.
Neben dem Konzept der Schattenobjekte wurde noch das Konzept der
Info-Objekte eingeführt. Info-Objekte sind Objekte die einen Netzknoten
(NetNode) näher spezifizieren, d.h. ein Netzknoten wird um genauere Informationen angereichert. Die Info-Objekte ermöglichen es zum einem eigene
Informationsstrukturen (wie in Abb. 4.5 auf Seite 38 angedeutet) zu implementieren; zum anderen läßt sich die genauere Spezifizierung eines Netzknotens einfach austauschen.
Die Weiterentwicklung der in dieser Studienarbeit entwickelten Konzepte ist
eine interessante Herausforderung. Das Potential der eingesetzten Datenbank
von Poet wurde sicherlich noch nicht voll ausgeschöpft.
Abschließend läßt sich feststellen, dass es nach Anwendungsbereich ein anderer Persistenzmechanismus gewählt werden sollte. Es gibt keinen Persistenzmechanismus der für jeden Anwendungsbereich optimal geeignet ist. Auch
der Wechsel eines Persistenzmechanismuses ist nicht trivial. Im vorliegenden
Fall, war der Wechsel vom relationalen System MySQL zum objektorientierten System von Poet nicht einfach zu vollziehen. Es reichte nicht aus die zu
persistierenden Klassen zu identifizieren und alle anderen Klassen zu entfernen. Es war nötig zwei neue Konzepte zu entwickeln, um die beim Wechsel
auftretenden Probleme zu lösen und spezifische Charakteristika des Anwendungskontextes zu berücksichtigen.
Literaturverzeichnis
[1] R. Adatia. Professional EJB. Birmingham: Wrox Press, 2001.
[2] R. Barret and P. P. Maglio. Intermediaries: New places for producing
and manipulating web content. In Proceedings of the 7th Internationl
WWW Conference, 1998.
[3] Carnegie Mellon University.
Die Homepage von WebSPHINX.
http://www-2.cs.cmu.edu/ rcm/websphinx/.
[4] E.F. Codd. A relational model of data for large shared data banks.
CACM, 13(6th), Juni 1970.
[5] C.J. Date. An Introduction to Database Systems. Addison-Wesley, 7th
edition, 2000.
[6] Persistence Group Glasgow der Universität Glasgow. Das PJAMA System. http://www.dcs.gla.ac.uk/pjava/, 1995.
[7] Duden Verlag. Fremdwörter Duden - Band 6. Duden Verlag, 2nd edition,
1966.
[8] IBM Almaden. WBI: Web Intermediaries, Homepage von WBI.
http://www.almaden.ibm.com/cs/wbi/.
[9] A. Kemper and A. Eickler. Datenbanksysteme - Eine Einführung. R.
Oldenbourg Verlag, 3., korr. edition, 1999.
[10] M. Kofler. MySQL - Einführung, Programmierung, Referenz. AddisonWesley, 2001.
[11] P. C. Lockemann, J. W. Schmidt, et al. Datenbankhandbuch. Springer
Verlag, 1st edition, 1993.
[12] P. Loshin, editor. Big Book of World Wide Web RFCs. Morgan Kaufmann, 2000.
43
44
LITERATURVERZEICHNIS
[13] M. Mayer. Kontextvisualisierung: BrowsingIcons und BrowsingGraphs
zur Verbesserung der Orientierung und Navigation im WWW. In P. Ohly, G. Rahmstorf, and A. Sigel, editors, Fortschritte in der Wissensorganisation, pages 267–280. Ergon Verlag, 2000.
[14] R. C. Miller and B. Krishna. Sphinx: A framework for creating personal, site-specific Web Crawlers. In Proceedings of the 7th International
WWW Conference, 1998.
[15] POET Software GmbH. POET Object Server Suite: POET Java Programmer’s Guide. POET Software GmbH, 2000.
[16] G. Saake and K.-U. Sattler. Datenbanken und Java: JDBC, SQLJ und
ODMG. dpunkt.Verlag (iX-Edition), 1st edition, 2000.
[17] Sun
Microsystems.
http://access1.sun.com/jdo.
JDO
-
Java
Data
Objects.
[18] F. Thelen. Der ODMG-Java-Standard 3.0. Java Spektrum, 4(26):S.49 –
S.55, Juli/August 2000.
[19] F. Thelen. XML, Java und Persistenz. Java Spektrum, 1(29):S.59 – S.65,
Januar/Februar 2001.
[20] H. Weinreich and V. Jürgens.
http://www.scone.de, 2001.
SCONE Framework Dokumentation.
[21] H. Weinreich and W. Lamersdorf. Concepts for improved visualization
of Web link attributes. In Proceedings of the 9th International WWW
Conference. Elsevier, 2000.
[22] F. Wollenweber. Entwicklung eines generischen Robots für das SconeFramework (in progress), 2002.
Herunterladen