RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Software-Engineering-Projekt Berufsakademie Horb Studiengang Informationstechnik Java RMI und SOAP Timo Holzherr, Marc Wodischek IT2003 BA - Horb Florianstraße 15 72160 Horb a. N. [email protected] [email protected] Betreuender Dozent: Prof. Dr.-Ing. Olaf Herden Dezember 2005 1 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Abstract In der Folgenden Arbeit werden Grundlagen, Vorgehensweisen in der Verwendung sowie Implementierung von RMI 1 bzw. SOAP 2 , der Programmiersprache Java erläutert. Dies geschieht mit Hilfe eines Beispielprogramms. Dieses Beispielprogramm ist ein Online-Spiel, das an klassische „Battleship“ (Schiffe versenken) - Spiel erinnern soll. Mithilfe dieses Spieles werden die Technologien sowie deren Implementierung erklärt und die theoretischen Grundkenntnisse verständlich illustriert. Auf die Implementierung des Spieles, dessen Algorithmen und den Aufbau des Applets, mit der Grafischen Benutzeroberfläche wird nur eingegangen, falls dies zum Verständnis der themenbezogenen Programmteile erforderlich ist. 1 2 Remote Method Invocation (Erklärung s. Abschnitt 1) Simple Object Access Protocol (Erklärung s. Abschnitt 6) 2 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Inhaltsverzeichnis Java RMI und SOAP......................................................................................................... 1 Abstract............................................................................................................................. 2 Inhaltsverzeichnis ............................................................................................................. 3 1 Einleitung.................................................................................................................. 4 2 Nutzen von entfernten Zugriffen / Aufrufen ............................................................. 5 2.1.1 2.2 Das RMI Protokoll.............................................................................................. 6 2.3 Allgemeine Probleme ......................................................................................... 7 2.3.1 Netzwerkbasierende Probleme.................................................................. 7 2.3.2 Speicherbasierende Probleme ................................................................... 8 2.4 Entfernte Objekte allgemein ............................................................................... 8 2.4.1 3 4 Java RMI (Remote Method Invocation).................................................... 5 Entfernte Schnittstellen definieren ............................................................ 9 Entfernte Objekte implementieren mit JAVA-RMI................................................ 10 3.1 Aufbau und Besonderheiten bei der Implementierung ..................................... 10 3.2 Entfernte Methoden implementieren ................................................................ 11 3.3 Serialisierung .................................................................................................... 11 3.4 der DistributedGC............................................................................................. 13 SOAP ...................................................................................................................... 14 4.1 Einleitung ......................................................................................................... 14 4.2 Aufbau und Ablauf eines SOAP-Methodenaufrufes ........................................ 15 4.3 SOAP-Implementierungen ............................................................................... 16 4.3.1 Clientseitige SOAP-Programmierung ..................................................... 17 4.3.2 Serverseitige SOAP-Programmierung .................................................... 19 5 Fazit ........................................................................................................................ 21 6 Literaturverzeichnis ................................................................................................ 21 3 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr 1 Einleitung Aufgrund der rasanten Entwicklung auf dem Computermarkt in Bezug auf Geschwindigkeit, Ressourcen, Bedienbarkeit (Usability), Preis und vor allem steigender Kenntnis von Anwendern, hat sich auch die Art der Verwendung stark verändert. Waren früher Computer nur etwas für Institute mit wissenschaftlichem oder militärischem Hintergrund, so zeigte sich schnell ein Trend in Richtung „Personal Computer“ („PC“). Die Komponenten wurden für den Massenmarkt hergestellt und somit billiger. Programme wurden auf benutzerfreundliche Bedienung ausgelegt und es wurde stark zwischen Server oder Supercomputer und Personal Computer in Hinsicht auf Entwicklung unterschieden. So wurde auch die Arbeitsweise mit dem Computer verändert. War es zu Beginn noch eine große Rechenmaschine, die Arbeit für eine ganze Abteilung übernahm, da nicht jeder Mitarbeiter einen Computer hatte, so wurde dies in den letzten Jahren so verändert, dass nun jeder Mitarbeiter oder auch jedes Familienmitglied seinen eigenen Computer hat, da dieser stark genug wurde um alle Aufgaben, die der Benutzer hat, gut ausführen zu können. Nun kommen wir mit Dual-Core 1 Prozessoren, neuen verbesserten Prozessorarchitekturen mit mehreren ALUs 2 , größeren Speichern, kleineren Strukturen, geringerem Stromverbrauch und der Rechenleistung in neue Dimensionen. Dies und verbesserte Netzwerkarchitekturen mit höherer Bandbreite sowie moderne Betriebssysteme mit echter Multiuser Unterstützung oder auch Funktionen wie „Remote Desktop“ erwirken einen weiteren Wandel in der Verwendung von Computern. Es wird nun ein weiterer Schritt eingeführt, dass ein sehr leistungsfähiger PC zur Verfügung steht, auf den alle Benutzer zugreifen können und so von seiner Rechenleistung profitieren. Ein weiterer Vorteil ist, dass auch Daten aller Anwender lokal für alle zugreifbar gespeichert werden können. Benötigt werden nun jedoch Technologien, wie „Remote Desktop“, oder Multiuser Fähigkeit von Betriebssystemen um es den Benutzern zu ermöglichen über externe Verbindungen den Computer zu nutzen. Sun stellt Java mit RMI/SOAP genau solche Technologien zur Verfügung, die entfernte Zugriffe auf Methoden oder Funktionen nutzen. 1 Als Dual-Core-Prozessor (Doppelkernprozessor) bezeichnet man einen Multi-Core-Prozessor mit genau zwei Hauptprozessoren. Als Multi-Core-Prozessor (auch: Mehrkernprozessor oder Multikernprozessor), bezeichnet man einen Mikroprozessor mit mehr als einem vollständigen Hauptprozessor. 2 Eine Arithmetic Logical Unit (ALU, zu deutsch arithmetisch-logische Einheit) ist ein elektronisches Rechenwerk, welches in Prozessoren zum Einsatz kommt. 4 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr 2 Nutzen von entfernten Zugriffen / Aufrufen Um die Funktion von RMI so gut wie möglich zu erklären sollte ein Beispiel auf der Tatsache der neuen Art der Benutzung von Computern, wie auch schon in der Einleitung beschrieben, aufgebaut werden. Denkt man an Aufgabengebiete, bei denen Supercomputer immer noch nötig sind, so fällt schnell das Beispiel der Simulationen ein. Simulationen werden in einem breiten Bereich der Forschung und Entwicklung eingesetzt. Sie sollen immer präziser werden und sind dies auch geworden. Dies benötigt jedoch Rechenleistung. Rechenleistung, die ein „Personal Computer“ wie ihn der Mitarbeiter / Forscher besitzt, nicht zur Verfügung stellen kann. Man will jedoch nicht den starken Simulationscomputer besetzten während man mit Implementierung und ähnlichem beschäftigt ist. So wäre es das Beste man könnte auf dem eigenen Laptop die Vorarbeit leisten und später die Berechnung vom Simulationscomputer durchführen lassen. Genau dies ist Sinn und Zweck der Remote Method Invocation 1 „RMI“. 2.1.1 Java RMI (Remote Method Invocation) Verwenden wir nun das Beispiel von der Simulation weiter um Java RMI zu erklären. Um in Programmen die Leistungsfähigkeit des Simulationsrechners nutzen zu können wäre es perfekt, wenn die komplizierte, rechenaufwändige Funktion auf diesem Computer laufen würde. Das Programm soll jedoch mit grafischer Oberfläche und Eingabeparametern dem Benutzer auf dessen PC zur Verfügung stehen. Man sollte also die Server-Funktionen wie lokale Funktionen aussehen lassen. Ein solches Modell, haben Birrel und Nelson bereits 1984 vorgestellt. (Quelle: Java ist auch eine Insel.) In unserem Beispiel wäre es nun so, dass der Benutzer eine Funktion aufruft, z.B. plot(crash_simulation(parameter1,parameter2)); Diese sich jedoch auf dem Server befindet und auch dort verarbeitet wird: double crash_simulation(double param1 , double param2) { //Komplizierte Berechnung Differentialgleichungen viele for - Schleifen usw.… } Wichtig ist nun noch die Verbindung zwischen Client und Server. Im Normalfall spricht der Client nicht direkt mit dem Server, sondern über Stellvertreterobjekte (engl. Proxies). Über diese Proxies wird die Verbindung aufgebaut. Für den Client sieht diese Funktion wie eine Serverfunktion aus, dabei verpackt sie die Informationen und sendet diese an den Server weiter. Daher wird die Implementiereung des Aufrufs der Simulationsfunktion crash_simulation() auf Client Seite eher so aussehen: 1 Aufruf von entfernten Methoden (remote = entfernt , Method = Methode , invocation = Aufruf) 5 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr double crash_simulation(double param1 , double param2) { // Verbindung aufbauen // die Parameter übernehmen und an den Server schicken ( „write(param1 , param2)“) // Auf das Ergebnis warten und… // Ergebnis Ausgeben.“ plot(Ergebnis);“ } Abbildung 1: Unterschiede zwischen Verbindung mit und ohne Proxy. (Quelle: http://publib.boulder.ibm.com) Der Verbindungsaufbau kann über Sockets 1 geschehen. Hier ist ein bestimmter Ablauf programmiert. Der Server wartet auf Anfragen von Clients. Dann entnimmt er aus dem gesendeten Paket seine Aufgaben und ruft seine dazu passende Funktion auf. 2.2 Das RMI Protokoll RMI in Java ( aufzurufen. ) ist die Technologie um entfernte Objekte und deren Methoden Ähnlich wie beim OSI 2 - Schichten - Modell verwendet RMI auch verschiedene Abstraktionsebenen. 1 Ein Socket (wörtlich übersetzt "Sockel" oder "Steckverbindungen") ist eine bi-direktionale SoftwareSchnittstelle zur Interprozess- (IPC) oder Netzwerk-Kommunikation. 2 Das OSI-Modell (engl. Open Systems Interconnection Reference Model) ist ein offenes Schichtenmodell für die Kommunikation informationsverarbeitender Systeme. Es handelt sich um vereinheitlichte Verfahren und Regeln für den Austausch von Daten. 6 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Sockets sind wie bereits angesprochen eine Lösung für den Verbindungsaufbau. Es ist jedoch auch möglich, die Übermittlung der Daten mittels http - Anfragen zu steuern. Auch verschlüsselte Verbindungen über SSL 1 sind denkbar oder auch Verbindung über UDP 2 . All diese Protokolle sind zusammengefasst unter dem Begriff „RMI Wire Protocol“. Abbildung 2: Architektur von RMI 2.3 Allgemeine Probleme Während RMI eine Lösung für das Problem der entfernten Aufrufe liefert, gibt es einige Probleme, die nicht nur durch Software gelöst werden können. 2.3.1 Netzwerkbasierende Probleme Ein grundlegendes Problem ist die allgemeine Bereitstellung eines Kommunikationssystems. Doch ein Kommunikationssystem löst nicht alle Probleme einer Verbindung. Es muss sichergestellt werden, dass die Verbindung auch immer vorhanden ist, oder dass die Daten in einwandfreiem Zustand ankommen. Da beide Rechner physikalisch voneinander getrennt sind und dadurch verschiedene Lebenszyklen haben, kann nicht immer garantiert werden, dass eine Kommunikation möglich ist. Ist der Server aufgrund verschiedener Einwirkungen nicht erreichbar, so muss dies der Client erkennen und darauf reagieren. Hier können nur typische Vorgehensweisen verwendet werden wie z.B. über einen Zeitablauf (Timeout) zu gehen. 1 Transport Layer Security (TLS) oder Secure Sockets Layer (SSL) ist ein Verschlüsselungsprotokoll für Datenübertragungen im Internet. 2 Das User Datagram Protocol (UDP) ist ein minimales, verbindungsloses Netzprotokoll. Es gehört zur Transportschicht der TCP/IP-Protokollfamilie und ist im Gegensatz zu TCP nicht auf Zuverlässigkeit ausgelegt. 7 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Zudem ist die Zeit ein kritischer Faktor. Da bei entfernten Verbindungen die Abarbeitungszyklen deutlich höher sind als bei lokalen Aufrufen, muss das Abarbeiten zeitkritisch beobachtet werden. Die zeitlichen Probleme kommen vor allem von der Verbindung über Netzwerke wie von zusätzlichen Implementierungen, die einen entfernten Aufruf erst ermöglichen z.B. Proxy Aufbau und Verbindung über Sockets. Hier muss wie beschrieben jede Aufgabe in Anfragen verpackt werden. 2.3.2 Speicherbasierende Probleme Wie schon angesprochen ist eine Hauptursache für Probleme mit entfernten Zugriffen und Aufrufen die physikalische Trennung der zwei Geräte. So haben die beiden Rechner verschiedene Laufzeiten mit verschiedenen Prozessoren und vor allem verschiedenem Speicher. Wichtig ist es die Zugriffe exklusiv erfolgen zu lassen, da sonst Änderungen des Benutzers verloren gehen könnten. Werden beim Benutzer Änderungen vorgenommen, so werden sich diese nicht auf die Referenz des Objektes, mit der, der Server arbeitet, übernommen. Werden die Daten nun vom Server zurückgespielt, werden die Änderungen überschrieben. Somit wird deutlich, dass normale Referenzen nicht ausreichen. Große, umfangreiche Objekte müssen öfter serialisiert werden. Das Problem dabei ist jedoch, dass nicht alle Objekte serialisierbar sind. Vor allem Systemklassen können nicht einfach übertragen und serialisieren. 2.4 Entfernte Objekte allgemein Der Begriff Middleware bezeichnet in der Informatik im Allgemeinen eine Schicht zwischen zwei Prozessen. Einerseits um die Komplexität der jeweilig anderen Seite zu verbergen, oder um eine einfach zu implementierende eindeutig definierte Schnittstelle zwischen den Prozessen zu liefern. Somit wird die Kopplung zweier Systeme entzerrt. Es ist eine Zwischenschicht und ist wie der Server für den Client und der Client für den Server, obwohl keine direkte Verbindung besteht. Es kommuniziert sozusagen die Middleware mit dem Server und mit dem Client und stellt somit die Verbindung her. Ein weiteres Einsatzgebiet ist die Trennung zwischen Datenbank und Benutzerprogramm. Das Benutzerprogramm ist nicht direkt mit der Datenbank verbunden, sondern gibt seine Anfragen an die Middleware weiter, die dann die Ergebnisse von der Datenbank abholt, um Sie dann dem Benutzerprogramm wieder zugänglich zu machen. Ein großer Vorteil ist, dass zum Beispiel die Anbindung der Datenbank zur Middleware verbessert werden kann, ohne dass der Benutzer ein Update seines Programms benötigt. 8 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr 2.4.1 Entfernte Schnittstellen definieren Wie bereits erwähnt, wird die Verbindung über eine Art Middleware vorgenommen. Will der Benutzer nun also Methoden nutzen, muss er die Middleware, also ein Stellvertreterobjekt befragen, welches die Daten nun für ihn verwaltet. Das heißt, es packt die Daten ein und übermittelt sie. Diese Hilfsfunktionen werden automatisch generiert. Sie müssen jedoch definiert werden, um passenden Quellcode für die Übertragung zu erzeugen. Bei Java RMI ist dies die Definition eines Interface mit den benötigten Methoden, z.B.: import import import import java.io.Serializable; java.rmi.Remote; java.rmi.RemoteException; java.util.Vector; public interface ReceiveMessageInterface extends Remote, Serializable { void startGame(Game game) throws RemoteException; //…usw. … } Diese Implementierung in unserem Spiel, zeigt die wichtigsten Eigenschaften der Schnittstelle: - Die eigene Schnittstelle erbt von der Schnittstelle „Remote“ und erweitert diese. Dies ist nötig, da nur Klassen, die von Remote erben, entfernte Methoden anbieten können. Remote ist ein „leeres“ Interface, es sind also keine Methoden vorgegeben, die implementiert werden müssen. - Jede „Remote“ - Methode muss die Anweisung „throws RemoteException“ besitzen, da die angegebenen Methoden nicht beabsichtigte Fehler auslösen können. 9 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr 3 Entfernte Objekte implementieren mit JAVA-RMI 3.1 Aufbau und Besonderheiten bei der Implementierung Der Server ist ein wichtiger Bestandteil und der Client muss über den Stellvertreter mit ihm kommunizieren können. Er muss einige Vorgaben erfüllen, damit die Verbindung zustande kommen kann. Er muss die entfernte Schnittstelle implementieren, einen speziellen Konstruktor besitzen und eine Klasse erweitern. Implementiert sieht die Klasse RMIServer folgendermaßen aus. : public class RmiServer extends UnicastRemoteObject implements ReceiveMessageInterface { public static void main(String args[]) { try { int port=3232; if((args!=null) && (args.length>0) && (args[0]!=null)) { try { port=new Integer(args[0]).intValue(); } catch(NumberFormatException nfe) { System.err.println("Falscher Port!“); } } new RmiServer(port); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } public RmiServer(int port) throws RemoteException { registry = LocateRegistry.createRegistry( thisPort ); registry.rebind("rmiServer", this); System.out.println("RMI-Server gestartet”); } } 10 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Wie bereits erwähnt, muss unsere RMIServer Klasse eine andere Klasse erweitern. Diese ist die „UnicastRemoteObject“ - Klasse aus dem Java – RMI – Paket. Durch die Methoden, die RMIServer.java von UnicastRemoteObject erbt, wird eine Übertragung von Daten über ein Standard-TCP/IP Socket ermöglicht. Wie man erkennt ist auch der Konstruktor in RMIServer.java kein Standardkonstruktor. Er hat zwei spezielle Eigenschaften. Von der Deklaration her ist er ein Standardkonstruktor. Er ruft jedoch automatisch den Konstruktor der Oberklasse, also von UnicastRemoteObject, auf. Es besteht bei der Implementierung des Servers jedoch auch ein Problem: Es kann sein, dass entfernte Klassen schon von einer anderen Klasse erben, und somit gegen die Mehrfachvererbung verstoßen würden. In diesem Fall, muss die implementierende Klasse ausgelagert werden. 3.2 Entfernte Methoden implementieren Entfernte Methoden werden wie alle anderen Methoden implementiert. Es ist jedoch wichtig die RemoteException zu werfen, falls ein Verbindungsfehler oder ähnliches eintritt. public void startGame(Game game) throws RemoteException { … game.start(); } 3.3 Serialisierung Ein Hauptpunkt bei Java RMI ist die Serialisierung. Die Besonderheit ist, wie bereits erwähnt, dass bei den entfernten Aufrufen nicht spezielle Zeichenketten als Art Protokoll übergeben werden, sondern komplette Objekte. Um auf die Klassen/Objekte und deren Methoden zugreifen zu können, müssen diese bei Namensdiensten angemeldet sein. Dies nennt man Serialisierung der Klassen. Es gibt hierfür in Java zwei Möglichkeiten. Einmal über die Methode Naming und über die Methode Registry. 11 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Mithilfe dieser Methoden wird der zu verwendende Port angegeben und dann einmal auf Serverseite das Objekt bekannt gemacht. Das heißt, das Objekt bekommt einen Namen unter dem der Client es finden kann. Dem Client muss ebenfalls gesagt werden, welchen Port er verwenden soll. Er legt nun das Objekt an, damit er es wie einen normalen Aufruf im weiteren Programm verwenden kann. Die Implementierung ist im Codebaispiel auf Seite 9 zu sehen. Der Aufruf der Methode bzw. wie das Objekt nun weiter verwendet wird, ist im Codebeispiel auf Seite 10 ersichtlich. Die mit der Naming Methode verbundene Syntax, hat immer wieder einige Befehle gemein, die kurz erwähnt werden sollen: - Bind/Unbind (Serverseitig zu An/Abmeldung des Objektes) - Lookup (Clientseitig um nach dem Server-Objekt „Ausschau“ zu halten) 12 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr 3.4 der DistributedGC Da die Lebensdauer entfernter Objekte nicht genau festgelegt und überprüft werden kann, kommen spezielle Anforderungen an den “Garbage Collector”(GC) 1 der JVM 2 hinzu. Im normalen Betrieb weiß der GC immer, wann Objekte referenziert und wieder dereferenziert werden. Somit kann er einfach die fälligen Speicherbereiche wieder leeren. Im entfernten Aufruf ist dies jedoch nicht möglich. Daher muss über einen zusätzlichen Mechanismus klargestellt werden, wann die Objekte referenziert und wieder dereferenziert werden. Es werden also referenced-flags beim Nutzen der Verbindung mitgeliefert. Genauso ein dereferenced flag beim Lösen der Verbindung. Die Klasse bleibt bis zum endgültigen Löschen aus dem Speicher jedoch noch einige Zeit auf dem Server erhalten. Man kann diese Verweildauer auch explizit angeben. Bsp: java –Djava.rmi.dcg.leaseValue=30 MyClass 1 Automatische Speicherbereinigung oder Garbage-Collection (GC) (auch Freispeichersammlung) ist ein Verfahren zur regelmäßigen automatischen Wiederverfügbarmachung von nicht mehr benötigtem Speicher und anderen Betriebsmitteln, indem nicht mehr erreichbare Objekte im Speicher automatisch freigegeben werden. 2 Die Java Virtual Machine (abgekürzt Java VM oder JVM) ist eine Laufzeitumgebung und virtuelle Maschine für Software. Die Java Virtual Machine führt den so genannten Java-Bytecode aus und kann als Pendant zur Common Language Runtime bei Microsoft .NET gesehen werden. 13 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr 4 4.1 SOAP Einleitung Es gibt verschiedene Ansätze, entfernte Methodenaufrufe auszuführen. Das oben bereits erwähnte Verfahren RMI ist eines davon. Der Nachteil dieser Kommunikation ist jedoch, dass sich diese Applikation an einen TCP/IP - Port bindet, was oft eher als sicherheitstechnisch bedenklich eingestuft wird. Viele Firewalls und Proxy-Server erlauben zudem oft nur eine Netzwerk-Kommunikation über den TCP-Port 80 (HTTP 1 ). Aus diesem Grund ist oft ein Verfahren, Daten zu übertragen, nötig, welches die Informationen über Port 80 bezieht und sendet. Eine sehr einfache Realisierung dieser Aufgabe könnte man durch dynamische Webseiten (mit PHP o.ä. erstellt) erreichen. Die Webseiten werden aufgerufen und bekommen die benötigten Informationen beispielsweise im Post-Header übertragen. Darauf kann das serverseitige Skript reagieren und entsprechende Ausgaben an den Client zurückgeben. Dies wäre jedoch eine sehr „einfache“ Lösung und hat kaum objektorientierten Charakter. Die Übertragenen Daten können nur aus Strings bestehen, bieten also nicht wie RMI die Möglichkeit bequem Objekte zu übertragen. Diesen Vorteil vereinigt SOAP mit dem Vorteil, über das HTTP-Protokoll Daten zu übertragen. SOAP steht für Simple Object Access Protocol und wird seit 1998 entwickelt. Die Firmen, die sich bei der Entwicklung dieses Protokolls anfänglich beteiligten waren, sind DevelopMentor, IBM, Lotus Development Corp., Microsoft und UserLand Software. Das Protokoll ist XML-basiert und beschreibt die Art und Weise, wie Inhalte (Serialisierung 2 ) und die XML-Daten übertragen werden. Die Übertragung selbst regelt SOAP nicht. Dafür wird meist das HTTP-Protokoll verwendet. Durch SOAP wird der entfernte Methodenaufruf geregelt und ausgeführt. Dabei übergibt der Aufrufende Parameter, die in Form einer XML-Struktur an den verarbeitenden Kommunikationspartner weitergegeben werden. Dieser liefert dem aufrufendem ClientProgramm wiederum die Rückgabewerte der Methode in Form einer XML-Struktur zurück. Wie man schon anhand der Beschreibung des Übertragungsweges von SOAP erkennen kann, ist die SOAP-Architektur im Vergleich zu RMI o.ä. sehr flexibel und damit programmiersprachen- und plattformunabhängig. Das Framework von .NET baut vollkommen auf eine Kommunikation mit SOAP auf. 1 Das Hypertext Transfer Protocol (HTTP) ist ein zustandsloses Protokoll zur Übertragung von Daten. Zugeordnet ist dabei die Anwendungsschicht. Diese entspricht im ISO/OSI-Modell der Schicht 7, im üblicherweise im Internet verwendeten TCP/IP-Referenzmodell dagegen der Schicht 5. Primär wird es im Rahmen des World Wide Web zur Übertragung von Webseiten verwendet (Webbrowser greifen fast ausschließlich mit diesem Protokoll auf Web-Server zu). 2 Man versteht darunter eine sequentielle Abbildung von Objekten auf eine externe Darstellungsform, um diese beispielsweise zu übertragen 14 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr An seine Grenzen stößt die SOAP-Architektur jedoch bei Umgebungen, welche eine performante Übertragung erfordern. Ein Beispiel hierfür kann die Kommunikation eines mobilen Endgerätes und einem Server sein. Auch in der Maschinensteuerung müssen Daten in Echtzeit übertragen werden. Hierfür ist SOAP bisher nicht geeignet. Der Grund hierfür ist, dass die XML-Repräsentation der Objekte und Strukturen die Daten sehr groß (ca. Faktor 25 beim Request und Faktor >500 bei der Antwort) macht. Dies beansprucht die Netzwerkbandbreite sehr stark. Zudem erfordert das Parsen der Strukturen zusätzliche Rechenleistung, welche vor allem im mobilen Clientbereich nicht immer ausreichend zur Verfügung steht. Da HTTP ein zustandsloses Protokoll 1 ist, sind Sicherheitsaspekte meist nicht ausreichend gewährleistet. Ein Client könnte sich mit einem Server verbinden und einen Aufruf starten, obwohl die Berechtigung fehlt. Beim Entwerfen von SOAPArchitekturen muss man stets diesen Aspekt mitbetrachten. 4.2 Aufbau und Ablauf eines SOAP-Methodenaufrufes Das Client-Programm benötigt eine Referenz auf den entfernten Server. Diese Referenz ist bei SOAP eine URL auf einen RPC-Router. Der Client sendet ein HTTP-POSTRequest an den HTTP-Server. In den Daten sind in Form einer XML-Struktur (siehe unten) der Name und die Parameter der aufzurufenden Methode beinhaltet. Im nachfolgenden Beispiel ist ein Methodenaufruf dargestellt, der Kreditkartendaten überprüfen soll. Als Parameter erwartet die Methode zwei Strings. Zum einen eine Kreditkartennummer (entspricht <number>) und zum Anderen das Gültigkeitsdatum der Karte (entspricht <valid>). Der Name der Methode, die aufgerufen werden soll, wird in …xmlns:ns1="urn:CardValidator"… festgelegt. Der RPC-Router empfängt diese Informationen und parst die XML-Struktur. Daraufhin wird die im Aufruf angegebene Methode mit den Parametern aufgerufen. Diese Methode berechnet ihr Ergebnis und gibt die Informationen, die an den Client zurückgesendet werden müssen, über den Server an den Client in Form einer XML-Struktur (siehe Beispiel weiter unten) zurück. (Rückgabe erfolgt im Tag <addReturn xsi:type="xsd:string">true</addReturn>) Die Client-Software nimmt das Ergebnis entgegen und die Kommunikation ist beendet. Eine SOAP-Anfrage eines Clients könnte beispielsweise folgendermaßen aussehen (ohne HTTP-Header): <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:validate soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 1 Ein zustandsloses Protokoll ist ein Protokoll, dessen Informationen aus früheren Anforderungen verloren gehen, wenn eine separate Anforderung gemacht wird. 15 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr xmlns:ns1="urn:CardValidator"> <number xsi:type="xsd:string">1234 5678 9876 5432</number> <valid xsi:type="xsd:string">12/08</valid> </ns1:validate> </soapenv:Body> </soapenv:Envelope> Die Antwort vom SOAP-Server (HTTP-Server) darauf könnte folgendermaßen aussehen: <?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope sxmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Body> <ns1:validateResponse soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="urn:CardValidator"> <addReturn xsi:type="xsd:string">true</addReturn> </ns1:validateResponse> </soapenv:Body> </soapenv:Envelope> 4.3 SOAP-Implementierungen Natürlich muss nicht jeder Programmierer selbst server- und clientseitige Software schreiben, welche SOAP-HTTP-Anfragen absetzen kann, auf diese Anfragen reagiert, diese XML-Strukturen parst und nach dem Methodenaufruf wieder XML-Strukturen generiert. Für diese Aufgaben gibt es im Internet viele fertige Implementierungen für unterschiedlichste Programmiersprachen und Systeme. Für die Programmiersprache Java sind die Softwarepakete der Apache Software Foundation zu empfehlen. Diese beinhalten den Tomcat Webserver 1 , der HTTP-Anfragen verarbeiten kann. Der Tomcat-Webserver erfordert eine installierte JRE 2 . Um SOAP-HTTP-Anfragen verarbeiten zu können, benötigt der Tomcat-Server das Apache SOAP-Servlet 3 , welches für die Anfragen später den RPC-Router bildet. 1 2 3 Erhältlich unter http://jakarta.apache.org/tomcat/index.html Java Runtime Environment = Laufzeitumgebung für Java-Programme Erhältlich unter http://xml.apache.org/soap/index.html 16 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr 4.3.1 Clientseitige SOAP-Programmierung Clientseitig bekommt man für Java-Anwendungen ebenfalls von der Apache Software Foundation Klassen, die SOAP-Dienste liefern. Im ZIP-Archiv des Apache SOAPServlets (s.o.) befinden sich auch alle JAR-Dateien, die man zur Entwicklung von SOAP-Client-Anwendungen benötigt: SOAP: soap.jar JAVAMAIL: mail.jar JAF: activation.jar XERCES: xerces.jar Hat man die vier Java-Archive in seine Codebase eingebunden, kann man ein SOAPRequest einem SOAP-Server ausführen. Im Folgenden ist ein Code-Beispiel dargestellt, welches auf einen SOAP-Server, der Beispiele zur Verfügung stellt, verbindet. Der RPC-Router der SOAP-Applikation ist unter der URL „http://213.23.125.181:8080/RPC“ verfügbar. Die Methode, die aufgerufen wird, lautet „ChristmasTree“ und läuft in der SOAP-Object-URI 1 „urn:christmas“. Der Aufruf einer SOAP-Methode wird durch das Call-Objekt realisiert. Zunächst wird im Beispiel ein neues Call-Objekt instanziiert. Diesem Objekt müssen daraufhin alle Attribute, die den Methodenaufruf bestimmen, gesetzt werden. Durch den Aufruf von setTargetURI(String) wird die SOAP-Object-URI festgelegt. Mit dem Befehl setMethodName(String) wird festgelegt, welche SOAP-Methode der Applikation aufgerufen werden soll. Mit setEncodingStyleURI(String) wird festgelegt, wie Objekte serialisiert und transferiert werden sollen. Der EncodingStyle wird in Form eines Namespaces definiert. Je nach angegebenem Namespace wird das Objekt anders serialisiert. Bei Apache SOAP gibt es einige vordefinierten String-Konstanten, die Namespace-Bezeichnungen widerspiegeln. Diese sind in der Klasse org.apache.soap.Constants abgelegt. Für Standard-Java-Objekte (String, Integer, Boolean, etc) ist der Namespace Constants.NS_URI_SOAP_ENC geeignet. Weicht der zu übertragende Objekt-Typ von Standard-Datentypen ab, muss je nach Typ der passende Namespace gewählt werden. 1 Ein SOAP-Object-URI ermöglicht es, mehrere Applikationen auf einem RPC-Router zu installieren. Jede Applikation hat ein eigenes Object-URI, unter der sie erreichbar ist. Jedes Object-URI (also jede Applikation) kann viele Methoden besitzen. 17 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Erwartet die aufzurufende Methode Parameter, kann man diese durch Call.setParams(Vector) setzen. Der Vector beinhaltet eine Liste von ParameterObjekten. Ein Objekt vom Typ Parameter repräsentiert je einen Parameter der aufzurufenden Methode und wird durch den Konstruktor new Parameter(String name, Class type, Object value, String encodingStyleURI) erzeugt. Der Parameter name des Konstruktors steht für den Namen des Parameters der entfernten Methode, der definiert werden soll. Der Parameter type gibt an, von welchem Typ der Parameter ist (Bspw. String.class). Der Parameter value steht für den zu übergebenden Wert. Der Parameter encodingStyleURI gibt an, wie der Parameter serialisiert werden soll (Die Werte, die angegeben werden können, entsprechen denen der Methode setEncodingStyleURI (s.o.)) Dieser Parameter muss jedoch nur angegeben werden, wenn der Wert des Parameters von der Default-Encodingstyle-URI, welche mit Call.setEncodingStyleURI zuvor gesetzt wurde, abweicht. Ist dies nicht der Fall, kann stattdessen null angegeben werden. Sind diese Attribute dem Call-Objekt zugewiesen, kann durch den Aufruf der Methode Call.invoke(java.net.URL, String) der entfernte Methodenaufruf durchgeführt werden. Als Parameter erwartet die Methode zum einen die URL des RPC-Routers (hier „http://213.23.125.181:8080/RPC“). Zum anderen erwartet die Methode den 2. Parameter SOAPActionURI, welche im Normalfall als Leerstring („“) gesetzt werden kann. Die Methode invoke kann bei einem Fehler bei der Kommunikation mit dem SOAPServer eine SOAPException werfen. Diese muss abgefangen werden. Bei erfolgreichem Ausführen der Methode invoke liefert sie ein Response-Objekt zurück, welches die Antwort auf die SOAP-Anfrage repräsentiert. Nicht alle Probleme, die bei der Datenübertragung auftreten können, werfen eine SOAPException. Wird versucht, eine Methode aufzurufen, die nicht existiert, führt dies nicht zu einer Ausnahme. Die Methode generatedFault() gibt Antwort auf die Frage, ob ein interner Fehler auftrat. Ist dies nicht der Fall, so bekommt man durch den Aufruf der Methode Response.getReturnValue() das Ergebnis des Methodenaufrufs in Form eines ParameterObjektes. An den eigentlichen Wert kommt man durch den Aufruf von Response.getReturnValue().getValue(), was eine Referenz vom Typ Object zurückliefert. 18 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Call call = new Call(); call.setTargetObjectURI( "urn:christmas" ); call.setMethodName( "ChristmasTree" ); call.setEncodingStyleURI( Constants.NS_URI_SOAP_ENC ); Vector p = new Vector(); p.addElement( new Parameter("h", double.class, new Double(200), null ) ); p.addElement( new Parameter("r", double.class, new Double(100), null ) ); p.addElement( new Parameter("l", double.class, new Double(10), null ) ); call.setParams( p ); Response resp = null; try { URL url = null; try { url = new URL( "http://213.23.125.181:8080/RPC"; ); } catch ( MalformedURLException e ) {} resp = call.invoke( url, "" ); } catch( SOAPException e ) { System.err.println( "SOAPException (" + e.getFaultCode() + "): " + e.getMessage() ); System.exit(0); } if ( !resp.generatedFault() ) { Parameter ret = resp.getReturnValue(); Object value = ret.getValue(); System.out.println( value ); } else { Fault fault = resp.getFault(); System.err.println( "Fehler bei der Ausführung: " ); System.out.println( " Fault-Code = " + fault.getFaultCode() ); System.out.println( " Fault-String = " + fault.getFaultString() ); } 4.3.2 Serverseitige SOAP-Programmierung Hat man den Tomcat-Webserver und das SOAP-Servlet installiert und konfiguriert, kann man über die Web-Oberfläche von SOAP (siehe Abbildung 1) neue SOAPApplikationen installieren (Deploy). 19 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr Abbildung 3: SOAP-Administrationsoberfläche Um die Methoden, die von SOAP-Requests ausgeführt werden sollen, zu implementieren, erstellt man eine neue Klasse, die jede dieser Methoden implementiert. Beispiel: public class SoapServerClass{ public String getHelloWorldString(){ return(“Hello World”); } } Diese Klasse wird dann beim Installieren einer neuen SOAP-Applikation als Java Provider Class eingetragen. Will man statt den Java Standard-Datentypen eigene Datentypen über die SOAPSchnittstelle übertragen, muss man jeden dieser eigenen Datentypen auch beim Eintragen als SOAP-Applikation in die Type-Mappings-Tabelle eintragen. Es muss definiert werden, wie Objekte serialisiert und deserialisiert werden können. (Java to XML Serializer, XML to Java Deserializer) Unter http://www.soapuser.com/ ist wird sehr detailliert beschrieben, wie man serverund clientseitig SOAP-Programme entwickelt. 20 RMI und SOAP für Java – Seminar-Arbeit von Marc Wodischek und Timo Holzherr 5 Fazit Die Architekturen RMI und SOAP bieten einfache Möglichkeiten zur Übetragung von Objekten. Für die Programmiersprache Java sind gute Bibliotheken erhältlich, die für den Programmierer die Übertragung der Objekte übernehmen. Die Vorraussetzung, dass RMI und SOAP gut funktionieren ist eine gute Netzwerkverbindung zwischen Client- und Server-Computer. Eine Lösung für Netzwerk-Probleme zwischen Client und Server bieten RMI und SOAP jedoch auch nicht. SOAP hat seine Vorteile darin, dass es die Daten über standardisierte Protokolle wie HTTP versendet. Dadurch müssen keine zusätzlichen Ports in Firewalls geöffnet werden. Bei RMI kann zwar der TCP/IP-Port angegeben werden, über den übertragen werden soll, trotzdem wird das RMI- Protokoll verwendet. Zudem ist eine verschlüsselte Übertragung der Daten bei SOAP kein Problem. Da SOAP auf HTTP aufsetzen kann, kann einfach statt HTTP HTTPS verwendet werden. Bei RMI ist eine verschlüsselte Übertragung der Daten nicht ohne Weiteres möglich. SOAP ist programmiersprachenunabhängig, wobei RMI hingegen den Programmierer fast ausschließlich an Java bindet. Ein Nachteil von SOAP ist, dass die Daten durch die XML-Representation während der Übertragung sehr groß werden und deshalb viel Bandbreite benötigen. Beide Architekturen – SOAP und RMI – sind jedoch Plattformunabhängig. 6 Literaturverzeichnis [JA04] Java ist auch eine Insel [Wik05] Wikipedia – Online – Enzyklopädie [SO05] http://www.soapuser.com/ [W305] http://www.w3.org/TR/soap12-part 21