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