Ausgewählte Implementierungsprobleme - Informatik - FB3

Transcription

Ausgewählte Implementierungsprobleme - Informatik - FB3
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Sowohl für interaktiv erarbeiten, als auch nachschlagen später
Vorgehen:
1
2
3
4
Aufgabenstellung
Ausgangscode runterladen und verstehen
Lücke(n) füllen
Musterlösung runterladen, vergleichen und verstehen
Nur einige Kernprobleme durch Aufgabenstellung, Rest durch
Ausgangscode bzw. Musterlösung → beides gut durcharbeiten
Sollte Ausgangsbasis für eigene Experimente sein
auch andere Quellen benutzten (hauptsächlich JavaDoc)
soll Anfangswissen für technischen Prototypen geben
möglichst zu Hause schon durcharbeiten dann Fragen stellen
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Themenübersicht
1
13. Nov: Multithreading + Serialisierung
2
20. Nov: Swing
3
27. Nov: TCP, Sockets
4
4. Dez: SSL, RMI
5
11. Dez: JDBC, OR-Mapper (Hibernate, JPox, Java Persistence API,
Castor, ...)
6
18. Dez: XML-Parser
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Multithreading I
mehrere Aufgaben gleichzeitig bearbeiten:
GUI neu darstellen und gleichzeitig mit dem Server kommunizieren
mehrere Clientverbindungen verarbeiten
java.lang.Thread kapselt einen Ausführungsfaden
es gibt immer einen Thread
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Multithreading II
Einsprungpunkt für neu erzeugte Threads ist
java.lang.Runnable.run()
wenn Runnable.run() verlassen wird, stirbt der Thread
entweder von Thread ableiten oder Runnable implementieren
start mit new MyThread().start() bzw. new
Thread(myRunnable).start()
myThread.start() erzeugt den neuen Thread und ruft dann run()
auf
mit myThread.join() wartet der aktuelle Thread, bis myThread
gestorben ist
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Aufgabe 1
Aufgabe: eine bestimmte Anzahl Threads erzeugen, starten und
warten, bis sie ihr Aufgabe beendet haben
WorkingThread :
ist Threadklasse
es soll work() aufgerufen werden
es fehlt der Konstruktor und die run -Methode
ThreadsTest
Hauptprogramm, welches die Threads erzeugt, startet und auf das Ende
warten soll
es fehlt die Implementierung der 3 Methoden
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Gemeinsamer Zugriff I
Daten können, sollten und werden von mehreren Threads gleichzeitig
genutzt
Thread kann während der Arbeit an den Daten unterbrochen werden
atomare Operation: Arbeit, während der keine Unterbrechung
stattfinden kann
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Aufgabe 2 I
erstmal nur Ausgangscode
n Threads erhöhen einen Wert um 1, n andere erniedrigen
erwartetes Ergebnis ist 0
ist es aber nicht
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Gemeinsamer Zugriff II
Problem: x = x + y ist keine atomare Operation
Lesen und Schreiben sind atomare Operationen, aber selbst beim
long Type nicht
Lösung 1:
während man an den Daten arbeitet wird man nicht unterbrochen
aka Interrupts sperren
verpönt und nicht möglich in Java
Lösung 2:
ALLE Benutzer der gemeinsamen Daten stimmen einem Protokoll zu:
nur maximal ein Benutzer darf mit den Daten arbeiten (lesen und/oder
schreiben)
Exklusivität durch Monitore (Feature von Java)
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Gemeinsamer Zugriff III
jedes Objekt hat einen Monitor, java.lang.Object reicht
nur maximal ein Thread kann den Monitor haben, andere müssen
warten, bis der erste Thread den Monitor abgegeben hat
Thread verliert keine Monitore, wenn er unterbrochen wird
synchronized ( objectAlsMonitor ) {
// E x k l u s i v e r B e r e i c h
}
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Aufgabe 2 II
Aufgabe: sichere den Bereich der Berechnung (in run ) durch einen
Monitor ab, so dass bei jedem Aufruf das Ergebnis das erwartete
Ergebnis (0) ist.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Benachrichtigungen I
Beispiel: Produzent (Clientverbindung auf dem Server) und
Konsument (Verarbeiter) haben eine Liste von noch offenen Aufgaben
als gemeinsame Daten.
Problem: wie kann der Produzent den Konsumenten benachrichtigen,
dass es neue Aufgaben gibt? Bzw. wie kann der Konsument auf neue
Aufgaben warten?
Lösung 1:
Busy-wait
der Konsument fragt in einer Schleife laufend nach, ob es neue Arbeit
gibt
besser: kurzzeitige Selbstunterbrechung (Schlafen legen)
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Benachrichtigungen II
Lösung 2:
Produzent benachrichtigt Konsument
Konsument “legt sich auf dem Monitor schlafen”
synchronized ( objectAlsMonitor ) {
objectAlsMonitor . wait ( ) ;
}
Produzent weckt ihn über den Monitor auf
synchronized ( objectAlsMonitor ) {
objectAlsMonitor . notify ();
// o d e r
objectAlsMonitor . n o t i f y A l l ();
}
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Gemeinsamer Zugriff
Benachrichtigungen
Aufgabe 3
Aufgabe: busy-wait Lösung so umstellen, dass sie Benachrichtigungen
verwendet
Beachte, dass sowohl die Consumers auf den Producer warten, als
auch ProducerConsumerExample auf die Consumers
die zwei vorhandenen busy-wait Stellen sind an Thread.sleep() zu
erkennen.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Persistenzproblem & CSV
Binärformat
Serialisierung
Einführung
Anforderungen: Zeiterfassung im offline-Modus, keine Datenbank auf
dem Klienten
Eingaben müssen bis zur nächsten Serververbindung gespeichert
werden
Lösung 1:
eine CSV-Datei (comma seperated values)
zum Schreiben java.io.PrintWriter
zum Lesen java.io.BufferedReader
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Persistenzproblem & CSV
Binärformat
Serialisierung
Aufgabe 1
Aufgabe: fülle die 3 Methoden mit Code um in einer Datei alle
Studenten im Format
<f i r s t n a m e >;< l a s t n a m e >;< l o g i n >;< m a t r i k u l a t i o n N u m b e r >;<mark>
abzuspeichern.
Welche Probleme kann es geben?
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Persistenzproblem & CSV
Binärformat
Serialisierung
Binärformat
Probleme: bei CSV müssen die speziellen Zeichen Semikolon und
Newline verhindert werden
eine mögliche Lösung: URL-Format, z.B. %3B statt ;
eine andere: Länge voranstellen: 6:Thomas
Lösung 2: Binärformat
schreiben mit java.io.DataOutputStream , lesen mit
java.io.DataInputStream
für jeden Primitivtype eine readXXX() und writeXXX() Methode
readUTF() und writeUTF() für Strings
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Persistenzproblem & CSV
Binärformat
Serialisierung
Aufgabe 2
Aufgabe: fülle die 3 Methoden mit Code um in einer Datei alle
Studenten im Binärformat abzuspeichern. Die Datei soll am Anfang
die Anzahl der Einträge (Studenten) enthalten. Danach sollen die
entsprechenden Felder der einzelnen Einträge folgen.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Persistenzproblem & CSV
Binärformat
Serialisierung
Objekte
Geht es einfacher? Ja!
Java kennt die einzelnen Felder der Klassen auch selber →
Serialisierung
Lösung 3: Serialisierung
schreiben mit java.io.ObjectOutputStream.writeObject() ,
lesen mit java.io.ObjectInputStream.readObject()
Klassen müssen das Markierungsinterface java.io.Serializable
implementieren, um zu zeigen, dass sie mit der Serialisierung
einverstanden sind
writeObject() bildet einen Objektgraphen auf einen Bytestrom ab
alle durch das Startobjekt erreichbaren Objekte werden serialisiert →
manchmal wird mehr serialisiert, als man wünscht
Container wie ArrayList implementieren auch Serializable →
man kann gleich den ganzen Container serialisieren
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Persistenzproblem & CSV
Binärformat
Serialisierung
Aufgabe 3
Aufgabe: fülle die 3 Methoden mit Code um alle Studenten zu
serialisieren, und dann in einer Datei zu speichern und natürlich auch
wieder zu laden.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
AWT ist das erste GUI-Toolkit für Java
AWT hat platformspezifisches Aussehen
Swing:
einheitliches Aussehen
mehr und mächtige Komponenten
insgesamt besser
benötigt mehr Resourcen (etwas langsamer als AWT)
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Komponenten
alle in javax.swing.*
JLabel eine Beschriftung
JButton ein Knopf
JCheckBox ein “Häckchen”-Knopf
JPanel ein (per-default) unsichtbarer Container
JFrame ein Hauptfenster
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Generelles Vorgehen
1
Erzeugen der Objekte: einfach mit Konstruktor
2
Setzen von spez. Eigenschaften wie Fonts oder Listeners
3
Zusammenfügen: Objekte werden den Containern hinzugefügt
4
Anzeigen: Top-Level Objekt reicht
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Listener I
Benannte innere Klasse:
c l a s s MyListener implements A c t i o n L i s t e n e r {
p ub l i c void actionPerformed ( ActionEvent e ) {
...
}
}
myComponent . a d d A c t i o n L i s t e n e r ( new M y L i s t e n e r ( ) ) ;
Anonyme innere Klasse:
myComponent . a d d A c t i o n L i s t e n e r ( new A c t i o n L i s t e n e r ( ) {
p ub l i c void actionPerformed ( ActionEvent e ) {
...
}
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Listener II
besser ist es in der Listener-Methode eine andere aufzurufen
p r i v a t e void doSort () {
...
}
s o r t B u t t o n . a d d A c t i o n L i s t e n e r ( new A c t i o n L i s t e n e r ( ) {
p ub l i c void actionPerformed ( ActionEvent e ) {
doSort ( ) ;
}
});
weitere Listener:
ActionListener für JButton
KeyListener
MouseListener
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Container
hauptsächlich JPanel: myPanel.add(someComponent);
jeder Container hat einen LayoutManager; später mehr
JFrame ist speziell:
myFrame.getContentPane().add(myMainPanel);
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Anzeigen
JFrame:
// O p t i o n a l : Wenn d a s X g e d r ü c k t w i r d −> System . e x i t
f r a m e . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
// O p t i o n a l : Z e n t r i e r t a u f dem B i l d s c h i r m
frame . s e t L o c a t i o n R e l a t i v e T o ( n u l l ) ;
// L a y o u t e n
f r a m e . pack ( ) ;
// A n z e i g e n
frame . s e t V i s i b l e ( t r u e ) ;
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 1
Wir wollen schrittweise eine Eingabemaske aufbauen, um Pizza zu
bestellen.
Die erste Aufgabe ist ein kleines Fenster zu erstellen, welche ein
JLabel und einen JButton enthält. Wenn auf den Button gedrückt
wird, soll das Programm beendet werden.
Beispiel:
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JTextField
JTextField einzeilige Texteingabe
Initialwert über Konstruktor oder setText
aktueller Wert der Texteingabe mit getText
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Layout
Wh: jeder Container hat einen LayoutManager
Default von JPanel ist java.awt.FlowLayout
setzen im Konstruktor oder mit set-Methode
FlowLayout: wie Wörter im Text; Umbruch an bestimmter Stelle
GridLayout:
java.awt.GridLayout
m*n Tabelle
alle Kinder haben gleiche Größe
Dimensionen im Konstruktor angeben
Auffüllen wie Leserichtung (Zeile-für-Zeile, in der Zeile von links nach
rechts)
Hinzufügen mit panel.add(component);
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 2
In der zweiten Aufgabe soll 3 JLabels und 3 JTextFields angezeigt
werden. Zusätzlich sollen die Buttons richtigen Namen bekommen.
Für das Layout soll GridLayout eingesetzt werden.
Beispiel:
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDialog
JDialog Dialog als Hauptfenster
kann modal sein (Eingabe in andere Fenster nicht möglich solange
modaler Dialog offen ist)
Anzeigen wie JFrame
auch myDialog.getContentPane().add(myMainPanel); wie bei
JFrame
owner im Konstruktor kann null sein
Anmerkung: bei einem modalen JDialog kehrt setVisible erst
zurück, wenn der Dialog zerstört wurde
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 3
In der dritten Aufgabe wollen wir das Ganze in einem entsprechenden
Rahmen fassen. Dazu gibt ein Datenhaltungsobjekt Order , einen
OrderDialog und ein kleines Hauptprogramm.
Der Code soll so abgeändert werden, dass OrderDialog die Daten,
welche in Order schon enthalten sind als Startwerte für die Anzeige
nimmt. Das Drücken der Escape Taste soll dem Drücken des
Cancel-Buttons entsprechen.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JOptionPane
statische Hilfsklasse um einfach und schnell Dialoge anzuzeigen
möglich sind Meldungen aber auch Entscheidungen
Beispiel: JOptionPane.showMessageDialog(parentComponent,
meldung, titel, messageType);
messageType kann z.B. JOptionPane.WARNING MESSAGE sein
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 4
In der vierten Aufgabe sollen die Daten des Benutzers überprüft
werden. Denkt euch Regeln für die Eingabe aus, und überprüft sie,
wenn der Benutzer den Send-Knopf drückt. Zeigt den Fehler in einem
extra Dialog an. Wenn die Validierung erfolgreich war, soll das
übergebene Order Objekt aktualsiert werden. Dies kann dann vom
Aufrufer ausgewertet werden.
Beispiel:
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JTabbedPane
Container um einzelne Komponenten als Karteikarten anzuzeigen
Karteikarten bekommen einen Namen
immer nur eine Karteikarte sichtbar
Hinzufügen mit: myTabbedPane.add("name", someComponent);
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Tooltips
für alle Swing-Componenten möglich
comp.setToolTipText("ein text");
mit null wird der Tooltip gelöscht
HTML möglich!!!
comp.setToolTipText("<html>Zeile1<br>Zeile2</html>");
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 5
In der fünften Aufgabe soll ein JTabbedPane eingesetzt werden, um
Platz für die eigentliche der Pizza zu bekommen. Diese Karteikarte
bleibt aber erstmal leer. Desweiteren sollen die Elemente Tooltips
bekommen.
Beispiel:
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
MVC
MVC (Model-View-Controller) ist ein Architekturmuster zur Trennung
von Daten (Model), der Präsentation (View) und der
Programmsteuerung (Controller)
Swing ist nach MVC aufgebaut
→ fast jede Swingkomponente hat ein Model (ja, selbst das einfach
JTextField hat eins)
Modelle werden per Default erzeugt; man kann aber auch ein eigenes
angeben
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JComboBox
eine Dropdown-Box: Auswahl von genau einem Wert aus einer Menge
für JComboBox gibt es das ComboBoxModel
Elemente im Konstruktor oder über Model übergeben (Konstruktor
reicht sowieso nur durch)
das aktuell ausgewählte Element mit getSelected* bzw.
setSelected* bearbeiten
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JList
eine Liste
entweder nur maximal ein Element selektierbar oder beliebig viele
(default)
hat auch ein Model wie JComboBox, gleiches gilt für das Setzen bzw.
Abfragen der Selektion
intern hat JList aber statt eines einfachen Wertes, der die aktuelle
Selektion speichert ein ListSelectionModel an die Anfragen wie
setSelectedIndex weitergeleitet werden
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 6
In der sechsten Aufgabe wollen wir uns endlich der eigentlichen Pizza
zuwenden. Eine Pizza hat eine Größe und eine Menge von Zutaten
(Ingredient). Über eine Dropdown-Box ( JComboBox ) soll der
Benutzer die Größe auswählen können. In einer Liste sollen die
Zutaten erscheinen. Hier kann der Benutzer mehrere auswählen.
Beachte: der Startwert soll dem aktuellen Wert der übergebenen Order
entsprechen.
Beispiel:
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Mauszeiger
alle Komonenten können einen Mauszeiger gesetzt bekommen
comp.setCursor(myCursor);
java.awt.Cursor
Menge von vordefinierten Cursortypen
auch möglich eigene Cursor zu definieren
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JProgressBar
Fortschrittsanzeige
minimal und maximal Wert (z.B. 0 und 100)
aktualisieren mit myBar.setValue(24);
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 7
In der letzten Aufgabe soll die Bestellung abgeschickt werden. Dazu
soll ein Fortschrittsanzeige benutzt werden. Auch soll der Mauszeiger
des Bestelldialogs in einen Wartezeiger wechseln (und natürlich auch
wieder zurück). Auch soll das Abschicken fehlschlagen können
(benutzt dazu z.B. das Express flag). In diesem Fehlerfall soll ein
Dialog dieses anzeigen und der Benutzer soll weiter editieren können.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Offene Themen
Nicht behandelt aber interessant:
JTable Daten in einer Tabelle darstellen
JTree Bäume darstellen
JSlider Zahlenwerte einfach einstellen
JScrollPane Um Listen, Tabellen und Bäume zu scrollen
Border beliebige Rahmen (auch benannte) um alle Objekte möglich
weitere Layouts
Menüs
Tastaturkürzel
Renderer (List, Tree, Table)
und noch vieles mehr ...
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Netzwerk
wir verwenden TCP-Verbindungen statt UDP
TCP bietet bidirektionale Datenströme
Identifikation über Ports (0 - 216 − 1) auf Quell- und Zielrechner
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Vorgehen
1
2
3
4
5
6
Server erzeugt einen Socket auf einem bekannten Port ( new
ServerSocket(port) )
Server lauscht auf diesem nach eingehenden Verbindungen (
serverSocket.accept() ) accept() blockiert hierbei
Client erzeugt einen Socket mit der Serveradresse und dem Serverport
und verbindet sich zu diesem ( new Socket(servername,
serverport) )
auf der Server kehrt accept() mit dem serverseitigen Socket der
Verbindung zurück. Der ServerSocket kann weiter verwendet werden.
Kommunikation ( socket.getInputStream() bzw.
socket.getOutputStream() )
eine der Seiten schliesst die Verbindung ( socket.close() )
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 1
Es soll eine Verbindung zwischen zwei seperaten Programmen (Client und
Server) aufgebaut werden.
Der Server soll einen Verdoppelungservice anbieten. Es soll ein Byte lesen
und den doppelten Wert zurückschicken. Der Server soll nicht unbedingt
mehrere Clientverbindungen hintereinander bzw. parallel unterstützen. Die
erste Aufgabe soll einfach sein.
Der Client soll mit java.util.Random eine Menge von Zufallszahlen
erzeugen, und diese vom Server verdoppeln lassen. Das Ergebnis des Server
soll der Client lokal überprüfen.
Anmerkung: Es sollen die Methoden InputStream.read() bzw.
OutputStream.write() verwendet werden. Diese lesen bzw. schreiben
Bytes und nicht Integer, wie das die Signatur
der
Funktionen vielleicht
Ausgewählte
Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 2
Die zwei Einschränkungen der letzten Aufgabe (keine Clientverbindungen
hintereinander, keine parallelen Clientverbindungen) sollen beseitigt werden.
Erweitert den Server, so dass mehrmalige Verbindungen unterstützt werden.
Hinweis hier ist, dass dafür accept mehrmals aufgerufen werden muss.
Erweitern den Server so, dass mehrere Cliente parallel mit der Server
arbeiten können. Hinweis: pro Clientverbindung ein Thread.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 3
Das bisherige Serviceinterface für den Server ist nicht wirklich verständlich
und sicher.
Ändert das Interface von 1 Byte hinsenden, 1 Byte zurücksenden auf ein
Stringbasiertes Interface ab. Dabei soll der Client eine Anfrage (Request)
schicken (eine Zeile) und der Server eine Antwort (Response). Diese soll
auch wieder eine Zeile sein. Die Anfrage soll wie folgt aussehen: "add:23"
die Antwort dann "result:46" . Hinweis: Zu verwenden sind
PrintStream und DataInputStream .
Der Server soll bei einer fehlerhaften Anfrage die Abarbeitung dieser
Verbindung abbrechen.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 4
Alternativ und insbesondere typesicherer kann man die Kommunikation mit
Hilfe von Serialisierung machen.
Ändert die Kommunikation so, dass der Client serialisierte Anfragen an den
Server und der Server entsprechende Antwortobjekte zurückschickt.
Um die Kommunikation allgemein zu halten sollen die Klassen Request
und Response eingeführt werden und davon die speziellen Klassen
AddRequest sowie ResultResponse abgeleitet werden.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 5
Im bisherigen Server arbeiten alle Klienten zwar parallel aber tauschen
keine Daten aus. Dies ist nicht realistisch. Es soll der Server um eine Model
Klasse erweitert werden, welche alle Daten der Anwendung beinhaltet, nur
einmal vorhanden ist und von allen Klienten gemeinsam benutzt wird. Des
weiteren soll die Verarbeitung der Anfragen von der ClientConnection
Klasse in die RequestProcessor ausgelagert werden. Bei einer richtigen
Anwendung würde hier ein Teil der Businesslogik stehen.
Über den ChangeNameRequest ist es möglich, dass mehrere Klienten
gleichzeitig auf die Daten zugreifen. Dies soll geschützt werden.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
transparente Verschlüsselung
optionale Authentifizierung beider Parteien über Zertifikate
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Vorgehen
1
Erzeugen eines Schlüssel/Zerifikat-Paares für den Server
2
Verteilen des Server-Zertifikats an die Clienten (kopieren, per email,...)
Anpassen der Java-Programme
3
1
2
Setzen von KeyStore/TrustStore über Properties
Sockets und ServerSockets werden über Factories statt über den
Konstruktur erzeugt
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Kryptographie
asymmetrische Verschlüsselung
ein öffentlicher und ein privater Schlüssel gehören zusammen
Klartext wird mit öffentlicher Schlüssel verschlüssel und kann nur mit
dem privaten Schlüssel entschlüsselt werden
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Zertifikate
Zertifikat enthält:
Identität
öffentlichen Schlüssel
Beglaubigungen
Beglaubigungen über Kette von Zertifikaten bzw. Web-of-Trust
Alternativ: Selbstbeglaubigung
X.509 als Standard für Zertifikate
Zertifikate können in verschiedenen Containern liegen
viele Containerformate: PEM, DER, PKCS#10, PKCS#12, RFC 1421
usw.
für Java: Java Key Store (JKS) (ist ein Binärcontainer)
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JKS
der Keystore ist mit einem Passwort geschützt
Einträge werden über ein Alias(-Name) referenziert
das Tool keytool vom JDK dient zum berarbeiten
auch wenn der Name KeyStore es nicht nahelegt, kann eine JKS auch
Zertifikate enthalten
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Schlüssel erzeugen
Tool keytool vom JDK
Erzeugen mit keytool -genkey ...
die erstellte Datei enthält den privaten Schlüssel mit einem
Selbstzertifikat
Zertifikat muss für die Verteilung abgetrennt werden: keytool
-export ...
gesamter Ablauf in generate ssl key.sh
Ergebnis: zwei JKS Dateien
eine Datei mit dem privaten Schlüssel für den Server
eine Datei mit dem Zertifikat zum Verteilen an die Clienten
vergleichbares Vorgehen, wenn SSL-Schlüssel für alle Clienten erstellt
werden sollen
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Bekanntgeben in Java I
die Dateinamen und die Passwörter für die Dateien müssen dem
Javaprogramm bekannt sein
Zwei Varianten:
über Zuweisen von Properties
über manuelles Erstellen von SSL Klassen und viel mehr Handarbeit
(wollen wir nicht)
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Bekanntgeben in Java II
auf der Seite, welche den privaten Schlüssel hat (bei uns der Server)
muss der Keystore gesetzt werden
entweder mit java -Djavax.net.ssl.keyStore=... oder mit
System.setProperty
System . s e t P r o p e r t y ( ” j a v a x . n e t . s s l . k e y S t o r e ” ,
” / p a t h / t o / j k s −w i t h −the −p r i v a t e −k e y ” ) ;
System . s e t P r o p e r t y ( ” j a v a x . n e t . s s l . k e y S t o r e P a s s w o r d ” ,
” thePassword ” ) ;
auf der anderen Seite muss der Truststore gesetzt werden
siehe Ausgangscode für Aufgabe 1
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Erzeugen von SSLSockets
Sowohl Socket als auch ServerSocket bisher über Konstruktur erzeugt
für SSL über eine Factory (
javax.net.ssl.SSLServerSocketFactory bzw.
javax.net.ssl.SSLSocketFactory )
Vorgehen:
1
2
Factoryinstanz besorgen: SSLServerSocketFactory.getDefault()
Socketinstanz erzeugen lassen:
mySslServerSocketFactory.createServerSocket(...)
Parameter sind vergleichbar zu denen des normalen
Konstruktoraufrufes
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 1
Wandelt das erste Netzwerkbeispiel so ab, dass die Kommunikation durch
SSL abgesichert wird. An der eigentlichen Funktionaltät soll nichts
geändert werden.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
Remote Method Invocation
Verteiltes Objektsystem
Registry als Anker um an Referenzen zu kommen
ähnlich CORBA
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Methodenaufruf
Nicht mehr Client → Server sondern Caller → Callee
Caller und callee könne in der gleichen VM, unterschiedlichen VMs auf
dem gleichen Rechner oder auf unterschiedlichen Rechnern sein.
Macht keinen Unterschied.
Aufruf mit RMI indirekt:
1
2
3
4
5
6
7
Caller hat ein Stellvertreterobjekt (Proxy) vom Callee, welches das
gleiche Interface wie der eigentliche Callee hat
Caller ruft Proxy auf
Proxy marshallt die Daten: serialisiert alle Parameter
Daten werden über VM Grenzen zu einem weiteren Hilfsobjekt geschickt
Hilfsobjekt packt die Daten aus (unmarshalling)
Hilfsobjekt führt den Aufruf auf dem Callee aus
Rückgabewert wird über den gleichen Weg (Hilfsobjekt, Serialisierung,
Proxy, Caller) zurückgegeben
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Schlüsse
der Proxy muss das gleiche Interface wie das aufgerufene Objekt
haben → es wird ein interface deklariert und nur Methoden aus
diesem Interface können durch RMI verwendet werden
irgendwoher muss das Proxyobjekt kommen, und auch wissen, wo das
“richtige” Objekt liegt
→ Referenzen (die Proxies) müssen verteilt werden
geht über Registry (vergleichbar zu DNS bzw. gelben Seiten)
Registry muss auch ein RMI Objekt sein
woher die Referenz für die Registry nehmen (bootstrapping problem)
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Nutzobjekte
Implementieren den eigentlichen Service, der angeboten werden soll
zu jedem Objekt existiert mind. ein Interface
das Interface ist von java.rmi.Remote abgeleitet
die Implementierung des Interfaces leitet von
java.rmi.server.UnicastRemoteObject ab
alle Methoden des Interfaces werfen java.rmi.RemoteException
p u b l i c i n t e r f a c e Foo e x t e n d s Remote { . . . }
p u b l i c c l a s s FooImpl e x t e n d s UnicastRemoteObject
i m p l e m e n t s Foo { . . . }
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Vorgehen
hier Server: stellt einen Service zur Verfügung hier Client: benutz den
Service durch eine Aufruf
1
2
3
4
5
6
Server beschafft sich die Referenz zu einer Registry
Server erzeugt ein Objekt, welches zur Verfügung gestellt werden soll
Server trägt das Objekt in der Registry unter einem bestimmten
Namen ein
Client beschafft sich die Referenz zu der Registry, die auch der Server
verwendet hat
Client holt sich unter dem gleichen Name von der Registry die
Referenz auf das Nutzobjekt
Client verwendet Nutzobjekt
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Registry
Verschiedene Implementierungen möglich und unterstützt
einfachste ist mitgelieferte
// S e r v e r : C r e a t e
LocateRegistry . createRegistry ( port ) ;
// C l i e n t : Get
L o c a t e R e g i s t r y . g e t R e g i s t r y ( ” hostname ” , p o r t ) ;
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Aufgabe 1
Implementiert den bekannten addiere-zwei-Integer Service mit RMI. Die
Lösung umfasst die folgenden 4 Klassen:
Adder Interface mit der add Methode
AdderImpl Implementierung von Adder
Server Erzeugt Instanz von AdderImpl und macht diese über die
Registry verfügbar
Client Holt sich die Referenz zu Adder über die Registry und testet
diese mit Zufallszahlen.
Testet eure Lösung auch für dann Fall, dass Server und Client auf
verschiedenen Rechnern laufen.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Authentifizierung
Aufrufe sind Stateless → zwei Aufrufe sind nicht verkettbar → keine
Clientverbindung, die der Server einmalig authentisieren könnte
Alternativen suchen (keine Schöne bekannt)
Alternative 1: die Ausgabe der Referenz beschränken, ABER die
Referenzen können erraten werden
Alternative 2: die Authentifizierungsinformationen (Login+Passwort)
für bei jedem Aufruf übertragen, ABER dadurch verliert die RMI
Lösung viel von der Eleganz
Alternative 3: ein Hack, der mit den Sockets, welche RMI verwendet,
rumspielt
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Rest
es ist möglich und auch unterstützt RMI über SSL laufen zu lassen
rmiregistry als externer Registry-Prozess
seit JDK 1.5 dynamische Erzeugung der Proxyklassen und der
Hilfsklassen. Vorher: Erzeugung mit rmic
Bei Rückgabe von einem Remote-Objekt wir nur der Proxy
zurückgegeben, sonst eine Kopie.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Einführung
JDBC erlaubt Zugriff auf Datenbank
Package java.sql
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Vorgehen
1
Treiber laden Class.forName(...)
2
Verbindung aufbauen DriverManager.getConnection(url,
username,password)
Beliebig oft parallel:
3
1
2
Statement erzeugen connection.createStatement()
Beliebig oft hintereinander:
1
2
3
4
Statement ausführen statement.execute() bzw.
statement.executeQuery()
Ergebnisse verwenden ( ResultSet )
Statement schliessen statement.close()
Verbindung schliessen connection.close()
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Datenbanken
für Projekt MySQL
hier eine embedded Datenbank, da einfacher aufzusetzen
100% Java, nur ein Jar, DB als 3 Dateien
hier H2 (http://www.h2database.com/)
Treibername: "org.h2.Driver"
Url-Syntax: "jdbc:h2:/tmp/testdb" wobei ”/tmp/testdb” der
Dateiname der DB ist
Username ist "sa" , Passwort leer
Datenbank wird automatisch erzeugt
Webinterface auf dem lokalen Rechner
h2/bin/h2.jar muss zum Classpath hinzugefügt werden
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Aufgabe1
Schreibe eine Anwendung, welche eine Tabelle mit zwei Spalten (eine
ID-Spalte vom Typ integer, eine Spalte “Name” vom Typ String) erzeugt.
Es sollen dann die Namen “Hello” und “World” sowie alle übergebenen
Kommandozeilenparameter der Tabelle hinzugefügt werden.
Der Inhalt der Tabelle soll auf dem Bildschirm ausgegeben werden.
Bei welchen Eingaben gibt es Probleme?
Verwendet für die SQL-Anfragen der Ausgangscode.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
PreparedStatement
eigentlich Optimiertung von Anfragen, da die Anfrage vorverarbeitet
wird
löst auch das Problem der problematischen Zeichen
(Anführungszeichen, Komma,...) (war Problem bei letzter Aufgabe)
Platzhalter werden duch Fragezeichen definiert
diese Platzhalter werden dann mit Werte besetzt
wiederverwendbar
Vorgehen:
1
2
3
PreparedStatement erzeugen connection.prepareStatement(sql)
Werte setzen preparedStatement.setXXX(platzhalterNr, wert)
Ausführen preparedStatement.execute()
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Aufgabe2
Verändert eure Lösung von Aufgabe1 so, dass sie PreparedStatements
verwendet, und damit auch mit ungewöhnlichen
Kommandozeilenparameter keine Probleme hat.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Weitere JDBC-Themen
Transaktionen (notwendig?)
Auto-commit um schneller zu sein
Verschiedene SQL-Datentypen
connection pooling
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Architektur
Was sind die Anforderungen an die Schnittstelle der DB-Komponente
auf dem Server?
einfacher Austausch der DB (MySQL, Postgres, Oracle, ...)
einfacher Austausch der Zugriffsart (JDBC, Hibernate, JDO,...)
wenige Änderungen, wenn sich die Menge/Art der Objektdaten ändert
Lösung: POJO und DAO
weite Unterstützung von den Frameworks
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
POJO
Plain Old Java Object
Klassen, welche (fast) nur Domainwissen enthalten
meist nur Datencontainer mit keinen Anwendungslogik (private
Attribute + setter/getter)
Vererbung erlaubt
Vorteil: können von allen Schichten (UI, Businesslogik, DB) gleich gut
verwendet werden
sind also nicht auf spezielle Zugriffsarten bzw. Schichten zugeschnitten
habt ihr schon mit dem Datenmodell definiert
haben meist eine ID (int oder String), welche für die DB notwendig
ist, aber im engeren Sinne nicht Teil des Domainmodels ist
siehe auch DTO (Data Transfer Object)
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
DAO
Data Access Object
Interface welches Zugriff auf die DB bereitstellt
bietet meist CRUD (Create, Read, Update, Delete) Funktionalität an
ein DAO Interface ist für Objekte einer Klasse zuständig
Durch Interface wird Entkoppelung von der Implementierung erreicht
meist eine Factory, welche DAO-Instanzen erzeugt, Alternative ist die
Implementierungsklassen hart in den Benutzer zu codieren
kein State ausser DB-Verbindung → Singleton
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Aufgabe3
Verändert eure Lösung von Aufgabe2 so, dass sie POJOs und DAOs
verwendet. Das DAO soll über folgende Methoden verfügen.
v o i d c r e a t e ( Foo f ) ;
Foo r e a d ( i n t i d ) ;
Foo [ ] r e a d A l l ( ) ;
v o i d u p d a t e ( Foo f ) ;
v o i d d e l e t e ( Foo f ) ;
Erweitert das Programm so, dass es alle neuen Methoden sinnvoll
verwendet.
Erstellt eine Factory, welche die DAO-Instanzen verwaltet und ausgibt.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Assoziationen I
Beispiel: Es gibt eine Studentengruppe und Studenten. Ein Student ist
in genau einer Gruppe.
Wie wird das gespeichert?
Jeder Student hat ein Attribute gruppe , welches den Typ der
ID-Spalte von Gruppe hat.
ist eine 1:n Relation
die 2 Anderen sind 1:1 und m:n
m:n immer mit extra Tabelle
1:1 mit extra Spalte oder mit gleichem primär Schlüssel
1:1 wird eher selten gebraucht
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Assoziationen II
Wie soll jetzt der Zugriff darauf im POJO aussehen? (Annahme ID ist
ein Integer)
1
2
Student hat eine Methode int getGroup()
Student hat eine Methode Group getGroup()
die erste Methode ist die einfachere
bei der zweiten Methode wird das abhängige Objekt/die abhängigen
Objekte auch mit ausgelesen und als POJOs konstruiert → weniger
DAO Aufrufe im restlichen Code aber zusätzliche Probleme
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Assoziationen III
bestimmt möchte man gern alle Studenten einer Gruppe haben
Alternativen:
1
2
3
Gruppe hat keine solche Methode, muss über spezielle Methode im
Studenten-DAO gemacht werden
Gruppe hat eine Methode List<Integer> getStudents()
Gruppe hat eine Methode List<Student> getStudents()
die Letzte wäre schon nicht schlecht, da könnte man ja einfach
group.getStudents().add(myNewStudent);
groupDao.update(gropup); schreiben
die Letzte ist aber auch die Komplizierteste
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Probleme mit Assoziationen
bei der letzten Alternative gibt ein paar Probleme
wenn man beim Laden eines Objektes alle assoziierten Objekte lädt,
müssten ja eigentlich auch alle mit den assoziierten Objekten
assoziierten Objekte geladen werden. usw.
Lösung: lazy loading, hier werden die Listen von assoziierten Objekte
nur bei Bedarf/beim Zugriff darauf geladen
erzeugt neue Probleme (asynchron muss eine DB-Verbindung
aufgebaut werden)
Was soll passieren, wenn ein Student hinzugefügt wurde, welcher noch
gar nicht in der DB gespeichert ist?
Lösung: Kaskadierung, d.h. der Student wird erstmal in der DB
erzeugt
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Einführung
die DAO-Implementierungen sind sehr vorhersagbar und sich
wiederholend
Idee: werden von einem Framework übernommen
Vorteile:
1
2
3
4
genaue Spezifikation des Datenmodells (meist in XML)
wesentlich weniger SQL-Anweisungen
Transaktionssupport
vollständige OO-Modellierung des Datenmodell in Java (immer die
letzte Alternative)
Nachteile:
1
2
Einarbeitungsaufwand
die Probleme der Assoziationen sind immer noch da
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Warnung
Die Vergangenheit zeigt, dass die
Verwendung von Mapping-Frameworks ein
hohes Risiko darstellt.
Der geplante Aufwand wird meist um ein größeres Vielfaches überschritten.
Hauptproblem sind Relationen/Assoziationen.
Eine Möglichkeit ist das Mapping Framework ohne die
Relationsunterstützung zu verwenden. D.h. es gibt nur int getGroup()
in Student.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Liste – Die großen Drei
Hibernate wird wohl am häufigsten verwendet
(http://www.hibernate.org/)
JDO (Java Data Objects) ist ein Standard von SUN
(http://java.sun.com/products/jdo/) Implementierungen:
JPOX (http://www.jpox.org/)
TJDO (http://tjdo.sourceforge.net/)
OJB (http://db.apache.org/ojb/)
Castor (http://castor.exolab.org/)
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Liste – Andere
Torque (http://db.apache.org/torque/)
Ibatis SQL Maps
(http://java-source.net/open-source/persistence/ibatis-sql-maps)
Java Ultra-Lite Persistence (http://julp.sourceforge.net/)
JDBCPersistence (http://www.jdbcpersistence.org/)
SeQuaLite (http://sequalite.sourceforge.net/)
viele weitere
Vergleich: http://www.devx.com/Java/Article/33768/0/page/1
ich kann keine Empfehlung geben
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Einführung
Auch mit “Hausmitteln” kann man eine pure JDBC-Implementierung
verschlanken.
Zutaten sind:
Reflektion und BeanUtils
möglichst wenige Sonderfälle
Verwendung von JDK 1.5 Features
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
BeanUtils
Teil von Apache-Commons (http://commons.apache.org/beanutils/)
Damit ist es möglich Properties in Objekten abzufragen und zu setzen
Map<S t r i n g , C l a s s > m = B e a n U t i l s . d e s c r i b e ( o b j ) ;
f o r ( S t r i n g name : m. k e y S e t ( ) ) {
O b j e c t v a l u e = m. g e t ( name ) ;
C l a s s t y p e = P r o p e r t y U t i l s . g e t P r o p e r t y T y p e ( o b j , name ) ;
System . o u t . p r i n t f ( ” p r o p e r t y : %−20s t y p e : %−40s v a l u e : %s \n” ,
name , t y p e , v a l u e ) ;
}
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
JDBC
POJO und DAO
Assoziationen
Mapping-Frameworks
Verbesserung einer JDBC-Implementierung
Weitere Gedanken
Es wird einfacher, wenn Propertyname und Spaltennamen gleich sind.
Es ist möglich einen allgemeinen DAO zu schreiben, der dann, wie eine
Liste, durch den Nutzdatentyp spezialisiert wird
Über varargs lassen sich spezifische Filterabfragen implementieren
Foo [ ] f i n d B y P a r a m e t e r ( O b j e c t . . . o b j s ) { . . . }
...
x = studentDao . findByParameter ( ” gruppe ” , 2 3 ) ;
http://www.javaworld.com/javaworld/ \
jw-05-2002/jw-0524-sql.html?page=1
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Einführung
XML sind strukturierte hierarchische Daten
Schreiben ist einfacher und nicht relevant für SWP
Zu lösen für SWP: Einlesen und Extrahieren von Informationen aus
XML-Datei
<r o o t −e l e m e n t>
<!−− T h i s i s a comment −−>
<someElement s o m e A t t r i b u t e=” s o m e v a l u e ”> <!−− s t a r t −t a g −−>
some c o n t e n t
</ someElement>
<!−− end−t a g −−>
<e m p t y : e l e m e n t −w i t h A t t r i b u t e s f o o=” 42 ” />
</ r o o t −e l e m e n t>
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
SAX
Simple API for Xml (SAX) (http://www.saxproject.org/)
Parser parst XML-Datei und ruft bei bestimmten Ereignissen
Funktionen auf
Vorteile: schnell, wenig Speicher
Nachteile: Kontext nur eingeschränkt vorhanden
Klassen liegen im Package org.xml.sax
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Vorgehen
// E i n e SAX−P a r s e r I n s t a n z b e s o r g e n
XMLReader r e a d e r = XMLReaderFactory . createXMLReader ( ) ;
// U n s e r e r H a n d l e r m i t den s p e z . C a l l b a c k s
MyHandler h a n d l e r = new MyHandler ( ) ;
// I n s t a l l i e r e n
reader . setContentHandler ( handler ) ;
reader . setErrorHandler ( handler );
// Und s t a r t e n
r e a d e r . p a r s e ( new I n p u t S o u r c e ( new F i l e R e a d e r ( f i l e n a m e ) ) ) ;
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Aufgabe1
XMI ist ein Standard zum Austausch von UML-Diagrammen. Mit SAX
sollen die Datei WebLog en.uml eingelesen werden und zum Schluss die
Liste aller Klassennamen ausgegeben werden.
Klassen sind packagedElement Elemente, wobei das Attribute “type”
den Wert “uml:Class” hat.
Die Ausgabe sollte somit [User, BlogEntry, CreateAccount,
EditAccount, Login, CreateBlog, ViewBlogs] sein.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
DOM
Document Object Model (DOM) (http://www.w3.org/DOM/)
Parser parst XML-Datei komplett in den Speicher als Baum. Dieser
kann dann traversiert werden.
Vorteile: Kontext vollständig vorhanden (notwendig für semantische
Überprüfung)
Nachteile: langsamer, mehr Speicher
Klassen liegen im Package org.w3c.dom
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Vorgehen
// I n s t a n z b e s o r g e n
DocumentBuilderFactory f a c t o r y =
DocumentBuilderFactory . newInstance ( ) ;
DocumentBuilder b u i l d e r = f a c t o r y . newDocumentBuilder ( ) ;
// P a r s e n . E r g e b n i s i s t W u r z e l k n o t e n
Document doc = b u i l d e r . p a r s e ( f i l e n a m e ) ;
Document ist ein Node . Damit Traversierung vom kompletten Baum
möglich.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Aufgabe2
Aufgabe 1 mit DOM lösen.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Digester
Apache-Commons Digester (http://commons.apache.org/digester/)
Was möchte man eigentlich? Aus XML-Daten Java-Objekte erstellen
lassen. Mit möglichst wenig Aufwand.
Digester ist nicht die Erste und nicht die Einzigste Lösung.
Benutzer gibt Regeln an. Durch Reflektion wird daraus der
anwendungsspez. Objektbaum.
Vorteile: wenig Programmieraufwand, Daten sind danach in spez.
Javaklassen, low-level Sachen wie SAX und DOM werden gekapselt,
erweiterbare Typkonvertierung
Nachteile: eigentlich keiner (ist nicht beim JDK mit dabei)
baut intern auf SAX auf
Klassen liegen im Package org.apache.commons.digester
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Vorgehen
// I n s t a n z b e s o r g e n
D i g e s t e r d i g e s t e r = new D i g e s t e r ( ) ;
// R e g e l n zum D i g e s t e r h i n z u f ü g e n
...
// S t a r t e n
M yTop Le v e l O b j e c t r e s u l t = ( M yTop Leve l O bj e ct )
d i g e s t e r . p a r s e ( new F i l e R e a d e r ( f i l e n a m e ) ) ;
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Regeln
sind Regeln für eine Stackmaschine
pattern beschreibt, wann die Regeln ausgeführt werden.
Beispiele für pattern sind “xyz/foo” oder “xyz/foo/bar”
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Übliche Regeln
// e i n e I n s t a n t von c l a s s N a m e e r z e u g e n
d i g e s t e r . addObjectCreate ( ” p a t t e r n ” , ” className ” ) ;
// a l l e XML−A t t r i b u t e w e r t e
// a l s Java−P r o p e r t i e s s e t z t e n
digester . addSetProperties (” pattern ” );
// den Body d e s XML−E l e m e n t e s u n t e r
// dem Java−P r o p e r t y p r o p e r t y N a m e s p e i c h e r n
d i g e s t e r . a d d B e a n P r o p e r t y S e t t e r ( ” p a t t e r n ” , ” propertyName ” ) ;
// a u f dem v o r h e r i g e n S t a c k o b j e c t w i r d methodName
// m i t dem a k t . O b j e k t a l s P a r a m e t e r a u f g e r u f e n
d i g e s t e r . a d d S e t N e x t ( ” p a t t e r n ” , ”methodName” ) ;
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Aufgabe3
Unter sample.xml ist ein Brotbackrezept abgespeichert. Dies soll mit den
Digester eingelesen werden. Die Datenklassen Recipe und Ingredient
sind schon vorhanden und sollen durch den Digester instantiiert werden.
Für diese Aufgabe ist es notwenig den Digester und entsprechnden
Abhängigkeiten runterzuladen und dem Classpath hinzuzufügen.
Ausgewählte Implementierungsprobleme
Einführung
Multithreading
Serialisierung
Swing
Netzwerk
SSL
RMI
JDBC
XML
Einführung
SAX
DOM
Digester
Ausblick
Ausblick
Nicht behandelt wurden auf
Encoding
Validierung von XML (Stichwort DTD)
Namespaces
Ausgewählte Implementierungsprobleme