1 INHALTSVERZEICHNIS Inhaltsverzeichnis 1 Einleitung 3 2 Das Phänomen der Web Services 2.1 Definition eines Web Services . . . . . . . . . . . . . . . . . . 2.2 Web Services Architecture . . . . . . . . . . . . . . . . . . . . 5 5 6 3 Die Standards SOAP und WSDL 3.1 Simple Object Access Protokoll (SOAP) . . 3.2 Web Service Description Language (WSDL) 3.2.1 Einleitung . . . . . . . . . . . . . . . 3.2.2 Beschreibung des Sprache WSDL . . 3.2.3 SOAP Binding . . . . . . . . . . . . 3.2.4 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 13 13 14 18 20 4 Kategorisierung von lokationsbasierten Diensten 22 4.1 Identifizierung und Klassifizierung von lokationsabhängigen Diensten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.1.1 Output Services . . . . . . . . . . . . . . . . . . . . . 24 4.1.2 Input Services . . . . . . . . . . . . . . . . . . . . . . 26 4.1.3 Storage and Computation Services . . . . . . . . . . . 27 4.1.4 Device Control (Steuerungsdienste) . . . . . . . . . . . 27 4.1.5 Communication Services . . . . . . . . . . . . . . . . . 28 4.2 Konzeption einer WSDL-Taxonomie der Dienste . . . . . . . 28 4.2.1 Ausgabedienste . . . . . . . . . . . . . . . . . . . . . . 29 4.2.2 Input Services . . . . . . . . . . . . . . . . . . . . . . 38 4.2.3 Storage and Computation Services . . . . . . . . . . . 40 4.2.4 Communication Services . . . . . . . . . . . . . . . . . 42 4.3 Weitere wichtige Aspekte bezüglich lokationsbasierter Dienste 46 4.3.1 Autorisierung . . . . . . . . . . . . . . . . . . . . . . . 46 4.3.2 Authentizität . . . . . . . . . . . . . . . . . . . . . . . 47 4.3.3 Abrechnung . . . . . . . . . . . . . . . . . . . . . . . . 49 5 Beispielhafte Implementierungen für Web Services 5.1 Java Web Service Developer Pack . . . . . . . . . . . 5.1.1 Kurzbeschreibung des Pack . . . . . . . . . . 5.1.2 JAX-RPC . . . . . . . . . . . . . . . . . . . . 5.1.3 JAXM und SAAJ . . . . . . . . . . . . . . . 5.2 Beispielimplementierungen für Druckdienste . . . . . 5.2.1 PrintManagement – Bottom-Up-Ansatz . . . 5.2.2 PrintManagement - Top Down Ansatz . . . . 5.2.3 JAXM-basierter PrintService . . . . . . . . . 6 Abschließende Bemerkungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 51 51 52 58 60 61 66 67 73 2 INHALTSVERZEICHNIS A Taxonomie 79 B selbstdefinierte WSDL für den Druckdienst 82 C PrintService – HTTP-Servlet 85 C.1 Client-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 C.2 Service-Code . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 Einleitung 1 3 Einleitung Durch die immer stärker werdende Vernetzung von Rechnern und durch die weitere Verbreitung von unterschiedlichen Devices (wie Handy, PDA, usw.), die auf verschiedenen Plattformen arbeiten, werden verteilte Anwendungen bzw. Systeme immer wichtiger. Unter verteilten Anwendungen sind lose über das Internet gekoppelte Softwarekomponenten zu verstehen, die idealerweise zur Laufzeit zueinander finden und damit den Anforderungen an Flexibilität und Dynamik entsprechen. Um dies zu realisieren, wurde das Konzept der Web Services entwickelt, die sich von normalen Web-Anwendungen dadurch unterscheiden, dass sie nicht auf eine Benutzung durch Menschen, sondern ” auf eine automatisierte Benutzung ausgerichtet sind“ [Kre02]. Sie verwenden XML als plattformunabhängige Sprache zur Beschreibung der Schnittstellen und der Daten, die zwischen den einzelnen Anwendungen übertragen werden. Zur Datenübertragung wird das Internet genutzt, da es heutzutage eine weite Verbreitung erreicht hat und nahezu allgegenwärtig ist. Damit die Anwendungen in der Tat Just in Time“ und automatisch zuein” ander finden, ist eine Standardisierung der Beschreibung von Web Services notwendig. Schließlich sind Maschinen noch nicht in der Lage, die Semantik von verschiedenen Worten zu verstehen, sofern sie nicht eindeutig festgelegt ist. Zur Beschreibung von Web Services und der Nachrichten, die zwischen den Anwendungen ausgetauscht werden, wird ein Standard names WSDL (Web Service Description Language) von der Standardisierungsorganisation W3C entwickelt, der von mehreren großen Unternehmen, unter anderem IBM, Ariba und Microsoft, unterstützt wird und damit gute Aussichten auf verbreitete Verwendung besitzt. Jene Beschreibungssprache wird auch innerhalb der vorliegenden Arbeit benutzt, um Dienste zu beschreiben. Aber Dienste müssen nicht nur beschrieben werden, sie müssen auch publik gemacht werden, andernfalls wäre ein automatisches Service Discovery“ nicht ” möglich. Aufgrund dessen werden die Web Services in öffentlichen Verzeichnissen publiziert, deren Einträge ebenfalls standardisiert sein sollten, damit ein Software-Agent in diesen nach geeigneten Diensten für seinen Client suchen kann. Wichtig ist dabei nicht nur, dass die Dienste in den richtigen Kategorien eingeordnet sind, um gefunden zu werden, sondern auch, dass alle benötigten Auswahlkriterien, wie beispielsweise Kosten und Standort des Dienstes, angegeben sind. Letzteres ist vor allem für lokationsbasierte Dienste wichtig, für die im Rahmen dieser Arbeit eine Taxonomie erstellt wird. In der vorliegenden Arbeit wird in Kapitel 2 zunächst definiert, was unter einem Web Service zu verstehen ist. Ferner werden die einzelnen Komponenten einer Web Service Struktur beschrieben. Anschließend werden in Kapitel 3 das Nachrichtenübertragungsformat SOAP und die Dienstbeschreibungs- 4 Einleitung sprache WSDL beschrieben. Im folgenden Kapitel werden zunächst lokationsbasierte Dienste identifiziert und eine Taxonomie für diese entwickelt. Jene kategorisierten Dienste werden anschließend mit WSDL-Fragmenten beschrieben, wobei der Aspekt Modularisierung berücksichtigt wird. Darüber hinaus werden noch weitere für Web Services wichtige Aspekte diskutiert: Autorisierung, Authentisierung und Abrechnung. Im zweiten Teil der Arbeit (Kapitel 5) wird ein Druckdienst exemplarisch implementiert. Benutzt wird dazu das Java Web Services Developer Pack von Sun Microsystems, insbesondere die APIs JAX-RPC und JAXM. Untersucht wird auch, inwieweit die in Kapitel 4 erstellten WSDL-Fragmente bei der Implementierung verwertet werden können. Das Phänomen der Web Services 2 2.1 5 Das Phänomen der Web Services Definition eines Web Services Frank Coyle bezeichnet in seinem Buch XML, Web Services, and the Da” ta Revolution“ die Web Services als Technologie, Prozess und Phänomen zugleich [COY02]. Aus technologischer Sicht handelt es sich bei Web Services seiner Meinung nach um eine Menge von Protokollen, die auf die durch SOAP, XML und HTTP ermöglichte globale Kopplung von Anwendungen aufbauen. Als Prozess eröffnen Web Services die Möglichkeit, Dienste über das Internet zu entdecken und zu verbinden bzw. zu nutzen. Web Services sind aber auch ein Phänomen, denn die wichtigsten Industrien entwickeln Systeme, die diese Technik unterstützen, da sie etliche Vorteile in sich birgt und sich deswegen weit verbreiten wird. Der Vorteil liegt in der Flexibilität und Effizienz des Konzepts, da es die Verbindung lose gekoppelter Systeme ermöglicht, ohne auf eine spezielle Programmiersprache, Komponentenmodell oder Plattform angewiesen zu sein. Trotz dieser guten Aussichten ist Coyle der Meinung, dass die Technologie Web Service noch in den Kinder” schuhen“ steckt und die bisherigen Unterstützer als Early Adopters“ be” zeichnet werden müssen, und die Investition nicht ganz risikofrei ist, schließlich werden bis zur Reife der Technologie noch einige Jahre vergehen. Des Weiteren können Leute von der losen Kopplung von Services spätestens zur Laufzeit des Programmes erst profitieren, wenn es genügend Unternehmen bzw. Personen gibt, die Web Services über das Internet anbieten und damit eine genügend große Auswahl an solchen Diensten vorhanden ist. Dabei kann ein Web Service alles mögliche anbieten – von einer einfachen Auskunft bis hin zu einer komplizierten Kreditkartentransaktion. Aber was sind Web Services eigentlich? Von der Standardisierungsorganisation W3C werden sie wie folgt definiert: Definition 1 (Web Service) : A Web Service is a software system iden” tified by a URI, whose public interfaces and bindings are defined and described using XML. Its definition can be discovered by other software systems. These systems may then interact with the Web service in a manner prescribed by its definition, using XML based messages conveyed by internet protocols.“ [CHA02] Diese Definition der W3C setzt nur die Nutzung von XML voraus, nicht die Nutzung von Techniken wie SOAP oder WSDL, die nachfolgend beschrieben werden; sie ist damit wesentlich allgemeiner und umfassender, als die Beschreibung eines Web Services von F. Coyle und wird aus diesem Grund in dieser Arbeit als die Definition eines Web Services gewählt. Ein Web Service unterscheidet sich nach der obigen Definition von einer normalen Web-Anwendung dadurch, dass der Austausch von Informationen bzw. Nachrichten auf XML basiert und der Dienst selbst mit Hilfe von XML be- 6 Web Services Architecture schrieben wird. Die Benutzung von XML als Sprache eröffnet die Möglichkeit, dass solche Web Services auch von Maschinen entdeckt und benutzt werden können, ganz ohne das Hinzutun eines Menschen. Im folgenden Abschnitt sollen nun die einzelnen Komponenten eines Web Services genauer beschrieben werden. 2.2 Web Services Architecture Bezüglich der Architektur eines Web Services wird in eine Basis Architek” tur“ und eine Erweiterte Architektur“ unterschieden [CHA02]. In der Ba” ” sis Architektur“ wird ein Web Service als der Austausch von Nachrichten zwischen Software Agents“ beschrieben, die eine der folgenden drei Rollen ” annehmen können: Service Provider“ (Dienstanbieter), Service Requestor“ ” ” (Dienstnachfrager) oder Service Discovery Agency“ (siehe Abbildung 1). ” Discovery Agency Publish Find Service Requestor Refer Interact Service Provider Refer Use Servicedescription Abbildung 1: Basis Architektur. Quelle: [CHA02] Der Service Provider“ stellt einen Dienst, den er implementiert hat, über ” eine URI im Netz zur Verfügung und erstellt eine XML Beschreibung seines Web Services, die angibt, wo der Dienst zu finden ist, welche Operationen er unterstützt, wie das Format der Ein- und Ausgabedaten beschaffen sein muss und welches Protokoll zur Übertragung benutzt werden soll [Kre02]. Diese Beschreibung kann dann im Internet über einen beliebigen Host (dies kann der Service Provider“ selbst sein) veröffentlicht und damit zur Verfügung ” Web Services Architecture 7 gestellt werden. Der Dienst kann anschließend in einem Verzeichnis, einer Service Discovery Agency“, nach unterschiedlichen Kriterien bekannt ge” macht werden. Im dem Verzeichniseintrag kann der Service auf die XMLBeschreibung seines Services verweisen; ist der Dienst in keinem Verzeichnis eingetragen, so kann dies der Dienstanbieter auch selbst tun, ebenso ist es möglich, im Falle fester Vereinbarungen bzw. Geschäftsverbindungen, die Datei mit der Beschreibung direkt an den Client zu senden. Der Service Requestor“, der den Dienst erfragt, kann entweder in dem Ver” zeichnis oder im Internet nach einem für ihn geeigneten Dienst suchen. Hat ein Dienstnachfrager einen entsprechenden Dienst, der seine Auswahlkriterien erfüllt, ausgewählt, kann er diesen Dienst aufrufen. Dazu benutzt er die Dienstbeschreibung, die er über das Verzeichnis oder den Provider des Service-Anbieters erhalten hat. Ein Software-Agent kann dabei gleichzeitig in einer oder mehreren Rollen agieren, dass heißt beispielsweise, dass ein Service Provider“ ebenfalls ein Service Requestor“ sein kann, falls er einen ” ” Teil des angebotenen Dienstes nicht selbst ausführen kann. In der Erweiterten Architektur“ werden neben der eben beschriebenen ” Basisfunktionalität noch zusätzliche Funktionen bzw. Features angeboten, die die vorhandene Technologie und Komponenten erweitern. Hier sind einige Beispiele für zusätzliche Funktionalität: • Asynchronous Messaging • Unterstützung von (langen) Transaktionen • Zuverlässigkeit der Nachrichten (Schutz vor Verlust von Nachrichten) • Vertraulichkeit der Nachrichten (hier gibt es die Möglichkeit einer Kodierung und Dekodierung der Nachricht mittels SOAP oder der Nutzung von SSL) • Session • Authentifizierung und Autorisierung (Möglichkeiten ergeben sich hier durch HTTP auth oder SOAP,...) Für die Realisierung der oben beschriebenen Basis- und Erweiterte Funktionalität werden zurzeit mehrere Spezifikationen entwickelt. Sehr aktiv ist in diesem Bereich die Standardisierungsorganisation W3C, die die Entwicklung in folgenden Bereichen vorantreibt: • UDDI (Universal Description, Discovery, and Integration) – diese Sprache unterstützt das Publizieren und Finden von Diensten in Verzeichnissen. • SOAP (Simple Object Access Protokoll) – ein Nachrichtenformat, das neben der Definition der Struktur einer Nachricht noch zusätzliche Funktionalität übernehmen kann (wie beispielsweise die Autorisierung). 8 Web Services Architecture • WSDL (Web Service Description Language) – dient zur Beschreibung von Web Services. Wie bereits im Kapitel zuvor erwähnt, werden jene Standards nur empfohlen, und es ist keine Pflicht diese Techniken zu verwenden, der einzige Standard, der bei Web Services verpflichtend ist, ist XML. Im nächsten Kapitel werden die beiden Standards SOAP und WSDL näher betrachtet, insbesondere letztere Sprache, da sie zur Erstellung der Taxonomie von lokationsbasierten Diensten in der vorliegenden Arbeit verwendet wird. Die Standards SOAP und WSDL 3 9 Die Standards SOAP und WSDL Der Schwerpunkt dieser Arbeit liegt auf der Erstellung einer WSDL-Taxonomie für lokationsbasierte Dienste und damit auf dem Standard WSDL. In Kapitel 5 werden zwei Beispiele für lokationsabhängige Web Services exemplarisch implementiert, die als Nachrichtenprotokoll SOAP und als Übertragungsprotokoll HTTP verwenden. Aus diesem Grund wird zunächst eine kurze Einführung in SOAP gegeben, bevor dann ausführlich auf WSDL eingegangen wird. Dies soll das Verständnis der in Kapitel 5 vorgestellten Beispielimplementierungen erleichtern, aber keine komplette Einführung in beide Themengebiete darstellen. 3.1 Simple Object Access Protokoll (SOAP) SOAP wurde ursprünglich von der DevelopMentor AG als plattformunabhängiges Protokoll für den Zugriff auf Dienste und Objekte zwischen Applikationen und Servern über HTTP entwickelt. SOAP verwendete dazu ein einfaches XML-basiertes Format, um Remote Procedure Calls und ihre Eingabe- und Rückgabeparameter darzustellen. Im Jahr 1999 wurde die Spezifikation SOAP 1.0, unterstützt von mehreren großen Firmen, veröffentlicht. Durch Beitrag weiterer Firmen (Microsoft und Lotus Corporation) wurde schließlich die SOAP 1.1 Spezifikation als W3C Note herausgegeben. Aktuell ist momentan die Version 1.2, die am 24.06.2003 von der Standardisierungsorganisation W3C veröffentlicht wurde [NASKSR]. SOAP ist folglich ein Nachrichtenprotokoll, das es ermöglicht, strukturierte und getypte Information zwischen Rechnern in einer dezentralisierten, verteilten Umgebung mit Hilfe von XML auszutauschen. Da eines der Ziele beinhaltete, dass SOAP möglichst flexibel sein soll, unterstützt der Standard mehrere unterschiedliche Übertragungsprotokolle: z.B. HTTP, FTP und SMTP. Um SOAP-Nachrichten zu erstellen oder den Inhalt zu extrahieren und zu verwenden, müssen Objekte bzw. vernetzte Objektstrukturen serialisiert und auf XML abgebildet werden und umgekehrt. Bereit gestellt wird dazu ein modulares Paketmodell, das auch Mechanismen zur Verschlüsselung der zu sendenden Daten anbietet. Häufig wird in der Literatur zwischen zwei Arten von Nachrichten unterschieden: einfache SOAP Messages und SOAP Messages mit Attachments. Im ersten Fall besteht die Nachricht nur aus dem SOAP Envelope, der im rechten Teil von Abbildung 2 abgebildet ist. Dessen SOAP Body enthält entweder die Daten eines RPC-Aufrufs oder ein Dokument in XML-Format. Im zweiten Fall werden an die Nachricht eine oder mehrere Dateien in beliebigen Format angehangen. Jede SOAP Message kann folglich aus bis zu vier Komponenten bestehen: 1. einem Umschlag (SOAP Envelope): Der Umschlag ist das Wurzelelement und dient als Behälter für die gesamte Nachricht. Er besitzt zwei 10 Simple Object Access Protokoll (SOAP) direkte Kindelemente: den Header (Kopf) und den Body (Datenbereich). 2. einem optionalen SOAP Header (Nachrichtenkopf): Der SOAP Header kann genutzt werden, um Informationen oder Anweisungen, abseits des eigentlichen Funktionsaufrufs, an den Empfänger oder eine dritte Person zu übermitteln. Soll eine Nachricht über mehrere Knoten (Stationen) im Netz laufen, so kann dies im Header eingetragen werden. Jede Zwischenstation kann entweder bestimmte Funktionen ausführen oder einfach nur die Nachricht weiterleiten. Bei den Zusatzfunktionen kann es sich zum Beispiel um eine Authentisierung oder um das Einleiten einer Transaktion handeln. 3. einem SOAP Body (Körper): Der Body einer Nachricht enthält die Daten, die für den Empfänger der Nachricht bestimmt sind. Der genaue Inhalt des Körpers hängt dabei von der Art der SOAP-Nachricht ab. Im Falle eines entfernten Funktionsaufrufs (Remote Procedure Call) wird zwischen drei verschiedenen Arten von Nachrichten unterschieden: Anfrage (Request), Antwort (Response) oder Fehlerbeschreibung (Fault). Bei einer Anfrage enthält der SOAP Body den Namen der aufzurufenden Funktion inklusive aller für die Ausführung des Aufrufs benötigten Daten bzw. Parameter. Bei erfolgreicher Ausführung der Funktion wird eine SOAP-Nachricht zurückgeschickt, die im Body das Ergebnis des Funktionsaufrufs an den Aufrufenden zurückliefert. Obwohl das Protokoll ursprünglich für den Funktionsaufruf gedacht war, ist es zusätzlich möglich, One-Way Messages zu schicken. Der Body enthält dann beliebige Daten im XML-Format, die der Empfänger der Nachricht über einen Parser einlesen und verwerten kann. Bei den Daten kann es sich auch um ganze Dateien (im XML-Format) handeln. Ein solcher Ausstauch von Daten wird als dokumentenbasiert“ be” zeichnet. Im Falle eines Fehlers - falscher Aufbau der SOAP-Nachricht oder Fehler bei der Bearbeitung - werden im Body der Nachricht detaillierte Fehlerinformationen zurückgeliefert. 4. einem optionalen AttachmentPart (Anhang): In dem Körper der SOAPNachricht können nur Daten im XML-Format transportiert werden. Sollen Daten in einem anderen Format oder ganze Dateien übertragen werden, kann der AttachmentPart der SOAP-Nachricht verwendet werden. Eine SOAP Message mit Attachments wird auch SOAP mes” sage package“ genannt und benutzt die Technik MIME (Multipurpose Internet Mail Extensions), einen Standard, der das Format von Internet Mails erweitert, indem mehrere Nachrichten-Körper-Teile (Body Parts), die jeweils ein unterschiedliches Format besitzen können, zugelassen werden. 11 Simple Object Access Protokoll (SOAP) In Abbildung 2 ist die Struktur einer SOAP-Nachricht dargestellt, wobei der rechte Teil eine einfache SOAP-Nachricht repräsentiert und die gesamte Grafik eine SOAP Message mit Attachments. SOAP Message MIME Header SOAP Envelope MIME Boundary Root Body Part SOAP Envelope (text/xml) SOAP Header Header Entry Header Entry MIME Boundary Body Part Attachment MIME Boundary Body Part ... MIME Boundary Body Part Body Entry ... Attachment SOAP Body Body Entry Attachment Abbildung 2: SOAP Message. Quelle:[ORMA02] und [NASKSR] An dieser Stelle wird anhand von zwei Beispielen gezeigt, wie die übertragenen Nachrichten aussehen. Zunächst folgt eine einfache SOAP Message ohne Attachment, die mittels des Übertragungsprotokolls HTTP übermittelt wurde. POST /StockQuote HTTP/1.1 Host: www.stockquoteserver.com Content-Type: text/xml; charset:"utf-8" Content-Length: nnn SOAPAction: "Some-URI" <SOAP-ENV: Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" SOAP-ENV:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Header /> <SOAP-ENV:Body> <m:GetLastTradePrice xmlns:m="some-URI"> <symbol>DEF</symbol> </m:GetLastTradePrice> </SOAP-ENV:Body> </SOAP-Envelope> Dieses Beispiel ist aus dem Java Web Services Developer Pack [ORMA02] entnommen, das in Kapitel 5 genauer beschrieben ist. Die Nachricht ruft auf dem Host www.stockquoteserver.com die Funktion GetLastTradePrice auf, um die letzte Börsennotation der Aktie DEF herauszufinden. Nachfolgend ist ein Beispiel für eine SOAP Message mit Attachment dargestellt: 12 Simple Object Access Protokoll (SOAP) MIME-Version: 1.0 Content-Type: Multipart/Related; boundary=MIME_boundary; type=text/xml; start="anyURI" Content-Type-Description: This is the optional message description. --MIME_boundary Content-Type: text/xml; charset=UTF-8 Content-Transfer-Encoding: 8 bit Content-ID: <"anyURI"> <?xml version="1.0"?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header> ... </SOAP-ENV:Header> <SOAP-ENV:Body> ... </SOAP-ENV:Body> </SOAP-ENV:Envelope> --MIME_boundary Content-Type: image/tiff Content-Transfer-Encoding:binary Content-ID: <"anyURi"> ...binary TIFFimage... --MIME_boundary-- Dem Beispiel kann entnommen werden, dass die Nachricht aus einem MIME Header und mehreren Body Parts mit jeweils eigenem Header und Body besteht, wobei die Body Parts durch ein sogenanntes MIME boundary voneinander getrennt werden. Über das Attribut Content-Type kann das Format für den jeweiligen body part“ definiert werden und mittels des Attributs ” Content-Transfer-Encoding das Kodierungsformat. Der Content-Type des Headers ist auf den Wert Multipart/Related gesetzt, der angibt, dass die Nachricht aus mehreren zusammenhängenden Body Parts besteht. Einer der Body Parts ist der sogenannte Root Body Part“ (im Default-Fall ist dies der erste Body Part), er enthält den SOAP Envelope. In der Regel verweist der Root Body Part durch Referenzen im Header oder Body des SOAP Envelopes auf die anderen Body Parts. An dieser Stelle sollen kurz die wesentlichen Eigenschaften von SOAP zusammengefasst werden: • transportiert in XML-Notation kodierte Funktionsaufrufe und Parameter von einer Quelle zum Ziel • ermöglicht Austausch von Information zwischen Applikationen Web Service Description Language (WSDL) 13 • basiert auf den bereits etablierten Standards HTTP und XML • robuster und flexibler als die get- und post-Funktionen von HTTP • SOAP ist plattformunabhängig • SOAP ist sprachenunabhängig • Einfachheit • Erweiterbarkeit • SOAP gilt als Standard des W3C • mit Hilfe von SOAP können RPC-Aufrufe über Firewallgrenzen hinweg einfach realisiert werden. 3.2 3.2.1 Web Service Description Language (WSDL) Einleitung Das Ziel bei der Erstellung eines Web Services ist die Anforderung, den Service so zu definieren, dass er nicht nur von Menschen, sondern auch von Applikationen benutzt werden kann. Aber wer sagt einer Maschine, was ein spezieller Service kann und wo er zu finden ist? Aus diesem Grund wurde von den Unternehmen Ariba, IBM und Mircosoft die Web Service Description Language (WSDL) entwickelt, deren erste Version im September 2000 veröffentlicht wurde. Die nächste Version WSDL 1.1 [CHR01] wurde im März 2001 bei der Standardisierungsorganisation W3C eingereicht, wo WSDL zur Zeit noch weiterentwickelt wird. Aktuell ist zum Zeitpunkt der Erstellung dieser Arbeit die Version WSDL 1.2 [CHI03], die als Working Draft“ am ” 11.06.2003 herausgegeben wurde und in diesem Kapitel beschrieben werden soll. Eine solche auch von Maschinen verständliche bzw. verarbeitbare Sprache hat mehrere Vorteile [BOO03]: • Sie ist formaler und daher genauer als eine natürliche Sprache (sie besitzt eine eindeutige Semantik). • Mit ihrer Hilfe können Softwaretools automatisch stub“- oder skele” ” ton“-Code (Code-Gerüste oder auch einzelne Klassen ) generieren, dies führt zu einer erleichterten Implementierung für Dienstanbieter und nachfrager. • Sie unterstützt die dynamische Entdeckung (Selektion) und Nutzung von Diensten. • Sie erleichtert Schiedsgerichtsverfahren, da die Sprache eindeutig ist (ihre Semantik ist eindeutig festgelegt), wodurch die Geschäftsbedingungen zwischen Dienstanbieter und -nutzer ebenfalls eindeutig geregelt sind. 14 Web Service Description Language (WSDL) Die Anforderung an die Sprache ist wie Kuschke und Wölfel in ihrem Buch schreiben sehr hoch: Ziel einer WSDL-Beschreibung ist die Schaffung ei” nes maschinen- oder besser von Applikationen lesbaren Zugangs zu angebotenen Diensten. Es soll also im Sinne einer Applikation-zu-ApplikationKopplung (A2A) eine weitgehend automatische Integration von verschiedenen angebotenen Diensten zu neuen Anwendungen möglich werden. Anders als bei hergebrachten Integrationen ist hierbei das Fernziel, dass Applikationen automatisch und auf der Basis solcher Beschreibungen zur Laufzeit eines Programms die gerade benötigten Dienstleistungen dynamisch einbinden. WSDL ist also bei Web Services das Mittel, dass eine automatische Anwendungsintegration ’Just in Time’ erlaubt.“[KUWÖ]. Im Folgenden wird nun die Sprache beschrieben, die diesen Anforderungen soll. 3.2.2 Beschreibung des Sprache WSDL Der Standard WSDL wird von der W3C wie folgt beschrieben: Definition 2 (WSDL) Die Web Services Description Language (WDSL) stellt ein Modell und ein XML-Format bereit, um Web Services zu beschreiben. WSDL ermöglicht die Separation der Beschreibung der abstrakten Funktionalität, die von einem Service angeboten wird, von den konkreten Details der Servicebeschreibung (beispielsweise das wie“ und wo“ die Funktiona” ” lität gewährt wird). [CHI03]. Einfacher gesagt, besteht ein WSDL-Dokument aus einer Reihe von Definitionen im XML-Format, die beschreiben, was ein Service tun kann, wo er sich befindet und wie er aufgerufen werden kann. Da ein WSDL-Dokument aus Definitionen im XML-Format besteht, erhielt das Wurzelelement treffenderweise den Namen <definitions>. Das Wurzeltag definitions“ dient als ” Container für die WSDL-Komponenten (<message>, <interface>, <binding> und <service>) und Typsystemkomponenten (Typdefinitionen, Elementdeklarationen). <definitions targetnamespace="xs:anyURI"> <documentation />? [ <import /> | <include />]* <types />? [ <message /> | <interface /> | <binding /> | <service /> ]* </definitions> Anmerkung: Die Notation der in diesem Kapitel dargestellten Beispiele entspricht der EBNF (Extended Backus-Naur Form), die von XML 1.0 [BRA00] benutzt und beschrieben ist. Das oben angegebene WSDL-Fragment ist der WSDL1.2-Beschreibung entnommen [CHI03] und liest sich wie folgt: Jedes <definitions>-Element besitzt ein Attribut targetnamespace, dessen URI auf ein maschinell oder Web Service Description Language (WSDL) 15 durch Menschen lesbares Dokument verweist, das entweder direkt oder indirekt die Semantik des WSDL-Infosets definiert (siehe Abbildung 3). Des Weiteren besitzt die Definitionskomponente mehrere Kindelemente, wobei die Elemente <documentation> und <types> optional eingefügt werden können. Die anderen beiden untergeordneten Elementgruppen können alle innerhalb ihrer Gruppe in einer WSDL-Datei gar nicht oder mehrfach in beliebiger Reihenfolge auftauchen. Im Folgenden werden die einzelnen Kindkomponenten, die im Rahmen dieser Arbeit wichtig sind, näher betrachtet. Sem/ BLA WSD Client Applikation Web Service Abbildung 3: Semantik und WSDL. Quelle: [BOO03] include, import Die WSDL Spezifikation stellt zwei Mechanismen zur Modularisierung von Servicebeschreibungen zur Verfügung; zum einen das <include>- und zum anderen das <import>-Element. Ersteres dient der Separation verschiedener Komponenten einer Servicedefinition in unabhängige WSDL-Dokumente, die beliebig zusammengesetzt werden können. Dabei müssen die Komponenten den gleichen Zielnamensraum (target namespace) besitzen wie das Dokument, in das sie inkludiert werden. Dieser Mechanismus erlaubt einen modularen Aufbau von WSDL-Dokumenten sowie das Anlegen von Bibliotheken für häufig verwendete Beschreibungsregeln. Das import-Element hingegen dient der Separation von Komponenten einer WSDL-Beschreibung in unabhängige Beschreibungen, wobei diese unterschiedliche Zielnamensräume (target namespaces) besitzen dürfen. [CHI03] Der Zielnamensraum entspricht der Webadresse, unter der die Beschreibung, das Schema oder was auch immer später zu finden ist. 16 Web Service Description Language (WSDL) <include location="xs:anyURI"> <documentation />? </include> <import namespace="xs:anyURI" location="xs:anyURI"?> <documentation />? </import> Die beiden oben genannten Mechanismen können genutzt werden, um andere WSDL-Dokumente oder XML-Schemata zu inkludieren. Auf diese Weise ist es ebenfalls möglich, die verschiedenen Elemente einer einzelnen ServiceDefinition in unabhängigen Dokumenten zu speichern. So können beispielsweise die abstrakten Elemente einer Service-Definition von den konkreten getrennt werden oder nach Grad der Abstraktheit definiert werden. Die Trennung in unabhängige Dokumente erhört die Übersichtlichkeit und Klarheit der Service-Definitionen und maximiert die Wiederverwendbarkeit der einzelnen Teile einer Service Definition (vgl. [CHR01]). Das <import>-Element wird in Kapitel 4 bei der Erstellung einer WSDL-Taxonomie von lokationsbasierten Diensten mehrfach benutzt; dort befinden sich dementsprechend mehrere Beispiele für die Nutzung dieses Mechanismus. types Wie hängt WSDL mit dem XML-Schema zusammen? WSDL unterstützt die Benutzung des XML-Schemas zur Definition eigener strukturierter (einfache und komplexe) Datentypen. Schließlich ist die Struktur der Sprache WSDL selbst in XML-Schema definiert worden. WSDL verwendet genauso wie das XML-Schema Namensräume, um Konflikte bei gleicher Namensgebung zu vermeiden. Die Typ- bzw. Elementdefinitionen können zwischen den beiden Tags <types> und </types> direkt in der WSDL-Datei definiert oder importiert werden. message Die Komponente <message> beschreibt in abstraktem Format die Nachrichten, die von einem Dienst empfangen oder gesendet werden. Sie besteht aus mehreren logischen <part>-Elementen (den Teilen einer Nachricht), deren Format mit Referenz auf eine Typ- oder Elementdeklaration festgelegt wird. Im Falle einer SOAP-RPC-Nachricht entsprechen <part>Elemente den Ein- und Ausgabeparametern der Operation. Zur Elementbzw. Typdeklaration wird von der Standardisierungsorganisation W3C, wie bereits erwähnt, das XML-Schema empfohlen. Des Weiteren ist anzumerken, dass die Nachrichten einen eindeutigen Namen NCName besitzen müssen, damit sie später bei der konkreten Bindung an ein Netzwerkprotokoll und bei der Gruppierung von Nachrichten innerhalb von Operationen referenziert werden können. <message name="xs:NCName"> <documentation />? <part name="xs:NCName element="xs:QName"? type="xs:QName"?/>* </message> Web Service Description Language (WSDL) 17 interface Analog einer traditionellen Programmierschnittstelle besteht das Element <interface> aus einer Gruppe von Operationen. Jede der Operationen wiederum besteht aus null oder mehreren Eingabe-, Ausgabe- und Fehlernachrichten, die über ihren eindeutigen <message>-Namen an dieser Stelle referenziert werden. Ferner kann ein <interface> über das Attribut extends ein anderes <interface> erweitern und somit dessen Operationen erben. <interface name="xs:NCName" extends="list of xs:QName"? > <documentation />? [<operation /> | <feature /> | <property />]* <\interface> wobei: <operation name="xs:NCName" pattern="xs:anyURI" > <documentation />? [<feature /> | <property /> | <input /> | <output /> | <infault /> | <outfault />]* </operation> Die Referenz auf ein vorher definiertes <message>-Element mittels seines eindeutigen Namens (QName) erfolgt in den Elementen <input> bzw. <output> über das Attribut message wie folgt: <input name="xs:NCName"? message="xs:QName" /> Im Fall eines <infault> oder <outfault>-Elements kann die Referenz auch aus einer Liste auf mehrere message-Namen bestehen. <infault name="xs:NCName" messages="list of xs:QName" /> Die weiteren Kindelemente <feature> und <property> werden an dieser Stelle nicht näher betrachtet. Es wird für weitere Informationen auf Chinnici, Gudgin, Moreau und Weerawarana [CHI03] verweisen. binding Mit der <binding>-Komponente werden die Schnittstelle und die darin enthaltenen Operationen an ein konkretes Nachrichtenformat und Übertragungsprotokoll gebunden. Hierbei sind beliebig viele Anbindungen für ein Interface möglich. <binding name="xs:NCName" interface="xs:QName" > <operation> <input name="xs:NCName"? /> <output name="xs:NCName"? /> 18 Web Service Description Language (WSDL) <infault name="xs:NCName" /> <outfault name="xs:NCName" /> </operation> </binding> Wie dem obigen XML-Fragment entmommen werden kann, ist in der Spezifikation WSDL 1.2 keine Bindung an ein spezielles Format vorgegeben oder angegeben. Für einen Überblick über die einzelnen von WSDL unterstützten Anbindungsformate existiert eine eigene Spezifikation namens: WSDL (Version 1.2) Bindings“ ([MOSC]), in der Anbindungen für SOAP ” 1.2, HTTP GET & POST und MIME definiert sind. In WSDL können für die Anbindung an Netzwerk- und Nachrichtenprotokolle sogenannte Erweiterungselemente (benutzerdefinierte Elemente) definiert werden, die auch als WSDL Binding Extensions“ bezeichnet werden. Sie sind sehr flexi” ble Konstrukte, da sie dem Schreiber einer WSDL-Datei ermöglichen, die Anbindung an das Protokoll zu ändern, ohne den Rest der Definitionen des WSDL-Dokumentes zu berühren. Im folgenden Kapitel wird die Anbindung an SOAP näher erklärt, da diese in der Implementierung später benutzt wird. Zunächst wird aber noch kurz auf das letzte Kindelement, das <service>-Tag, von <defintions> eingegangen. service Die <service>-Komponente beschreibt genau eine Schnittstelle (<interface>), die der Service bereitstellt und enthält als Kindelemente eine Sammlung der <endpoints>, an denen der betreffende Service angeboten wird. Dies sieht wie folgt aus: <service name="xs:NCName" interface="xs:QName" targetResource="xs:anyURI"? > <endpoint name="xs:NCName" binding="xs:QName" /> * </service> 3.2.3 SOAP Binding In der <binding>-Komponente wird bei Verwendung des SOAP-Protokolls ein zusätzliches Erweiterungselement <soap:binding> definiert, das angibt, dass dieses Protokoll verwendet wird: <binding> <soap:binding protocol ="uri" style="document|rpc"? namespaceDefault="uri"? encodingStyleDefault="uri"? > </soap:binding> </binding> Das Attribut protocol (es hieß in der WSDL 1.1 Version transport), gibt an, welches Protokoll verwendet wird, um die SOAP Envelopes zu übertragen. In den Beispielen, die in Kapitel 5 implementiert werden, wurde als Web Service Description Language (WSDL) 19 Übertragungsprotokoll HTTP verwendet; in der aktuellen Version SOAP 1.2 würde die URI wie folgt lauten: http://www.w3.org/2003/05/soap/bindings/ HTTP/. Andere mögliche Protokolle wären beispielsweise FTP(File Transfer Protokoll) oder SMTP (Simple Mail Transport Protokoll). Die weiteren Attribute sind optional, müssen also nicht angegeben werden. Interessant ist allerdings noch das Attribut style: Es kann einen der beiden Werte rpc“ (Remote Procedure Call) oder document“ annehmen, der ” ” dann für alle in dem <binding>-Element definierten Operationen gilt. Wird das Attribut nicht angegeben, so wird der Wert document“ als Default ” verwendet. Die Variante ’rpc’ definiert RPC-ähnliche Operationen, also ” ein Austausch von Nachrichten, die Parameter und Rückgabewerte beinhalten. ’document’ bezeichnet einen dokumentenbasierten Nachrichtenaustausch, also Nachrichten, welche Dokumente beinhalten“ [KUWÖ]. Mit dem encodingStyleDefault kann die Kodierungsvorschrift angegeben werden, die für die im binding definierten Operationen verwendet werden soll. Des Weiteren kann noch, wie der Name des letzten Attributes verrät, ein DefaultNamensraum für die Operationen spezifiziert werden. Wie bereits beschrieben, besitzt das <binding> ein <operation>-Element als Kindelement, in dem ebenfalls ein Erweiterungselement für die Anbindung an SOAP definiert werden kann. <operation> <soap:operation style="document|rpc"? soapAction="uri"? />? [<input> | <output>] <soap:body namespace="uri"? encodingStyle="uri"? />? [</input> | <output>] </operation> Das Attribut style wurde bereits erklärt, allerdings gilt der Wert des Attributes hier nicht für alle Funktionen, sondern nur für die eine Operation, innerhalb derer das Attribut festgelegt ist. Wird das Attribut nicht festgelegt, so gilt der Wert, der im <binding> definiert wurde, falls auch an dieser Stelle kein Wert definiert wurde, so gilt automatisch document“ als ” Defaultwert. Die URI, die im SOAP Action header eingetragen werden soll, kann mit dem Attribut soapAction bestimmt werden. Dieses Attribut muss bei der Übertragung von SOAP Envelopes über HTTP definiert werden, ansonsten ist es optional, daher hat es keinen Default-Wert. Über die Komponente <soap:body> kann spezifiziert werden, wie die Nachrichtenteile <parts> im SOAP Body Element erscheinen sollen. Folgende Eigenschaften können dabei festgelegt werden: der Namensraum (namespace), der für den SOAP Body Block benutzt werden soll und die Kodierungsvorschrift, mit der die <part>-Elemente kodiert sind. Das Attribut encodingStyle ist eine URI, mit der die konkrete Definition der Nachricht mittels der 20 Web Service Description Language (WSDL) abstrakten Typen der <part>-Elemente, die über das Attribut type definiert sind, ermittelt werden kann. Das letzte Erweiterungselement heißt <soap:address> und wird in das Tag <endpoint> wie folgt eingesetzt: <endpoint> <soap:address location="uri" /> </endpoint> Das Attribut location gibt die Adresse des Endpunktes (Ports) an, unter der der Dienst zu erreichen ist, wobei die Adresse zu dem im <soap:binding> spezifizierten Transportprotokoll passen muss. 3.2.4 Zusammenfassung Dienste werden von der Sprache WSDL als eine Ansammlung von Netzwerkendpunkten oder Ports verstanden. Die abstrakte Definition der Nachrichten, die zwischen den Diensten ausgetauscht werden, sind von ihrer konkreten Netzwerkbenutzung und ihren Datenformatbindungen getrennt und können unabhängig voneinander geändert werden. Diese Aspekte unterstützen die Wiederverwendung von WSDL-Fragmenten oder gar ganzen Dokumenten. Die Sprache WSDL besitzt dementsprechend folgende Vorteile: • unabhängig von verwendeter Plattform, da XML plattformunabhängig • unabhängig von bevorzugter Programmiersprache • automatische Anwengungsintegration Just-In-Time“ möglich ” • modulare Gestaltung von WSDL-Dokumenten möglich • sehr flexibel, wodurch nachträgliche Änderungen leicht vor genommen werden können • erweiterbare Sprache (es können z.B. andere Anbindungen als die bereits von WSDL unterstützen definiert werden, aber auch viele andere Elemente sind erweiterbar) Im Folgenden werden nicht alle Services betrachtet, sondern der Schwerpunkt auf lokationsbasierte Dienste gelegt. Die Dienste müssen dabei a priori nicht bekannt sein, sondern sollten über Ortsinformationen bei Bedarf ermittelt werden können und dem Clienten zugänglich gemacht werden. Um dies zu ermöglichen, werden die Dienste mittels der Sprache WSDL beschrieben, wodurch mögliche Kunden alle zur Benutzung des Dienstes benötigten Daten bei Bedarf ausmachen können. Mit Hilfe von auf dem Markt erhältlicher Software kann der Kunde sogar automatisch sub“- bzw. skeleton“” ” Code von der WSDL-Datei generieren. Im nächsten Kapitel wird WSDL Web Service Description Language (WSDL) 21 dahin gehend geprüft, ob die Spezifikation ausreichend ist, die nachstehende Funktionalität zu gewährleisten: 1. ausreichende Trennung von Dienst und Implementierung mittels WSDL 2. hohe Wiederverwendbarkeit durch Modularisierung 3. Einordnung der lokationsbasierten Dienste in eine WSDL-Taxonomie 22 Kategorisierung von lokationsbasierten Diensten 4 Kategorisierung von lokationsbasierten Diensten Ein Anbieter eines Dienstes, der einen neuen Service implementiert hat, muss diesen publizieren, damit ihn ein Client, der diesen lokationsabhängigen Dienst benutzen möchte, finden kann. Zur Publikation werden die Web Services in ein Dienstverzeichnis eingetragen, das über das Netz erreichbar ist und von möglichen Nutzern gelesen werden kann. Je größer ein Dienstverzeichnis ist, desto wichtiger ist eine Strukturierung der Einträge, so dass die Clients mit wenigen Klicks“ und geringer Wartezeit auf ihre Anfra” ge den entsprechenden Dienst finden. Zur Strukturierung eines Verzeichnises werden die Dienste in bestimmte Kategorien eingeordnet - eine solche Klassifizierung von Diensten in ein bestimmtes Kategoriensystem wird auch Taxonomie genannt. Eine Taxonomie kann für einen bestimmten Zweck erstellt werden oder als Standard oder Norm mehreren Zwecken dienen. Suchdienste wie Google oder Yahoo verwenden zum Beispiel erfolgreich ihre jeweils eigenen Taxonomien zur Einordnung von Websites, um die Antwortzeit auf eine Suchanfrage möglichst gering zu halten und gute Treffer liefern zu können. Ein Beispiel für eine standardisierte internationale Klassifikation ist die United Nations Standard Product and Services Classification (UNSPSC) Taxonomie, die das erste Industrie- und Dienstkategorisierungssystem ist, das für den Electronic Business“ bzw. den globalen Markt definiert wurde ” [GRA01]. Trotz seines großen Umfanges besteht dieses Kategorisierungssystem nur aus vier Hierarchieebenen und entspricht damit der Anforderung, dass ein Nutzer schnell zu dem gewünschten Eintrag navigieren kann. Im Zusammenhang mit den bei Web Services benutzten Standards WSDL und SOAP wird auch der Standard UDDI empfohlen. Die Technologie Universal Description, Discovery, and Integration (UDDI) definiert Schnittstellen und Mechanismen für Verzeichnisse zur Publikation und Speicherung von Diensten auf Basis von Nachrichten im XML-Format. UDDI definiert dabei sowohl die Struktur für ein universelles Verzeichnis, in dem die Dienste abgelegt werden können, als auch Funktionen, mit deren Hilfe die Verzeichnisdaten durchsucht und modifiziert werden können [NASKSR]. Zur Kategorisierung werden bei dieser Technik die Taxonomien NAICS (North American Industry Classification System), das eben erwähnte UNSPSC, die ISONorm 3166 und das Kategorisierungssystem Operator Specific unterstüzt [NASKSR]. Der NAICS-Index ist ein aus sechs Ziffern bestehender Klassifizierungscode, der nach Industrien und Industriezweigen klassifiziert. Er wurde zur statistischen Erfassung und Vergleichbarkeit von wirtschaftlichen Daten zwischen Mexiko, Kanada und den USA entwickelt (www.naics.com). Die ISO-Norm 3166 ist ein Klassifizierungssystem, das auf geographischen Unterteilungen beruht. Das letzte Kategorisierungssystem ist ein offenes System, das nicht vordefiniert ist und in das dementsprechend alle Kategorien Identifizierung und Klassifizierung von lokationsabhängigen Diensten 23 eingetragen werden können, die jemand in der Taxonomie definieren möchte [NASKSR]. Diese Taxonomien können zur Kategorisierung von lokationsbasierten Diensten allerdings nicht benutzt werden, da die eben genannten Einteilungen für andere Zwecke generiert wurden. Eine geeignete Kategorisierung für lokationsbasierte Dienste existierte bis UDDI 2.1 noch nicht, ab der Version 3.1 gibt es das Element keyedReferenceGroup, das als Ansatz dienen kann, um Ortsinformationen in einem UDDI Verzeichnis zu berücksichtigen [BEL02]. Im Rahmen dieser Arbeit soll eine eigene Taxonomie definiert werden, die im folgenden Kapitel nachgeschlagen werden kann. 4.1 Identifizierung und Klassifizierung von lokationsabhängigen Diensten In diesem Unterkapitel werden zunächst die ermittelten lokationsbasierten Dienste in einer selbst definierten Taxonomie angeordnet. Im folgenden Kapitel können dann die WSDL-Beschreibungen der Dienste bzw. Dienstkategorien nachgelesen werden. Diese Taxonomie erhebt keinen Anspruch auf Vollständigkeit, da sie - speziell im unteren Bereich der Klassifizierung - die Dienste einer vorhandenen technischen Infrastruktur berücksichtigt; außerdem ist davon auszugehen, dass die zukünftige Entwicklung lokationsbasierte Dienste bzw. Dienstkategorien hervorbringen wird, die es heute noch gar nicht gibt - weswegen die aufgestellte Kategorisierung erweiterbar bleiben soll. Zu beachten ist allerdings, dass die geschaffenen Klassen, wenn möglich, disjunkt sein sollten. In Anbetracht dessen wurde auf oberster Ebene versucht, eine Klassifizierung zu erstellen, in die voraussichtlich auch die meisten zukünftigen Dienste eingeordnet werden können. Zur Einordnung wurden folgende fünf Klassen ausgewählt: 1. Output Services 2. Input Services 3. Storage and Computation Services 4. Device Control 5. Communication Services Die Klassen eins und zwei trennen die Ausgabe- und die Eingabedienste, wobei in erstere Kategorie alle Dienste einzuordnen sind, die dazu dienen, Daten des Servicenutzers mittels eines Geräts auszugeben, das nicht in Besitz des Nutzers ist, ansonsten könnte der Dienst nicht als lokationsbasiert bezeichnet werden. Die Eingabedienste stellen das Gegenteil dar, denn hier wird ein fremdes Gerät zur Eingabe bzw. Erstellung von Daten benutzt. Da 24 Identifizierung und Klassifizierung von lokationsabhängigen Diensten jene Dienstkategorien gegensätzlich sind, sind diese beiden Klassen disjunkt. Des Weiteren gibt es natürlich auch Services, die sowohl Eingabe- als auch Ausgabecharakter besitzen, deswegen wurde als weitere Unterscheidung die Kategorie Communication Services“ eingeführt. Selbstverständlich existie” ren auch Dienste, bei denen weder die Ausgabe noch die Eingabe im Vordergrund steht, weswegen zusätzlich die Klassen Device Control“ und Storage ” ” und Computation Services“ hinzugefügt wurden. Im Folgenden wird jede der fünf Oberklassen einzeln genauer beschrieben, begonnen wird mit der Klasse Output Services“. Die Taxonomie wird im ” Text der Übersichtlichkeit halber immer nur in Teilstücken beschrieben; interessierte Leser, die die ganze Taxonomie sehen möchten, seien hiermit auf den Anhang verwiesen, in dem die Taxonomie als Ganzes dargestellt ist. 4.1.1 Output Services Auf der Ebene der Ausgabedienste wird zunächst in die drei Hauptkategorien Druckdienste ( Print Services“), Anzeigedienste ( Display“) und Ab” ” spieldienste ( Play“) getrennt. In allen Fällen werden Daten ausgegeben, ” im ersten Fall auf den Drucker, im zweiten auf einem Bildschirm bzw. Display und im dritten Fall über den Lautsprecher oder über Lautsprecher und Bildschirm, wodurch sich die Trennung in diese drei Gruppen ergibt. Auf der untergeordneten Ebene der Print Services“ wurde zunächst in Farb” bzw. Schwarz-Weißdruck unterschieden, da eine Person in der Regel zunächst auswählt, ob sie die Datei in Farbe ausdrucken möchte oder nicht. Dies ist auch insofern von Bedeutung, als nicht jeder Drucker in der Lage ist, Bilder bzw. Text in Farbe zu drucken. Ferner wurde weiter unterschieden, ob die entsprechende zu druckende Datei in einem ASCII-Format oder in einem Binärformat gespeichert ist. Diese Trennung ist den unterschiedlichen Datentypen, die für die beiden Formate im XML-Schema verwendet werden, zu begründen. Zusammengefasst wurden die Druckdienste in folgende Kategorien getrennt: Print Ascii Files“, Print Binary Files“, Print As” ” ” cii Color“ und Print Binary Color“. Die Kategorie Display Document“ ” ” wurde dementsprechend ebenfalls in die Unterkategorien Display Ascii Do” cument“ und Display Binary Document“ getrennt. Auf der untersten Ebene ” der Taxonomie kann der Client schließlich den für ihn passenden Drucker entsprechend des Formats der zu druckenden Datei aussuchen. In den untersten Klassen der Kategorie wird dazu in die speziellen Formate der Daten unterschieden, so gibt es beispielsweise Drucker, die nur Dateien vom Typ PS drucken können. Die letzte Differenzierung ist vor allem deswegen wichtig, da ein Dienstnutzer auf diese Weise schnell einen Dienst finden kann, der in der Lage ist, seine Datei auszudrucken. In der Kategorie Play“ wird zunächst in Play Audio“ und Play Video“ ” ” ” unterschieden, weil im ersten Fall nur der Lautsprecher involviert ist und im zweiten Fall zusätzlich noch der Bildschirm als Ausgabegerät genutzt wird. Identifizierung und Klassifizierung von lokationsabhängigen Diensten 25 Da für die unterschiedlichen Audio- und Videoformate unterschiedliche Abspielsoftware existiert, werden auf der untersten Ebene ähnlich wie bei den Druckdiensten die Play Services“ nach den Formaten getrennt, die sie ab” spielen können. Die Kategorie Nummer 3 ( Display“) wurde in die Unterklassen Display ” ” Document“ und Display Image“ getrennt, da ein Bild und ein Dokument ” unterschiedliche Anzeigeaspekte erfordern und für beide Zwecke verschiedene Anwendungssoftware existiert. Ebenso wie bei den beiden vorhergehenden Hauptkategorien wurde dann weiter nach den Formaten differenziert. Output Services: 1. Print Services 1.1 Black-White Print Services 1.1.1 Print Ascii Files 1.1.1.1 Print PS 1.1.1.2 Print HPGL 1.1.2 Print Binary Files 1.1.2.1 Print GIF 1.1.2.2 Print JPEG 1.1.2.3 Print PCL 1.1.2.4 Print PDF 1.1.2.5 ... 1.1.2.6 Print PNG 1.2 Color Print Services 1.2.1 Print Ascii Color 1.2.1.1 Print PS 1.2.1.2 Print HPGL 1.2.2 Print Binary Color 1.2.2.1 Print GIF 1.2.2.2 Print PCL 1.2.2.3 Print PDF 1.2.2.4 ... 1.2.2.5 Print PNG 2. Play 2.1 Play Audio 2.1.1 Play MP3 2.1.2 Play WAV 26 Identifizierung und Klassifizierung von lokationsabhängigen Diensten 2.1.3 ... 2.2 Play Video 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 Play Play Play ... Play MPEG1 MPEG2 MPEG4 Quicktime 3. Display 3.1 Display Document 3.1.1 Display ASCII Document 3.1.1.1 Display PS 3.1.1.2 Display HPGL 3.1.1.3 Display TXT 3.1.1.4 ... 3.1.2 Display Binary Document 3.1.2.1 Display DOC 3.1.2.2 Display PCL 3.1.2.3 Display PPT 3.1.2.4 ... 3.2 Display Image 3.2.1 3.2.2 3.2.3 3.2.4 4.1.2 Display GIF Display JPEG Display BMP ... Input Services In der Klasse der Eingabedienste ( Input Services“) sind nur Dienste ein” zuordnen, die der reinen oder zumindest hauptsächlich der Dateneingabe dienen. Möglichkeiten, Daten einzugeben, ergeben sich beispielsweise durch Sensoren, Videogeräte, Scanner oder Mikrophone. Sicher gibt es auch die Möglichkeit, über ein Diskettenlaufwerk, ein CD-ROM/DVD-Laufwerk, USB-Stick, Tastatur oder Maus Daten einzugeben. Dies wäre unter anderem dann der Fall, wenn man einen Laptop ohne DVD-Laufwerk besitzt, man aber ein solches benötigt und vor Ort eines existiert. Ebenso könnte ein Dienst ein Keyboard für PDA-Benutzer anbieten oder eine Maus für Laptop-Besitzer. Es wurde in folgende Dienstkategorien aufgeteilt: Identifizierung und Klassifizierung von lokationsabhängigen Diensten 27 Input Services: 1. Scan 2. Record 2.1 Audio Input 2.2 Video Input 3. Sensor Input 3.1 3.2 3.3 3.4 3.5 3.6 4.1.3 Measure Temperature Measure Ozon ... DVD Input Keyboard Input Mouse Input Storage and Computation Services Der Dienst des Speicherns wurde, obwohl er auch der Kategorie Output Ser” vices“ zugerechnet werden könnte, in eine eigene Klasse eingeordnet, da er von dem normalen Benutzer nicht als Ausgabedienst wahrgenommen wird. Ferner ist das Ziel eines Speichervorgang nicht nur die Ausgabe der Daten, sondern vielmehr die kurzfristige oder langfristige bzw. permanente Speicherung von Daten. Neben den Speicherdiensten sollen auch alle weiteren Dienste in dieser Kategorie eingeordnet werden, bei denen weder die Eingabe noch die Ausgabe im Vordergrund stehen. Storage and Computational Services 1. Save on external data mediums 1.1 Burn CD 1.2 Burn DVD 2. Computational Services 4.1.4 Device Control (Steuerungsdienste) In dieser Gruppe sind alle Funktionen einzuordnen, die dazu dienen, Geräte anzusteuern. Dies können Funktionen sein, wie beispielsweise das Ein- und Ausschalten eines Geräts oder das Setzen von Parametern, die für die Steuerung der Geräte wichtig sind. So könnten beispielsweise auch Geräte mit komplexen Funktionen angesteuert werden (beispielsweise die Ansteuerung von Robotern), ohne vorher eine spezielle Programmiersprache dafür zu erlernen. 28 Konzeption einer WSDL-Taxonomie der Dienste Device Control 1. Get-functions 2. Set-functions 4.1.5 Communication Services Unter der Hauptkategorie Communication Services“ sind alle Dienste ein” zuordnen, bei denen sowohl Eingabe als auch Ausgabe eine zentrale Rolle spielen. Communication Services 1. Chat 2. Message Services (Nachrichtendienste) 2.1 Fax 2.2 Mail 2.3 SMS 3. Conferences 3.1 Telephone Conference (over IP) 3.1.1 Dial In 3.1.2 Dial Out 3.2 Video Conference 3.2.1 Dial In 3.2.2 Dial Out 4.2 Konzeption einer WSDL-Taxonomie der Dienste Bei der Entwicklung der WSDL-Taxonomie werden nicht nur ganze Dienste betrachtet, sondern auch einzelne Funktionen der Dienste, die aufgrund von Aspekten der Vererbung in der Taxonomie höher angeordnet werden, falls sie für alle Kinderkategorien gleich sind. Auf diese Weise ergibt sich eine bestimmte Struktur von Dateien auf den einzelnen Ebenen, wobei die tieferen Ebenen die Dateien der jeweils höher liegenden Ebene inkludieren. Auf oberster Ebene der Klassifizierung (den fünf Hauptgruppen) werden keine XML-Beschreibungen implementiert, da hier die Gruppen noch zu allgemein sind, um Funktionen anzubieten, die für alle Untergruppen gelten. Konzeption einer WSDL-Taxonomie der Dienste 4.2.1 29 Ausgabedienste print Auf der Ebene der Druckdienste werden die Funktionen statusOfJob(), viewPrintJobs() und removeFromPrinterQueue() angeboten, da sie als Standardfunktionen von fast allen Druckern realisiert werden. Die wichtigste Funktion, die print-Funktion, wurde hingegen, aufgrund der vielen unterschiedlichen Formate der zu druckenden Dateien, auf eine tiefere Ebene verlagert. Im Folgenden ist das WSDL-Fragment der Datei print.wsdl“ ” dargestellt, das die eben beschriebene Funktionalität realisiert: <?xml version="1.0"?> <definitions targetnamespace="http://com.test/print" xmlns="http://www.w3.org/2003/06/wsdl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsd1="http://www.icsy.de/xml/lawns/schemas/" xmlns:tns="http://com.test/print"> <import location="print.xsd" namespace="http://www.icsy.de/xml/lawns/schemas/"> <message name="printCharacteristics"> <part name="printID" type="xs:integer"/> <part name="printerName" type="xs:integer"/> </message> <message name="statusOfPrintingJob"> <part name="status" type="xsd1:statusType"/> </message> <message name="viewPrintJobs"> <part name="printerName" type="xs:string"/> </message> <message name="queue"> <part name="printerName" type="xs:string"/> <part name="printerQueue" type="xsd1:printerQueue"/> </message> <message name="removeFromPrinterQueue"> <part name="printerName" type="xs:string"/> <part name="printID" type="xs:integer"/> </message> <message name="acknowledgementOfRemoval"> <part name="acknowledgement" type="xs:string"/> </message> <interface name="printing"> <operation name="statusOfJob"> <input message="tns:printCharacteristics"/> <output message="tns:statusOfPrintingJob"/> </operation> <operation name="viewPrintJobs"> <input message="tns:viewPrintJobs"/> <output message="tns:queue"/> </operation> <operation name="remove"> <input message="tns:removeFromPrinterQueue"/> 30 Konzeption einer WSDL-Taxonomie der Dienste <output message="tns:acknowledgementOfRemoval"/> </operation> </interface> </definitions> Die WSDL-Datei definiert drei Operationen, die von dem Tag <interface> zusammengefasst werden. Die erste Operation statusOfJob() erhält als Eingabe den Namen des Druckers und die printID des Druckerjobs, nach dessen Status sich der Client erkundigen möchte und liefert einen String als Ausgabe, der den aktuellen Status des Jobs enthält. Des Weiteren gibt es die Funktion viewPrintJobs(), die zur Ausgabe der ganzen Druckerschlange aufgerufen werden kann. Als Eingabeparameter benötigt diese Funktion lediglich den Namen des Druckers. Soll in Mehrbenutzersystemen die Möglichkeit gegeben werden, dass ein Client nur seine eigenen Jobs sehen kann, so müsste die Funktion um den Eingabeparameter Benutzername erweitert werden. Im Rahmen der vorliegenden Arbeit wurde die allgemeinere Methode gewählt, da sie von jedem System ausgeführt werden kann. Ist dies nicht gewünscht, so könnte eine Login-Funktion vorgeschaltet werden, damit wäre auch über die allgemeine Funktion ein Ausgeben nur der eigenen Jobs möglich - gleiches gilt für die Löschfunktion. Die letzte der drei Funktionen dient dem Löschen eines Druckauftrages mit dem Eingabeparameter printID und liefert als Ausgabe die Löschbestätigung, wobei der genaue Text der Ausgabe hier offen gelassen wird. Die Datei print.wsdl“ importiert eine XML-Schema-Datei namens print.xsd, ” ” in der die Datentypen printerQueueEntry, printerQueue und statusType wie folgt definiert werden: <xsd:simpleType name="statusType"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="queued"/> <xsd:enumeration value="printing"/> <xsd:enumeration value="printed"/> </xsd:restriction> </xsd:simpleType> <xsd:complexType name="printerQueueEntry"> <xsd:sequence> <xsd:element name="printID" type="xsd:integer"/> <xsd:element name="status" type="tns:statusType"/> <xsd:element name="fileName" type="xsd:string"/> <xsd:element name="percentagePrinted" type="xsd:integer"/> <xsd:element name="positionInPrinterQueue" type="xsd:integer"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="printerQueue"> <xsd:element name="printjob" type="tns:printerQueueEntry" minOccurs="0" maxOccurs="1000"/> Konzeption einer WSDL-Taxonomie der Dienste 31 </xsd:complexType> Der selbst definierte Datentyp statusType ist vom Typ string und kann die drei Werte queued, printing und printed annehmen. printerQueueEntry hingegen ist ein komplexer Datentyp, der aus den Elementen printID, percentagePrinted und positionInPrinterQueue vom Typ integer, dem Element fileName vom Typ string und dem Element status vom eben beschriebenen statusType besteht und der Anzeige der Charakteristiken eines Durckerjobs dient. Der letzte in der Datei definierte Typ printerQueue besteht schließlich aus Null oder mehreren Elementen vom Typ printerQueueEntry, die maximale Anzahl liegt bei 1000. Diese Grenze wurde aber beliebig gewählt und könnte auch eine andere Zahl darstellen. Der von XML-Schema her auch mögliche Wert unbounded kann hingegen nicht gewählt werden, da bei der Implementierung in Java auf die Datenstruktur Array zurückgegriffen werden soll und eine statische Grenze dabei die Realisierung vereinfacht. Print Ascii Files, Print Binary Files Eine Ebene unter der Kategorie Print Services“ wird zunächst in Print Ascii Files“ und Print Binary ” ” ” Files“ unterschieden, was sich durch den Unterschied bei der Datenübertragung ergibt. Ascii-Daten enthalten keine Kontrollzeichen, sondern sind reiner Text, wie beispielsweise die Formate PS oder HPGL. Eine solche Datei kann direkt im Body einer SOAP Message enthalten sein oder als Attachment angehängt werden. Da SOAP Messages nur Daten im XML-Format enthalten dürfen, kann eine binäre Datei hingegen nur als Attachment angehängt werden. Auf dieser Ebene wird die print()-Funktion angeboten, wobei deren Realisierung in den beiden Gruppen sich nur dadurch unterscheidet, dass in dem einen Fall eine Datei in dem base64Binary-Format als Attachment an eine SOAP Message angehangen wird und im anderen Fall eine Ascii-Datei als String (entweder im Body oder als Attachment) zum Drucker gesendet wird. Im Folgenden sind die WSDL-Dateien der beiden Dienste dargestellt. printascii.wsdl“: ” <?xml version="1.0"?> <definitions targetnamespace="http://com.test/printascii" xmlns="http://www.w3.org/2003/06/wsdl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsdl1="http://www.icsy.de/xml/lawns/print.wsdl" xmlns:tns="http://com.test/printascii"> <import location="print.wsdl" namespace="http://www.icsy.de/xml/lawns/print.wsdl"> <message name="printascii"> <part name="file" type="xs:string"/> 32 Konzeption einer WSDL-Taxonomie der Dienste <part name="numberOfCopies" type="xs:integer"/> </message> <interface name="printing"> <operation name="printascii" parameterorder="?"> <input message="tns:printps"/> <output message="wsdl1:printID"/> </operation> </interface> </definitions> printbinary.wsdl“: ” <?xml version="1.0"?> <definitions targetnamespace="http://com.test/printBinary" xmlns="http://www.w3.org/2003/06/wsdl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsdl1="http://www.icsy.de/xml/lawns/print.wsdl" xmlns:tns="http://com.test/printBinary"> <import location="print.wsdl" namespace="http://www.icsy.de/xml/lawns/print.wsdl"> <message name="printBinary"> <part name="file" type="xs:base64Binary"/> <part name="numberOfCopies" type="xs:integer"/> </message> <interface name="printing"> <operation name="printBinaryFile"> <input message="tns:printBinary"/> <output message="wsdl1:printID"/> </operation> </interface> </definitions> Die beiden Dateien enthalten jeweils eine Druckfunktion, die als Eingabe die zu druckende Datei und einen Parameter für die Anzahl der Kopien erhält und als Rückgabe eine ID für den Druckauftrag liefert. Eine Nachricht (<message>), die die printID beinhaltet, wurde bereits in der Datei print.wsdl definiert, weshalb diese in der Output Message referenziert wird. Durch den Import der Datei print.wsdl stehen natürlich auch alle Funktionen, die in dieser Datei definiert wurden, zur Verfügung. Print Color Im vorgehenden Kapitel wurde bereits beschrieben, dass eine Person in der Regel vor dem Druck entscheidet, ob in Schwarz-Weiß oder in Farbe gedruckt werden soll. Deswegen wurden die Kategorien Print Ascii ” Color“ und Print Binary Color“ eingeführt - in diesen Kategorien sind alle ” Farbdrucker einzuordnen. Die print()-Funktion wurde für diesen Fall nur um den weiteren Eingabeparameter Color“ vom Typ Boolean erweitert. Ist ” der Parameter auf Eins gesetzt, so wird die Datei in Farbe ausgedruckt, ist er Konzeption einer WSDL-Taxonomie der Dienste 33 auf Null gesetzt, so erfolgt der Ausdruck in Schwarz-Weiß bzw. Grautönen. Hier wird exemplarisch nur die Datei printAsciiColor.wsdl gezeigt, da die Datei printBinaryColor.wsdl sich nur bezüglich des Formats der Druckdaten von der anderen unterscheidet, was im Paragraph zuvor schon beschrieben und gezeigt wurde. <?xml version="1.0"?> <definitions targetnamespace="http://com.test/printAsciiColor" xmlns="http://www.w3.org/2003/06/wsdl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsdl1="http://www.icsy.de/xml/lawns/print.wsdl" xmlns:tns="http://com.test/printAsciiColor"> <import location="print.wsdl" namespace="http://www.icsy.de/xml/lawns/print.wsdl"> <message name="printAsciiColor"> <part name="file" type="xs:string"/> <part name="numberOfCopies" type="xs:integer"/> <part name="color" type="xs:boolean"/> </message> <interface name="printing"> <operation name="printps" parameterorder="?"> <input message="tns:printAsciiColor"/> <output message="wsdl1:printID"/> </operation> </interface> </definitions> Einzelne Druckformate Auf der untersten Ebene der Kategorie Print ” Services“ sind die Drucker nach den Formaten getrennt, die sie in der Lage sind auszudrucken. Im Rahmen dieser Arbeit wurden keine weiteren formatoder druckerspezifischen Funktionen mehr hinzugefügt; diese Klassen importieren nur die Funktionalität der über ihnen liegenden Kategorien. Da die WSDL-Dateien sehr ähnlich sind, werden hier nur zwei Dienste (drucken einer PS-Datei in Schwarz-Weiß und drucken einer PDF-Datei in Farbe) exemplarisch beschrieben - in den Klammern ist jeweils angegeben, wie ein Client über die einzelnen Kategorien zu dem gewünschten Service gelangt. 1. printPS.wsdl“ ( Print Services“ → Print Ascii“ → Print PS“) ” ” ” ” <definitions targetnamespace="http://com.test/printPS" xmlns="http://www.w3.org/2003/06/wsdl" xmlns:tns="http://com.test/printPS"> <import printAscii.wsdl/> </definitions> 2. printColorPDF.wsdl“ ( Print Services“ → Print Binary Color“ → Print ” ” ” ” PDF“) 34 Konzeption einer WSDL-Taxonomie der Dienste <definitions targetnamespace="http://com.test/printColorPDF" xmlns="http://www.w3.org/2003/06/wsdl" xmlns:tns="http://com.test/PrintColorPDF"> <import printBinaryColor.wsdl/> </definitions> Zur besseren Veranschaulichung ist an dieser Stelle die Vererbungs- bzw. Importhierarchie in einer Grafik dargestellt, um zusammenfassend einen Überblick über die Beziehungen zwischen den WSDL-Dateien zu erhalten. Der Pfeil hat dabei folgende Bedeutung: a.[wsdl—xsd] → b.[wsdl—xsd] heißt, dass die Datei b.wsdl (b.xsd) die Datei a.wsdl (a.xsd) importiert. Print. wsdl Print. xsd PrintAscii. wsdl Print PS. wsdl PrintBinary. wsdl PrintHPGL .wsdl PrintDOC. wsdl PrintPDF. wsdl Abbildung 4: Import-Hierarchie Play Die Kategorie Play“ besitzt die beiden Unterkategorien Play Au” ” dio“ und Play Video“, welche die Funktionen startPlaying(), stopPlaying() ” und pause() und windToMinute gemeinsam umfassen. Sie sind in der Datei play.wsdl“ wie folgt definiert: ” <?xml version="1.0"?> <definitions targetnamespace="http://com.test/play" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://com.test/play"> <message name="start"> <part name="file" type="base64Binary"/> </message> <message name="stop"> <part name="ID" type="xs:integer"/> </message> Konzeption einer WSDL-Taxonomie der Dienste 35 <message name="pause"> <part name="ID" type="xs:integer"/> </message> <message name="wind"> <part name="ID" type="xs:integer"/> <part name="minute" type="xs:integer"/> </message> <message name="returnMessage"> <part name="sentence" type="xs:string"/> </message> <message name="handle"> <part name="ID" type="xs:integer"/> </message> <interface> <operation name="startPlaying"> <input message="tns:play"/> <output message="tns:handle"/> </operation> <operation name="stopPlaying"> <input message="tns:stop"/> <output message="tns:returnMessage"/> </operation> <operation name="pause"> <input message="tns:pause"/> <output message="tns:returnMessage"/> </operation> <operation name="windToMinute"> <input message="tns:wind"/> </output message="tns:returnMessage"/> </operation> </interface> </definitions> Durch Ausführen der Funktion startPlaying() wird eine SOAP Message mit der abzuspielenden Datei als Anhang zum Service gesendet, als Ausgabe erhält der Client eine ID, die seinen Abspielauftrag eindeutig identifiziert. Die Funktionen stopPlaying() und pause() erhalten beide als Eingabeparameter die von der Funktion startPlaying rückgelieferte ID, damit der Service den entsprechenden Auftrag identifizieren kann. Die Ausgabe ist im Fall der erfolgreichen Ausführung des Befehls ein Wert, der dies bestätigt (dies könnte der Wert 1 oder die beispielsweise erneut die ID sein); im Falle eines Fehlers enthält die returnMessage eine Fehlermeldung, die angibt, warum der Befehl nicht ausgeführt werden konnte (z.B. falsches Format der Datei oder falsche Minutenangabe). Zusätzlich wird die Funktion windToMinute() definiert, wobei der Eingabeparameter die Stelle in Minuten angibt, zu der das Video vor- oder zurückgespult werden soll. In der Unterkategorie Play Audio“ steht zusätzlich zu den eben beschriebe” nen Funktionen, die natürlich inkludiert werden, noch putFileInPlayQueue() und removeFileFromPlayQueue() zur Verfügung. Damit besteht die Möglich- 36 Konzeption einer WSDL-Taxonomie der Dienste keit, dass der Nutzer des Audioabspielers sich mehrere Dateien hintereinander anhören kann. Dies könnte z.B. dann der Fall sein, wenn die Person eine Party in dem entsprechenden Raum gibt und nicht ständig damit beschäftigt sein möchte, neue Lieder an den Service zu senden; die Auswahl kann vorher getroffen werden. Die betreffende WSDL-Datei sieht wie folgt aus: <?xml version="1.0"?> <definitions targetnamespace="http://com.test/playAudio" xmlns="http://www.w3.org/2003/06/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsd1="http://www.icsy.de/xml/lawns/schemas/" xmlns:tns="http://com.test/playAudio"> <import location="playAudio.xsd" namespace="http://www.icsy.de/xml/lawns/schemas/"/> <import location="play.wsdl" namespace="http://www.icsy.de/xml/lawns/play.wsdl"/> <message name="putFileInQueue"> <part name="file" type="xs:base64Binary"/> </message> <message name="removeFileFromQueue"> <part name="fileName" type="xs:string"> </message> <message name="acknowledgement"> <part name="file" type="xs:string"/> <part name="acknow" type="xsd1:ackType"/> </message> <interface> <operation name="putFileInPlayQueue"> <input message="tns:putFileInQueue"/> <output message="tns:acknowledgement"/> </operation> <operation name="removeFileFromPlayQueue"> <input message="tns:removeFileFromQueue"/> <output message="tns:acknowledgement"/> </operation> </interface> </definitions> Die Operation putFileInPlayQueue() dient dem Senden einer Datei zur Eingliederung in die Abspielwarteschlange; sie bestätigt in einer Rückmeldung, dass die entsprechende Datei in die Warteschlange eingefügt wurde. Möchte ein Client die Datei wieder aus der Schlange entfernen, so ruft er die Funktion removeFileFromPlayQueue() mit dem Namen der Datei auf, die gelöscht werden soll. Er erhält darauf eine Bestätigung, die angibt, welche Datei gelöscht wurde. Der selbstdefinierte Datentyp ackType ist hierbei ein String, der entweder die Zeichenkette file listet in queue“ oder file removed ” ” from queue“ beinhaltet. Konzeption einer WSDL-Taxonomie der Dienste 37 Display Auf oberster Ebene wird hier die allen Unterkategorien gemeinsame Funktion close(ID) angeboten, mittels derer eine geöffnete Datei wieder geschlossen werden kann. Die eindeutige ID zur Identifizierung des Anzeigeauftrages wird von der entsprechenden display-Funktion, die eine Ebene tiefer in der Hierarchieebene angeboten wird, zurückgeliefert. Ferner wird die Funktion getResolution() angeboten, mit der die minimale und die maximale Auflösung erfragt werden können, die der Dienst anbieten kann. Die entsprechende WSDL-Datei sieht wie folgt aus: <?xml version="1.0"?> <definitions targetnamespace="http://com.test/display" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://com.test/display"> <message name="close"> <part name="ID" type="xs:integer"> </message> <message name="resolution"/> <message name="responseResolution"> <part name="minResolution" type="xs:string"/> <part name="maxResolution" type="xs:string"/> </message> <interface> <operation name="closeDocument"> <input message="tns:close"/> </operation> <operation name="getResolution"> <input message="tns:resolution"/> <output message="tns:responseResolution"/> </operation> </interface> </definitions> Die Unterkategorie Display Document“ ist, in die Klassen Display As” ” cii Document“ und Display Binary Document“ unterteilt, in denen dann, ” entsprechend dem Format der Datei, die angezeigt werden soll, der entsprechende Dienst gesucht werden kann. Besitzt der Dienstnutzer beispielsweise eine DOC-Datei, so würde sein Weg über die einzelnen Kategorien bis zur Druckerauswahl wie folgt, lauten: Output Services → Display → Display Document → Display Binary Document → Display Doc. Sowohl die Datei dis” playAsciiDocument.wsdl“ als auch die Datei displayBinaryDocument.wsdl“ ” bieten zwei Funktionen an, zum einen eine Operation zum Anzeigen der Datei (displayBinaryDocument() respektive displayAsciiDocument() und zum anderen eine openDocumentWith()-Operation, mit der die Datei mit einer anderen Software als dem dafür vorgegebenen Standard-Tool betrachtet werden kann. Exemplarisch wird hier die Datei DisplayBinaryDocu” ment.wsdl“ dargestellt. <?xml version="1.0"?> 38 Konzeption einer WSDL-Taxonomie der Dienste <definitions targetnamespace="http://com.test/displayBinary" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://com.test/displayBinary"> <message name="displayBinary"> <part name="file" type="xs:base64Binary"/> <part name="resolution" type="xs:string"/> </message> <message name="displayBinaryWith"> <part name="file" type="xs:base64Binary"/> <part name="resolution" type="xs:string"/> <part name="openWith" type="xs:string"/> </message> <message name="jobID"> <part name="ID" type="xs:integer"/> </message <interface> <operation name="displayBinaryDocument"> <input message="tns:display"/> <output message="tns:jobID"/> </operation> <operation name="displayDocumentWith"> <input message="tns:displayWith"/> <output message="tns:jobID"/> </operation> </interface> </definitions> 4.2.2 Input Services Scan Wichtig ist in der Kategorie Scan“ natürlich die eigentliche scanFile” Funktion. In der Regel gibt es zwar auch eine Vorschau-Funktion, aber auf diese wurde hier verzichtet und statt dessen nur eine Funktion gewählt, mit der ein Kunde die Auflösung (dpi) selbst einstellen kann. Ein Scan-Befehl mit einer niedrigen Auflösung würde demnach einem Vorschauscan und ein hoher Wert einem normalen Scanvorgang entsprechen. Als Ausgabe sendet die Funktion die eingescannten Daten in Form einer Datei in dem gewünschten Datenformat zurück. <?xml version="1.0"> <definitions name="ScanFile" targetnamespace="http://com.test/scan" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema">" xmlns:tns="http://com.test/scan"> <message name="scan"> <part name="resolution" type="xs:integer"/> <part name="dataType" type="xs:string"/> </message> Konzeption einer WSDL-Taxonomie der Dienste 39 <message name="scannedFile"> <part name="file" type="base64Binary"/> </message> <interface> <operation name="scanFile"> <input message="tns:scan"/> <output message="tns:scannedFile"/> </operation> </interface> </definitions> Record Die Kategorie Record“ besitzt die zwei Unterklassen Audio In” ” put“ und Video Input“ mit den gemeinsamen Funktionen: startRecording() ” und stopRecording(). Als Szenario denkbar wäre hier zum Beispiel, dass ein Nutzer ein Lied aufnehmen möchte, aber nicht über ein Mikrophon inklusive der entsprechenden Software verfügt - oder aber ein Client möchte per Webcam ein Bild aufnehmen und dieses per Mail oder über einen anderen Dienst weitersenden. Die beiden Funktionen besitzen keine Eingabe, da sie nichts anderes tun, als den Service zu starten und zu stoppen. Die Funktion stopRecording() liefert als Ausgabe die aufgenommenen Daten, die der Kunde dann beliebig weiter verwerten kann. Für den Datentyp den die aufgenommene Datei besitzen soll, gibt es zwei Möglichkeiten: Entweder wird die Auswahl des Datentyps in die Taxonomie integriert werden, das heißt, dass der Kunde schon bei der Auswahl des Dienstes das Ausgabeformat berücksichtigt. Alternativ kann ein zusätzlicher Message-Parameter eingeführt werden, mit dem die Auswahl getroffen werden kann. Im Rahmen der vorliegenden Arbeit wurde die zweite Option verwendet und implizit vorausgesetzt, dass die Dienste in dem Verzeichnis, in dem sie publiziert sind, angeben, welche Formate sie ausgeben können. Wäre dies nicht der Fall, so müsste der Dienstnutzer, zunächst die möglichen Datenformate beim Service erfragen. <?xml version="1.0"?> <definitions> <message name="start"> <part name="dataType" type="xs:integer"/> </message> <message name="stop"> </message> <message name="recordedFile"> <part name="file" type="xs:base64Binary"/> </message> <interface> <operation name="startRecording"> <input message="tns:start"/> </operation> <operation name="stopRecording"> 40 Konzeption einer WSDL-Taxonomie der Dienste <input message="tns:stop"/> <output message="tns:recordedFile"/> </operation> </interface> </definitions> Da auf der Ebene von Audio“ und Video Input“ keine weitere Funktiona” ” lität hinzugefügt wird, sind die WSDL-Fragmente der beiden Klassen hier nicht dargestellt. Sensor Input An dieser Stelle wurde als lokationsbasiertes Szenario angedacht, dass ein Client die aktuelle Temperatur oder den Ozonwert an der für ihn nächsten Messstation abfragen möchte. Auf dieser Ebene wird die Funktion measureValue() angeboten, ihre Ausgabe ist natürlich der gemessene Wert. <definitions> <message name="measure"/> <message name="measureResponse"> <part name="measuredValue" type="xs:integer"/> <message> <interface> <operation name="measureValue"> <input message="tns:measure"/> <output message="tns:measureResponse"/> </operation> </interface> </definitions> Für die Kategorien measure Temperature“ und measure Ozon“ werden ” ” keine weiteren Funktionen eingeführt. Deswegen werden sie an dieser Stelle auch nicht näher beschrieben. Möglich wären an dieser Stelle beispielsweise Funktionen, die die Temperatur bzw. das Ozon mehrmals zu bestimmten Zeiten am Tag messen und ein Array oder eine Liste von Zahlen ausgeben. 4.2.3 Storage and Computation Services BurnCD Mittlerweile sind zwar fast alle neuen PCs und Laptops mit Brenngeräten ausgestattet, aber noch ist nicht jeder in Besitz eines Brenners und muss deswegen auf einen Brenndienst zurückgreifen. Ganz abgesehen davon, gibt es mittlerweile viele kleine mobile Endgeräte, die ebenfalls keinen Brenner besitzen. Das Brennen ist natürlich ein Dienst der Kosten verursacht, aber diese werden an dieser Stelle nicht berücksichtigt. Zur Berücksichtigung von Kosten und deren Abrechnung befinden sich einige Anregungen in einem späteren Kapitel. Konzeption einer WSDL-Taxonomie der Dienste 41 <?xml version="1.0"?> <definitions targetnamespace="http://com.test/burn" xmlns="http://www.w3.org/2003/06/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsd1="http://www.icsy.de/lawns/xml/burn.xsd" xmlns:tns="http://com.test/burn"> <message name="burn"/> <part name="filesToBurn" type="xsd1:listOfBase64Binary"/> <part name="formatOfCD" type="xsd1:CDFormats"/> <part name="titleOfCD" type="xs:string"/> <part name="lengthOfFileandFolderNames" type="xsd1:ISO-Levels"/> <part name="burnSpeed" type="xs:integer"/> </message> <message name="burnResult"> <part name="resultOfBurn" type="xs:string"/> </message> <interface name="burnCD"> <operation name="burnCD"> <input message="tns:burn"/> <output message="tns:burnResult"/> </operation> </interface> </definitions> Die Kategorie BurnCD“ bietet genau eine Funktion an und zwar die Brenn” funktion burnCD, die eine SOAP Message mit Parametern formatOfCD, das angibt, ob es sich um eine Daten-CD, Audio-CD usw. handelt, den Namen der CD (titleOfCD), das ISO-Level, das u.a. die Länge der Dateiund Verzeichnisnamen bestimmt, die Brenngeschwindigkeit und natürlich als Attachment die zu brennenden Daten. Es gibt mit Sicherheit noch weitere Parameter, die für einen Brennvorgang relevant sind, aber diese Arbeit konzentriert sich auf die wichtigsten - weitere Funktionen mit unterschiedlichen Parametern können später beliebig hinzugefügt werden. Im Folgenden sind die XML-Schema-Ausschnitte für die selbst definierten Typen listOfBase64Binary, CDFormats und ISOLevels dargestellt: <xsd:complexType name="listOfBase64Binary"> <xsd:element name="file" type="xsd:base64Binary" minOccurs="1" maxOccurs="1000"/> </xsd:complexType> <xsd:simpleType name="CDFormats"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="audioCD"/> <xsd:enumeration value="dataCD"/> <xsd:enumeration value="audioAndDataCD"/> <xsd:enumeration value="VideoData"/> <xsd:enumeration value="DataInImageFile"/> </xsd:restriction> 42 Konzeption einer WSDL-Taxonomie der Dienste </xsd:simpleType> <xsd:simpleType name="ISOLevels"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="ISOLevel1"/> <xsd:enumeration value="ISOLevel2"/> </xsd:restriction> </xsd:simpleType> Die WSDL-Datei der Kategorie BurnDVD“ ist hier nicht dargestellt, da ” nur der Parameter regionType als Eingabe zur Funktion burn hinzukommt, ansonsten ändert sich nichts. Der regionType kann sechs verschiedene Werte annehmen, je nach dem in welcher geographischen Region der Dienstnutzer die DVD abspielen möchte. 4.2.4 Communication Services An die Dienste Mail, Fax, Chat und SMS wurde auch gedacht, aber es existieren bisher keine plausiblen lokationsbasierten Anwendungsszenarien für diese Dienste. Deswegen werden an dieser Stelle nur die Kategorien Telephone Conference“ und Video Conference“ beschrieben, wobei je” ” weils zwei verschiedene Konferenztypen unterschieden werden können: Dial ” In“ und Dial Out“. Im ersten Fall meldet eine Person, in der Regel der ” Konferenzführer, die Konferenz bei einem entsprechenden Dienst mit PINNummer und Datum des Tages, an dem sie stattfinden soll, an. Die PINNummer und das Datum werden anschließend in irgendeiner Form (Mail, mündlich, ...) den Konferenzteilnehmern bekannt gemacht, die sich dann an dem entsprechenden Tag mittels der PIN-Nummer zur Konferenz einwählen können. Im gibt eine Person unmittelbar vor Beginn der Konferenz oder länger im Voraus die Teilnehmer und deren Rufnummern an. Die Teilnehmer werden dann automatisch angerufen. Selbstverständlich bietet diese Konferenzform ebenfalls die Möglichkeit, Personen durch Angabe von Namen und IP-Adresse nachträglich (auch nach Beginn der Konferenz) einzuladen und Personen von der Konferenz auszuschließen. Bezüglich der WSDL-Dateien gibt es zwar keinen Unterschied zwischen einer Telefon- und Videokonferenz, allerdings stellt es einen großen Unterschied dar, ob der Kunde nun eine Video- oder eine Telefonkonferenz stattfinden lassen möchte. Deswegen wurde für die beiden Arten von Konferenzen eigene Gruppen in der Taxonomie eingeführt. Für eine Videokonferenz wäre beispielsweise folgendes Szenario denkbar: Eine Person möchte oder soll per Konferenz ein Vorstellungsgespräch führen und besitzt dazu nicht die nötige Ausrüstung. Dial In Bei Verwendung dieser Variante der Konferenz werden die Funktionen registerConference(), joinConference(), closeConference(), Konzeption einer WSDL-Taxonomie der Dienste 43 lockConference() und leaveConference(), angeboten. Letztere drei Funktionen benötigen als Eingabe nur die PIN-Nummer, während ihre Ausgabe leer ist. Mit der Operation registerConference() erfragt der Dienstnutzer, ob eine Konferenz an einem bestimmten Tag zu bestimmter Uhrzeit mit der selbst festgelegten PIN-Nummer stattfinden kann. Der Service sendet daraufhin eine Bestätigung, die die PIN-Nummer enthält. <?xml version="1.0"?> <definitions targetnamespace="http://com.test/dialIn" xmlns="http://www.w3.org/2003/06/wsdl" xmlns:xs="http://www.w3.org/2001/XMLSchema">" xmlns:xsd1="http://www.icsy.de/lawns/xml/conference.xsd" xmlns:tns="http://com.test/dialIn"> <import location="conference.xsd" namespace="http://www.icsy.de/lawns/xml/conference.xsd"> <message name="register Conference"> <part name="dateOfConference" type="xs:date"/> <part name="time" type="xs:time"/> <part name="PINNumber" type="xsd1:PINNumber"/> </message> <message name="conferenceID"> <part name="PINNumber" type="xsd1:PINNumber"/> </message> <message name="join"> <part name="PINNumber" type="xsd1:PINNumber"/> <part name="IPNumberOFConference" type="xsd1:IPAddress"/> </message> <interface name="telephoneConferenceInterface"> <operation name="registerConference"> <input message="tns:registerConference"/> <output message="tns:conferenceID"/> </operation> <operation name="joinConference"> <input message="tns:join"/> </operation> <operation name="leaveConference"> <input message="tns:conferenceID"/> </operation> <operation name="closeConference"> <input message="tns:conferenceID"/> </operation> <operation name="lockConference"> <input message="tns:conferenceID"/> </operation> </interface> </definitions> In der WSDL-Datei wird die XML-Schema-Datei conference.xsd“ inklu” diert, die die beiden einfachen Datentypen IPAddress und PINNumber definiert. 44 Konzeption einer WSDL-Taxonomie der Dienste <xsd:simpleType name="IPAddress"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{3}.\d{3}.\d{3}.\d{3}"/> </xsd:restriction> </xsd:simpleType> <xsd:simpleType name="PINNumber"> <restriction base="integer"> <xsd:length value="6"/> </restriction> </xsd:simpleType> Dial Out Für diese Art von Telefon- oder Videokonferenz werden fünf verschiedene Funktionen angeboten. Die erste, registerConference(), erhält als Eingabe das Datum und die Uhrzeit, zu der die Konferenz stattfinden soll und die IP-Adressen der Teilnehmer. Zu gegebenem Zeitpunkt startet dann der Dienstanbieter die Konferenz, indem er die Nachricht startConference() an alle gemeldeten Teilnehmer sendet. Die Konferenz kann folglich beginnen. Soll nachträglich jemand zur Konferenz eingeladen oder von der Konferenz ausgeschlossen werden, so können die Funktionen invitePerson() und excludeFromConference() aufgerufen werden. Beide Funktionen erhalten die IP-Adresse des Teilnehmers als Eingabe. Bei Aufruf der Funktion invitePerson() baut der Service eine Verbindung zu der einzuladenden Person und lädt die Person zur Teilnahme ein. Mit der letzten Operation closeConference() ist es, wie der Name bereits verrät, möglich die Konferenz zu beenden. Die betreffende WSDL-Datei sieht wie folgt aus: <?xml version="1.0"?> <definitions targetnamespace="http://com.test/dialOut" xmlns="http://www.w3.org/2003/06/wsdl" xmlns:xs="http://www.w3.org/2001/XMLSchema">" xmlns:xsd1="http://www.icsy.de/lawns/xml/conference.xsd" xmlns:tns="http://com.test/dialOut"> <import location="conference.xsd" namespace="http://www.icsy.de/lawns/xml/conference.xsd"> <message name="startConference"> <part name="IPAddresssOfparticipants" type="xsd1:listOfIPAddresses"/> <part name="date" type="xs:date"/> <part name="time" type="xs:time"/> </message> <message name="invite"> <part name="newParticipant" type="xsd1:IPAddress"/> </message> <message name="invitationToConference"> </message> <message name="exclude"> <part name="IPAddressParticipant" type="xsd1:IPAddress"/> </message> Konzeption einer WSDL-Taxonomie der Dienste 45 <message name="close"> </message> <interface name="telephoneConferenceInterface"> <operation name="registerConference"> <input message="tns:startConference"/> </operation> <operation name="startConference"/> <output message="tns:invitationToConference"/> </operation> <operation name="invitePerson"> <input message="tns:invite"/> <output message="tns:invitationToConference"/> </operation> <operation name="excludeFromConference"> <input message="tns:exclude"/> </operation> <operation name="closeConference"> <input message="tns:close"/> </operation> </interface> </definitions> In dieser Datei wird neben IPAddress der zusätzliche Datentyp listOfIPAddresses benutzt, der ganz einfach aus einer Liste von IP-Adressen besteht. Dieser Typ ist in der Datei conference.xsd“ definiert, in der auch ” die beiden Datentypen der Variante Dial In“ definiert sind. Da beide den ” Datentyp IPAddress verwenden, wurde aus Gründen der Wiederverwendbarkeit nur eine Schema-Datei und nicht zwei verschiedene erstellt. 46 4.3 Weitere wichtige Aspekte bezüglich lokationsbasierter Dienste Weitere wichtige Aspekte bezüglich lokationsbasierter Dienste Web Services ermöglichen zwar eine relativ einfache Integration beliebiger Anwendungen, aber im globalen Netzverkehr sind auch Aspekte wie Sicherheit, Vertrauenswürdigkeit von Nachrichten, Kodierung sensitiver Daten (beispielsweise Kreditenkartennummer), Workflow-Unterstützung usw. wichtig. Die Basisfunktionalität eines Web Services alleine reicht also nicht aus, es sind unterstützende Zusatzfunktionalitäten erforderlich. Stellvertretend werden an dieser Stelle die Aspekte Autorisierung, Authentisierung und Abrechnung näher beleuchtet. 4.3.1 Autorisierung Für die Frage der Autorisierung (Ist eine Person berechtigt, den Service zu nutzen?) bietet der Standard SOAP eine Möglichkeit. Im Header kann ein Kindelement <authentication> definiert werden, in dem der Benutzername und das Passwort des Dienstnutzers eingegeben werden können [KUWÖ]. Wird zusätzlich noch das Attribut mustUnderstand auf 1 gesetzt, so liefert der Dienst bei nicht bekanntem Benutzernamen oder falschem Passwort eine SOAP-Nachricht mit einer Fehlermeldung an den Dienstnutzer zurück. Eine Fehlermeldung gibt der Dienstanbieter ebenfalls aus, wenn er die Informationen im Header nicht verarbeiten kann. Ein entsprechendes Beispiel sieht wie folgt aus (vgl. [KUWÖ]): <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlSOAP.org/SOAP/envelope"> <SOAP-ENV:Header> <auto:authentication xmlns:auto="URI-Namespace" mustUnterstand="1"> <auto:user>userName</auto:user> <auto:password>password</auto:password> </auto:authentication> </SOAP-ENV:Header> <!-- SOAP Body --> </SOAP-ENV:Envelope> Das Element <authentication> muss als direktes Kindelement vom Hea” der“ seinen eigenen Namespace besitzen, der hier wahlweise auf auto gesetzt wurde. Die Autorisierung muss nicht durch den Empfänger der Nachricht bzw. Dienst selbst verarbeitet werden. Dies kann ebenfalls durch eine dritte Partei ausgeführt werden, wobei die Zwischenstationen, über die die Nachricht läuft, bevor sie ihr Ziel beim Empfänger erreicht, auch Nodes genannt werden. Ein Node kann die Nachricht einfach weiterreichen oder als ein Actor die Autorisierung für den Dienstanbieter übernehmen [KUWÖ]. Nach Weitere wichtige Aspekte bezüglich lokationsbasierter Dienste 47 der Durchführung der entsprechenden Aktion entfernt der Actor die für ihn bestimmte Anweisung aus dem Header oder ersetzt sie durch einen neuen Eintrag und schickt die Nachricht an den Empfänger oder an den nächsten Node weiter. Um dieses Verhalten zu erreichen, muss das Kindelement <authentication> wie folgt erweitert werden: <auto:authentication xmlns:auto="irgendeineURI" mustUnderstand="1" SOAP-ENV:Actor="URI des Actors"> <auto:user>userName</auto:user> <auto:password>password</auto:password> </auto:authentication> Aber eine Autorisierung ist nicht nur über den Standard SOAP realisierbar, auch HTTP Authentication ist geeignet, um zu testen, ob ein Benutzer autorisiert ist, um den Dienst zu nutzen [FRA99]. Eine weitere Möglichkeit zur Autorisierung bieten Zertifikate, sie können mit der SOAP-Nachricht übermittelt werden. Der Dienst oder ein Dritter müssten dann das Zertifikat verifizieren, um festzustellen, ob ein Nutzer berechtigt ist, den Dienst zu nutzen. Zertifikate können aber auch dazu dienen, den Absender einer Nachricht eindeutig zu identifizieren (Authentizität). 4.3.2 Authentizität Unter Authentizität ist laut Duden die Echtheit bzw. Rechtsgültigkeit zu verstehen – im Rahmen dieser Arbeit wurde Authentizität als das Faktum definiert, dass der Empfänger der Nachricht weiß, dass die Nachricht in der Tat von der Person stammt, die als Absender der Nachricht angegeben ist. Mit anderen Worten, der Empfänger der Nachricht kann den Absender eindeutig identifizieren. Für diesen Zweck existieren SOAP-Erweiterungen, die IBM entwickelt hat. Dies ist zum einen ein Erweiterungselement namens ¡SOAP-Authorization¿ das die Möglichkeit bietet, Zertifikate in der SOAPMessage zu inkludieren [NASKSR]. Zum anderen die Möglichkeit der digitalen Signatur [BAR02], die die im nichtelektronischen Bereich übliche Unterschrift ersetzt. Die Signaturen, die dabei auf die Daten im XML-Format angewendet werden, sind selbst in XML geschrieben bzw. kodiert. Es kann in drei Formen von XML Signaturen unterschieden werden [NASKSR]: • enveloped Signature (Die Signatur ist in dem XML-Dokument, das es signieren soll, selbst als Kindelement enthalten) • enveloping Signature (In diesem Fall ist der Inhalt der signiert werden soll, in einem <Object>-Element der Signatur selbst enthalten.) • detached Signature (Die Signatur signiert Daten, die außerhalb des ¡Signature¿-Elements stehen, d.h. die Signatur und die zu signierenden Daten sind voneinander getrennt. Hierbei ist es nicht zwingend 48 Weitere wichtige Aspekte bezüglich lokationsbasierter Dienste erforderlich, dass die Daten und die Signatur in zwei unterschiedlichen Dateien gespeichert sind.) Auch in diesem Bereich wurde in SOAP eine Möglichkeit geschaffen, die das Problem mit Hilfe der Verwendung von XML-basierten digitalen Signaturen adressiert. Hier ist ein Code-Beispiel für diese Technik dargestellt, das sich an ein einfaches Beispiel von der Organisation W3C anlehnt, das unter der URL http://www.w3.org/TR/xmldsig-core/“ zu finden ist: ” <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/envelope/"> <SOAP-ENV:Header> <SOAP-SEC:Signature xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/" SOAP-ENV:actor="Some-URI" SOAP-ENV:mustUnderstand="1"> <ds:Signature Id="MyFirstSignature" xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/> <ds:Reference URI="#Body"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n20010315"/> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <ds:DigestValue> j6lwx3rvEPO0vKtMup4NbeVu8nk= </ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>MC0CFFrVLtRlk=...</ds:SignatureValue> <ds:KeyInfo> <ds:KeyValue> <ds:DSAKeyValue> <P>...</P><Q>...</Q><G>...</G><Y>...</Y> </ds:DSAKeyValue> </ds:KeyValue> </ds:KeyInfo> </ds:Signature> </SOAP-SEC:Signature> </SOAP-ENV:Header> <SOAP-ENV:Body> ... </SOAP-ENV:Body> </SOAP-ENV:Envelope> Weitere wichtige Aspekte bezüglich lokationsbasierter Dienste 49 Dieses Beispiel definiert eine XML-basierte digitale Signatur, die die Daten des SOAP-Envelope signiert. Das <SOAP-SEC:Signature>-Element besitzt folgende Kindelemente: <SignedInfo>, <SignatureValue> und <KeyInfo>. Das erste Element, <SignedInfo>, ist recht komplex und enthält in seinen Kindelementen die Information, mit welchen Algorithmen die Signatur erzeugt wird, und definiert, welche Daten signiert werden. Das Element <SignatureValue> enthält den Wert der erzeugten Signatur. Auf die zu signierenden Daten wird mit dem Element <Reference> verwiesen. Das <KeyInfo>-Element ist optional und enthält Informationen, die der Empfänger der Nachricht nutzen kann, um die Signatur zu validieren. Im obigen Beispiel enthält das letztgenannte Element einen öffentlichen Schlüssel; andere Möglichkeiten sind beispielsweise Zertifikate oder Namen, die einen Schlüssel bzw. ein Schlüsselpaar identifizieren. Eine solche Signatur kann zusätzlich mit einem Zeitstempel versehen werden, aber dies wird hier nicht dargestellt. Auf diese Beispiele wird nun nicht näher eingegangen, für weitergehende Informationen wird auf [BAR02] verwiesen. 4.3.3 Abrechnung Dienste verursachen in der Regel Kosten, die der Dienstnutzer zahlen muss. Die Höhe der Kosten kann ein Kriterium sein, nach dem der Nutzer sich einen Dienst aussucht, deswegen sollten die Kosten des Dienstes in dem Verzeichnis, aus dem der Kunde sich den Dienst aussucht vermerkt sein. Bei komplizierteren Web Services mit längeren Transaktionen kann es sogar sinnvoll sein, einen Vertrag über die Art, Entstehung und Zusammensetzung der Kosten abzuschließen. Die Kostenabrechnung eines Dienstes muss nicht vom Anbieter selbst durchgeführt werden, sie kann auch durch einen Dritten vorgenommen werden. Der Web Service könnte beispielsweise nach der Nutzung die Kosten an einen Dritten melden, der an den Client dann die Rechnung stellt. Eine Realisierungsmöglichkeit der Abrechnung könnte beispielsweise darin bestehen, dass der Kunde seine Bankverbindung oder Kreditkartennummer in einer SOAP-Message mitteilt, dies erfordert allerdings, dass die Nachricht oder zumindest der Teil der SOAP-Message, der die sensitiven Informationen enthält, kodiert wird. Zur Verschlüsselung von Daten existiert eine Empfehlung der Standardisierungsorganisation W3C namens XML Encrypti” on Syntax and Processing“. Das entsprechende Dokument definiert einen Prozess zur Verschlüsselung der Daten und der Repräsentation dieser verschlüsselten Daten in XML [IMA02]. Die Daten können dabei beliebig sein; das Ergebnis ist ein XML Encrytion Element, das die verschlüsselten Daten entweder beinhaltet oder referenziert. Werden einzelne Elemente eines XML-Dokumentes verschlüsselt, so stehen die verschlüsselten Daten an der Stelle, wo die XML-Elemente stehen würden. Im Folgenden ist ein Beispiel dafür dargestellt; es ist der Quelle [IMA02] übernommen. Zunächst sind die 50 Weitere wichtige Aspekte bezüglich lokationsbasierter Dienste Daten unkodiert dargestellt, anschließend kodiert: <?xml version=’1.0’?> <PaymentInfo xmlns=’http://example.org/paymentv2’> <Name>John Smith</Name> <CreditCard Limit=’5,000’ Currency=’USD’> <Number>4019 2445 0277 5567</Number> <Issuer>Example Bank</Issuer> <Expiration>04/02</Expiration> </CreditCard> </PaymentInfo> ----gleiches XML-Dokument mit kodierten Daten: <?xml version=’1.0’?> <PaymentInfo xmlns=’http://example.org/paymentv2’> <Name>John Smith</Name> <EncryptedData Type=’http://www.w3.org/2001/04/xmlenc#Element’ xmlns=’http://www.w3.org/2001/04/xmlenc#’> <CipherData> <CipherValue>A23B45C56</CipherValue> </CipherData> </EncryptedData> </PaymentInfo> Weitere Informationen zu diesem Standard sind unter der Quelle [BAR02] verfügbar. Beispielhafte Implementierungen für Web Services 5 51 Beispielhafte Implementierungen für Web Services In diesem Abschnitt werden beispielhafte Implementierungen für die Druckdienste Print(), viewPrinterQueue(), statusOfJob() und deleteJobFromQueue() beschrieben. Bei der Implementierung wurde das Sun Java Web Service Developer Pack (JWSDP) in den Versionen 1.1 und 1.2 benutzt. Ursprünglich sollte nur mit der Version 1.2 gearbeitet werden. Da aber die bei der Implementierung des Druckdienstes benutzte Schnittstelle JAXM beim Übergang von Version 1.1 auf 1.2 nicht mehr im Developer Pack enthalten ist, wurde zunächst auf die Version 1.1 zurückgegriffen. Im Laufe der Erstellung der vorliegenden Arbeit erschien eine neue Version der JAXM API (JAXM 1.1.2), die dann zur Implementierung des Beispiels benutzt wurde. Als Implementierungssprache für die Beispiele wurde Java verwendet und das Druckersystem CUPS unter SUSE Linux angesprochen. Im folgenden werden zunächst das JWSDP und die bei der Implementierung benutzten Schnittstellen des Pack beschrieben; anschließend wird auf die beiden Beispiele eingegangen. Unter anderem wird der Aspekt beleuchtet, ob die in Kapitel 4.2 erstellten WSDL-Fragemente genutzt werden können. 5.1 5.1.1 Java Web Service Developer Pack Kurzbeschreibung des Pack Das Java Web Service Developer Pack ist eine von SUN Microsystems entwickelte Software, mit deren Hilfe Java-Entwickler Web Services, XML- und Web-Applikationen erstellen, testen und einsetzen kann. Die aktuelle Version ist das JWSDP1.2 und besteht aus folgenden Komponenten (http://www.java.sun.com): • JavaServer Faces (JSF) v1.0 EA4 • XML and Web Services Security v1.0 EA • Java Architecture for XML Binding (JAXB) v1.0.1 • Java API for XML Processing (JAXP) v1.2.3 • Java API for XML Registries (JAXR) v1.0.4 • Java API for XML-based RPC (JAX-RPC) v1.1 EA • SOAP with Attachments API for Java (SAAJ) v1.2 EA • JavaServer Pages Standard Tag Library (JSTL) v1.1 EA • Java WSDP Registry Server v1.0 05 52 Java Web Service Developer Pack • Ant Build Tool 1.5.2 • Apache Tomcat v5 development container • Ws-I Supply Chain Management Sample Application 1.0 EA Im Folgenden werden die in der vorliegenden Arbeit verwendeten Komponenten SAAJ und JAX-RPC des JWSDP 1.2 und die API JAXM genauer beschrieben. 5.1.2 JAX-RPC Das JAX-RPC (Java API für XML-basierte Remote Procedure Calls) ist eine Java-Schnittstelle, die einen XML-basierten Zugriff auf Remote Procedure Calls unterstützt, wodurch ein Aufruf einer Methode in verteilten Systemen ermöglicht wird, zum Beispiel in dem Fall, dass Dienstnutzer und Dienst auf verschiedenen Plattformen arbeiten. Als XML-basiertes Nachrichtenaustauschformat wird der Standard SOAP verwendet (siehe Kapitel 3.1); aktuell in der Spezifikation SOAP 1.1. Obwohl das JAX-RPC eine JavaSchnittstelle ist, setzt dies nicht voraus, dass sowohl der Nutzer als auch der Anbieter eine Java-Plattform einsetzen. Schließlich werden die Nachrichten im XML-Format SOAP ausgetauscht und beide Seiten können jede beliebige Technik nutzen, mittels derer die Daten einer Nachricht entpackt und verwertet werden können, und das JAX-RPC ist nur eine Möglichkeit dafür. Zurzeit gibt es zwei Ansätze, um einen Web Service, seine Dienstbeschreibung und die entsprechenden Applikationen mittels JAX-RPC zu erstellen: • Top Down – Bei diesem Ansatz wird zuerst die Dienstbeschreibung, die WSDL-Datei, erstellt, die dann benutzt wird, um automatisch stub“- oder skeleton“-Code zu generieren, der dann mit der Funk” ” tionalität ausgefüllt wird. • Bottom Up – Bei diesem Ansatz werden erst die Klassen bzw. der Applikationscode programmiert, der zur automatischen Generierung einer WSDL-Datei genutzt wird. Die Vorgehensweise, um einen Web Service mit dem Bottom-Up-Ansatz zu generieren, sieht wie folgt aus: • Begonnen wird mit der Programmierung des Servicecodes, der aus einem Interface und einer Klasse, die das Interface implementiert, besteht. Zusätzlich muss für jeden selbstdefinierten Datentyp eine eigene Java-Klasse oder ein Java Bean geschrieben werden. • Anschließend muss der betreffende Code kompiliert werden, dazu und für die folgenden Befehle kann das Ant-Tool1 benutzt werden. In diesem Fall lautet der Befehl: ant compile. 1 Entwicklungstool für Java von der Apache Software Foundation. Java Web Service Developer Pack 53 • Danach kann mittels des Befehls ant package des Ant-Tool oder mit alternativen Befehlen (unter Unix jar) eine WAR-Datei mit unten angegebener Struktur erstellt werden. • Als Nächstes wird das wsdeploy-Tool des Service Pack benutzt (ant process-war), um eine (deployable) WAR-Datei zu erstellen. Das Tool erzeugt ebenfalls die ties“ für den Service und die WSDL-Datei. ” Das wsdeploy-Tool benötigt als Eingabe eine Datei namens jaxrpc” ri.xml“, in der ein oder mehrere <endpoint>-Elemente definiert werden müssen. Das <endpoint>-Element besitzt Attribute, die den Namen des Endpunktes festlegen, den Namen, unter dem der Service angezeigt werden soll, den Namen des Interfaces und den Namen der Klasse. Mittels des <endpoint-Mapping>-Elements wird angegeben, unter welcher URL der Endpunkt erreichbar sein soll. • Waren die vorhergehenden Schritte erfolgreich, so kann der Dienst mittels des Befehls ant deploy oder mit dem Tomcat2 deployed werden. • Danach erfolgt der Aufruf von wscompile zur Generierung der stubs“ ” für den Client (zur Eingabe benötigt der Befehl die Datei config.xml“, ” in der die WSDL-Datei spezifiziert wird). • Zum Schluss wird ein Client implementiert, der den Service benutzt. Bei Verwendung des Top-Down-Ansatzes sieht die Vorgehensweise wie folgt aus: • Da die WSDL-Beschreibung vorliegt, wird mit dem Aufruf des Befehls wscompile begonnen. Dieser kann benutzt werden, um Code sowohl für die Client-Seite als auch für die Server-Seite zu generieren. Zusätzlich wird abhängig vom Inhalt der Datei config.xml“ ein WSDL” Dokument oder eine Service-Endpunkt-Definition generiert. Ebenso wird noch ein model-file erstellt, eine XML-Datei, die Informationen über den Service enthält. Dieses model-file ist so aufgebaut, dass es vom wsdeploy-Tool benutzt werden kann. • Anschließend muss eine Klasse geschrieben werden, die den Service implementiert, Klassen für die selbstdefinierten Datentypen sind bereits von der WSDL-Datei generiert worden. Ist die Implemetierung abgeschlossen, muss der Code kompiliert und eine WAR-Datei erzeugt werden. • Mit dem Befehl wsdeploy wird danach eine deployable WAR-Datei erzeugt, die per ant deploy oder Tomcat deployed wird (Aufruf von wsdeploy unter Nutzung des model-file). 2 Tomcat bezeichnet eine Ablaufumgebung für serverseitiges Java (Servlet) und die Java Server Pages (JSP) von der Apache Software Foundation. 54 Java Web Service Developer Pack • Als Abschluss wird ein Client zum Testen des Dienstes implementiert. Eine WAR-Datei ist eine JAR-Datei (Java-Archiv) mit folgender Verzeichnisstruktur: WEB-INF/ WEB-INF/classes (kompilierte Service- oder Client-Klasse) WEB-INF/src (Source-Code des Services oder Client) WEB-INF/web.xml WEB-INF/jaxrpc-ri.xml (falls JAX-RPC Web Service) *.html (falls JAXM und HTTP-Servlet: HTML-Datei, die das HTTPServlet startet) Bei den Ansätzen ist zu beachten, dass nicht alle Datentypen des XMLSchemas bzw. Java-Codes von den aktuellen Software-Tools, die die automatische Generation durchführen, unterstützt werden. Da in der vorliegenden Arbeit das Sun Java Web Service Developer Pack benutzt wurde, gelten die nachfolgenden Ansätze auch nur für das JWSDP. Nicht unterstützte Datentypen beim Top-Down-Ansatz Zunächst ist in diesem Abschnitt anzumerken, dass das JWSDP 1.2 noch nicht die aktuelle Version WSDL 1.2 unterstützt, sondern nur die Version WSDL 1.1. Da zur Erstellung der WSDL-Taxonomie die Version 1.2 benutzt wurde, werden hier zur Verständlichkeit der Beispiele die Unterschiede zwischen den beiden Versionen, soweit relevant, aufgelistet. • Das Element <portType> wurde in <interface> umbenannt. Das <interface>-Element erhielt zusätzlich die Funktionalität vererbar zu sein. • Das <port>-Element wurde in <endpoint> umbenannt. • Das von WSDL 1.1 unterstütze Überladen von Operationen wurde in der Version 1.2 entfernt. • In der Version 1.1 diente das <import>-Element dazu, andere Dateien (WSDL oder XML-Schemata) unabhängig vom verwendeten targetNamespace zu importieren. Waren die Zielnamensräume verschieden, so wurde das targetNamespace angegeben; waren sie hingegen gleich, wurde das targetNamespace-Attribut nicht gesetzt. Diese Funktionalität wird, wie in Kapitel 3.2.2 beschrieben, nun auf die beiden Elemente <include> und <import> aufgeteilt. Des Weiteren werden Typ- bzw. Elementdefinitionen des XML-Schemas, die die Attribute minOccurs und maxOccurs verwenden, von dem JWSDP Java Web Service Developer Pack 55 bei der automatischen Generierung von Code-Teilen aus WSDL nicht unterstützt. Folgender in Kapitel 4.2 definierter komplexer Datentyp ist demnach nicht möglich: <xsd:complexType name="printerQueue"> <xsd:element name="printJob" type="tns:printerQueueEntry" minOccurs="0" maxOccurs="1000"/> </xsd:complexType> Statt dessen muss der komplexe Datentyp als Array definiert werden, das im Fall des Beispiels wie folgt aussieht: <complexType name="printerQueue"> <complex Content> <restriction base="soap11-enc:Array"> <sequence> <attribute ref="soap11-enc:arrayType" wsdl:arrayType="tns:PrinterQueueEntry[]"> </sequence> </restriction> </complexContent> </complexType> Unterstützte Datentypen beim Bottom-Up-Ansatz Im Gegensatz zum Top-Down-Ansatz werden hier nicht die Datentypen beschrieben, die nicht unterstützt werden, sondern die Typen aufgelistet, die unterstützt werden. Möchte ein Dienstanbieter erst den Dienst in Java programmieren und dann mittels des JWSDP die Dienstbeschreibung automatisch erstellen, so muss er darauf achten, dass die Java-Datentypen unterstützt werden. Folgende primitive Datentypen werden von der aktuellen JAX-RPC-Version unterstützt (siehe Beschreibung [ARM03]): • boolean • byte • double • float • int • long • short Unterstützt werden ebenfalls ein- und mehrdimensionale Arrays von den eben genannten primitiven Datentypen. Ferner sind strukturierte Typen, sogenannte Value Types“, möglich, wobei allerdings nachstehende Regeln ” eingehalten werden müssen: 56 Java Web Service Developer Pack • Die Klasse muss einen öffentlichen Default-Konstruktor besitzen. • Die Klasse darf weder direkt noch indirekt das Interface java.rmi.Remote implementieren. • Die einzelnen Komponenten des Datentyps müssen von JAX-RPC unterstützte Datentypen sein. • Der Value Type“ kann aus öffentlichen, privaten oder geschützten ” (public, private oder protected) Feldern bestehen, wobei gilt: – Ein öffentliches Feld darf nicht als final oder transient deklariert werden. – Ein nicht-öffentliches Feld muss mindestens eine get- und eine set-Methode definieren. Alle JavaBeans, die den gleichen oben genannten Regeln für Klassen entsprechen und jeweils eine get- und eine set-Methode für jede der Eigenschaften (bean properties) besitzen, werden unterstützt. Ebenfalls können die in der folgenden Tabelle dargestellten Klassen verwendet werden, die das java.util.Collection-Interface implementieren. java.util.Collection Subinterface List Map Set Implementation Interface ArrayList LinkedList Stack Vector HashMap Hashtable Properties TreeMap HashSet TreeSet Erstellung des Client Ein Client, der JAX-RPC benutzt, kann eine Operation eines Service-Endpunktes auf drei verschiedene Arten aufrufen: 1. Die Operation kann durch ein lokales Objekt, einen sogenannten stub“, ” aufgerufen werden. 2. Ein dynamischer Proxy“ kann benutzt werden, um die Operation ” aufzurufen. 3. Die Operation kann mittels des Dynamic Invocation Interface (DII)“ ” dynamisch aufgerufen werden. 57 Java Web Service Developer Pack Im Folgenden werden diese drei Varianten beschrieben, wobei die erste am ausführlichsten erläutert wird, da diese bei der Implementierung des JAXRPC-Beispiels verwendet wird. Die erste Variante wird benutzt, wenn der Dienstnutzer weiß, welche Operation er aufrufen möchte und wie er sie aufrufen muss, das heißt, dass er auch weiß, welche Parameter die Funktion benötigt. Der stub“ dient der Verein” fachung von remote calls“, denn der Client sendet seinen Operationsaufruf ” an den stub“ (der das entfernte Objekt lokal repräsentiert) und damit be” steht für ihn kein Unterschied zu einem lokalen Aufruf. Der stub“ übersetzt ” dann den Funktionsaufruf in das richtige Format und sendet ihn zum Server. Dieser Prozess wird auch als marshalling“ bezeichnet. Auf Serverseite ” existiert ein tie“, der das Gegenstück zum stub“ auf Clientseite darstellt. ” ” Der tie“ entpackt die Information ( auch unmarshalling“ genannnt) und ” ” ruft dann die Funktion auf dem Objekt aus. Für die Antwort wird der Prozess umgekehrt. Der stub“ kann mittels des Befehls wscompile“ des ” ” JWDP automatisch von einer WSDL-Beschreibung oder der Definition eines Service-Endpunktes generiert werden [ORMA02]. Client 3. Runtime maps call to SOAP message Server 10. Runtime extracts SOAP Message 4. Runtime extracts SOAP Message HTTP JAX-RPC Runtime JAX-RPC Runtime SOAP Message 11. Stub returns response 2. Stub converts call Tie 12. Application gets response Client Applikation 8. Tie converts response 5. Tie makes call on Web Service Stub 1. Application makes RPC call 9. Runtime maps response to SOAP message 6. Web Service processes request 7. Web Service returns response Web Service Abbildung 5: Use stub“ to make remote call“. Quelle: The JavaTM Web ” ” Service Developer Pack, Part 2 [ORMA02]. Die zweite Variante benötigt keinen im voraus generierten Code ( stubs“), ” denn zur Laufzeit wird dynamisch ein proxy“ erzeugt, in dem die getPort” Funktion der Schnittstelle javax.xml.rpc.Service aufgerufen wird. Als Eingabe benötigt, die getPort()-Funktion lediglich den Namen des Ports und das kompilierte Interface des Endpunktes; Ausgabe der Operation ist eine dynamisch erstellte Implementierung des Service-Endpunktes. Diese Implementierung benutzt das java.lang.reflect.Proxy Objekt, um die 58 Java Web Service Developer Pack Objekte zu erstellen (einen entsprechenden SOAP-Envelope in diesem Fall), die per java.lang.reflect.InvocationHandler.invoke() an den Dienst geschickt werden [CHJE03]. Für weitere Informationen zur Funktionsweise von dynamischen Proxys wird auf die J2SE Dokumentation von Sun Microsystems verwiesen, die unter http://java.sun.com/j2se/ zu finden ist. Kennt der Dienstnutzer zur Laufzeit weder den Namen der Funktion, die er aufrufen möchte, noch die Anzahl, Art und Namen der Parameter, so kann er die Variante drei nutzen. Hier wird die Methode auf Client-Seite auf einem call-Objekt ausgeführt. Die Datenstruktur eines Call-Objektes spiegelt die Struktur einer WSDL-Datei wieder; es besitzt Attribute für folgende Informationen einer WSDL-Datei [ORMA02]: • Name der Operation • Interface des Service-Endpunktes • Eigenschaften der Anbindung (wie die SOAP Action Header URI der SOAP-Anbindung) über HTTP • Name, Typ und Modus der Ein- und Ausgabeparameter • Typ des Rückgabewertes Wird die Service-Endpunkt-Implementierung von einer WSDL-Datei generiert, werden diese Attribute mit Hilfe der WSDL-Datei gesetzt. Alternativ kann ein Client das Call-Objekt auch mittels set-Methoden konfigurieren, wie dies in einem Beispiel im JWSDP, Part 2 dargestellt ist [ORMA02]. Ein ausführliches Beispiel beschreiben auch Chappell und Jewell in ihrem Buch Java Web Services [CHJE03] (S. 168-171). Ferner unterstützt das DII nicht nur Request/Response-Nachrichten, sondern ist ebenfalls in der Lage asynchrone Nachrichten zu versenden. Auf diese Variante wird nun nicht näher eingegangen, da sie in den Beispielen nicht verwendet wird. 5.1.3 JAXM und SAAJ JAXM steht für Java API for XML Messaging“ und unterstützt mehre” re Industriestandards, unter anderem SOAP und ebXML [NASKSR]. Die Schnittstelle JAXM ermöglicht Java-Anwendungen einen Informationsaustausch mittels XML-Format über das Intranet oder Internet, wobei sowohl das Versenden von synchronen (request/response) als auch von asynchronen Nachrichten (one-way messages) unterstützt werden. Diese API wurde speziell für den Austausch von Dokumenten entwickelt und ist damit besonders auf Operationen im B2B (Business-to-Business) fokussiert, wo es häufig erforderlich ist, Dokumente auszutauschen [ARM03]. Im Gegensatz zum JAX-RPC wird bei dieser API keine spezielle Funktion/Methode aufgerufen, sondern ein XML-Dokument zum Service geschickt und vorausgesetzt, Java Web Service Developer Pack 59 dass der Service den Inhalt des Dokuments versteht und daraufhin die entsprechende Funktion aufruft. Ebenso ist die Antwort des Services auch nicht die Ausgabe einer Funktion sondern eine Nachricht, die die ausführende Applikation erstellt hat. In einem solchen Szenario ist es also sehr wichtig, dass sowohl Client als auch Service die Bedeutung der Nachrichten verstehen, die an sie gesendet werden. Diese API besteht aus zwei verschiedenen Paketen [ARM03]: • javax.xml.soap • javax.xml.messaging Erstgenanntes Paket gibt es auch getrennt von dem zweiten und heißt dann SAAJ (Soap Attachment API for Java) und ist im Gegensatz zu JAXM in dem Developer Pack 1.2 enthalten. Die JAXM API war nur bis zur Version 1.1 des Developer Pack integriert und wurde dann aus dem Pack ausgelagert. Das Paket javax.xml.soap stellt Interfaces und Klassen zur Verfügung, mit deren Hilfe der Programmierer eine SOAP Message und eventuell vorhandene Attachments erstellen und handhaben kann. Des Weiteren ermöglicht dieses Paket dem Client das Versenden von point-to-point“ response/request ” Nachrichten. Unter einer point-to-point“-Verbindung ist in diesem Szena” rio zu verstehen, dass die Nachricht von einem Client direkt an den Service gesendet wird. Request/Response heißt in diesem Fall, dass die Ausführung des Client-Codes nach Aufruf der entfernten Methode so lange gestoppt wird, bis der Client die Antwort auf seine Anfrage erhält. Viele der Namen der Klassen und Interfaces dieses Pakets entsprechen den Elementen einer SOAP-Nachricht, weswegen der Programmierer stets das Bild einer SOAPMessage vor Augen haben sollte, wenn er eine solche mit Hilfe der Interfaces und Klassen dieses Pakets zusammenstellt oder handhabt. Um eine One-Way-Nachricht zu versenden oder einen Message Provider zu benutzen, wurde das zweite Paket, das javax.xml.messaging entwickelt. Der Message Provider übernimmt die Übermittlung und das Routing der Nachrichten. Die Benutzung eines Providers zum Versenden und Empfangen von Nachrichten ist optional und deswegen wird bei der Erstellung eines JAXM-Servlets in solche unterschieden, die einen Provider nutzen, und solche, die keinen nutzen. Der Service erweitert das JAXM-Servlet und muss eine Methode onMessage() besitzen, die aufgerufen und abgearbeitet wird, sobald eine Nachricht eintrifft. Wird kein Provider verwendet, so muss der Client nicht in einem Web Container laufen. Ein Service, der auf der API SAAJ basiert, also nur auf dem ersten Paket, können der Service und der Client alternativ die Klasse HTTP-Servlet erweitern. In diesem Fall besitzt der Client eine doGet()-Methode, die eine Nachricht über HTTP versendet, woraufhin die doPost()-Methode des Services aufgerufen wird, die wiederum die onMessage()-Methode aufruft. 60 Beispielimplementierungen für Druckdienste Soll das JAXM-Servlet benutzt werden, um einen Request/Response-Service zu erstellen, so muss das JAXM-Servlet das Interface ReqRespListener implemetieren. Sollen hingegen asynchrone Nachrichten verschickt werden, so muss die Klasse das Interface OneWayListener implementieren. Auf die einzelnen Klassen und Interfaces wird an dieser Stelle aber nicht näher eingegangen, ihre Verwendung wird an den nachfolgenden Beispielen klar gemacht und kommentiert. Ferner wird auf das allgemeine JWSDPTutorial [ARM03] und das JWSDP-Tutorial Part 2 [ORMA02] verwiesen. 5.2 Beispielimplementierungen für Druckdienste In diesem Kapitel wird die Implementierung eines Druckdienstes zum Drucken der Formate PS, HTML und XML auf einem Schwarz-Weiß-Drucker als Web Service beschrieben. Die Druckfunktion, wurde mittels der API JAXM implementiert, da diese API, wie bereits erwähnt, speziell für den Transport von Dokumenten entwickelt wurde und sich demnach sehr gut für den Druckdienst eignet. Schließlich muss der Client zum Drucken, seine Datei bzw. sein Dokument an den Web Service versenden. Des Weiteren wurde ein Druckmanagementdienst implementiert, der Funktionen zum Anzeigen der Druckerschlange bzw. der Druckjobs, zum Löschen des Druckauftrages und zur Anzeige des Status eines Druckjobs anbietet. Für den Druckmanagementdienst wurde die API JAX-RPC verwendet, da diese Funktionen keine Dokumente sondern Parameter als Eingabe erwarten, mit denen eine Funktion aufgerufen wird, um eine bestimmte Aktion auszuführen und/oder Information zu erhalten. Unter anderem wurde für letztere Funktionen auch das JAX-RPC ausgewählt, weil diese API Funktionen besitzt, die die Verwendung der WSDL-Dateien aus der Taxonomie ermöglichen, sofern der TopDown-Ansatz verwendet wird. In der vorliegenden Arbeit werden nur exemplarisch Teile ausprogrammiert und beschrieben, da eine vollständige Implementierung nicht gefordert war. In Abbildung 6 sind die oben beschriebe- JAXM SOAP MSG (HTTP) print() JAXM PrintService JAX-RPC SOAP MSG (HTTP) statusOfJob(), remove(), viewPrinterQueue() JAX-RPC PrintManagement Service Requestor Service Provider Abbildung 6: Druckdienst Realisierung Beispielimplementierungen für Druckdienste 61 nen Implementierungsentscheidungen veranschaulicht. Der drei Funktionen umfassende Web Service PrintManagement wurde sowohl mit dem BottomUp-Ansatz, als auch mit dem Top-Down-Ansatz, der eine den Dienst beschreibende WSDL-Datei benutzt, erstellt. Zwar führen beide Ansätze zum gleichen Ziel, aber sie unterscheiden sich in einigen Punkten, weswegen hier beide Ansätze in groben Zügen dargestellt sind. 5.2.1 PrintManagement – Bottom-Up-Ansatz Bei diesem Ansatz werden zunächst die Schnittstelle des Services und eine Klasse, die diese Schnittstelle implementiert, erstellt. Die Schnittstelle heißt PrintIF.java und der Quellcode sieht wie folgt aus: package print; import import import import java.rmi.Remote; java.rmi.RemoteException; print.PrinterQueueEntry; print.StatusType; public interface PrintIF extends Remote { public StatusType statusOfJob (int printID, String printerName) throws RemoteException; public PrinterQueueEntry[] viewPrinterQueue (String printerName) throws RemoteException; public String remove (int printID, String printerName) throws RemoteException; } Die Schnittstelle PrintIF deklariert die drei Funktionen statusOfJob(), viewPrinterQueue() und remove(), wobei sie das Interface Remote erweitert, da diese drei Funktionen Methoden auf entfernten Objekten aufrufen; dementsprechend muss ebenso eine RemoteException abgefangen werden. Die Funktionen remove() und statusOfJob() benötigen neben der ID des Druckjobs noch den Namen des Druckers, falls der Druckdienst mehrere Drucker besitzt, die über unterschiedliche Namen angesprochen werden. Anschließend müssen die Schnittstelle und die einzelnen Funktionen implementiert werden. Dies wird in der Klasse PrintImpl.java getan; sie ist nachfolgend dargestellt. package print; import import import import java.io.*; java.rmi.RemoteException; print.PrinterQueueEntry; print.StatusType public class PrintImpl implements PrintIF, java.rmi.Remote, Serializable { 62 Beispielimplementierungen für Druckdienste public StatusType statusOfJob(int printID, String printerName) { // implementation of the function statusOfJob() } public PrinterQueueEntry[] viewPrinterQueue(String printerName) { // implementation of the function viewPrinterQueue() } public String remove(int printID, String printerName) { // implementation of the function remove() } } Die Funktion statusOfJob() erhält als Eingabe die ID des Druckauftrags sowie den Namen des Druckers und gibt den Status des Druckauftrags in Form eines selbstdefinierten Datentyps zurück, der die Werte printed“, ” printing“ oder queued“ annehmen kann. Da der Status eines Druckauf” ” trages in der Ausgabe des Linux CUPS (Common Unix Print System) nicht angegeben wird, wurde diese Funktion wie folgt implementiert: Zur Laufzeit wird die Funktion lpq zur Ausgabe der Druckerschlange aufgerufen und deren Ausgabe dann zeilenweise eingelesen und überprüft wird, ob eine dieser Zeilen in der Spalte printID, den Wert der gesendeten ID enthält. Folglich wird nur zwischen den printed“ und queued“ unterschieden. ” ” Die zweite Funktion gibt die zur Laufzeit des Programms akutelle Druckerschlange zurück. Dazu wird zunächst die Ausgabe des lpq-Befehls in eine Datei gelesen, die dann geparst wird, um die notwendigen Informationen zu entnehmen und in einem PrinterQueueEntry-Array zu speichern, das von der Laufzeitumgebung des JAX-RPC serialisiert wird und in den SOAPBody der Nachricht an den Client im XML-Format eingefügt wird. Die letzte Funktion löscht einen Druckauftrag mit einer bestimmten printID auf einem bestimmten Drucker. Da ein Auftrag bereits ausgedruckt sein könnte oder die printID falsch, wird an dieser Stelle gegebenenfalls der Error-Stream abgefangen und ausgegeben. Für den Typ StatusType muss eine eigene Klasse geschrieben werden, die teilweise nachstehend dargestellt ist. Diese muss sich an die Einschränkungen von JAX-RPC bezüglich der Datentypen richten und wird in dem nachfolgenden Unterkapitel mit der automatisch generierten Klasse vom Top Down Ansatz verglichen. package print; import java.io.*; public class StatusType implements Serializable { private String value; Beispielimplementierungen für Druckdienste 63 public static final String queuedString = queued“; ” public static final String printingString = printing“; ” public static final String printedString = printed“; ” public static final String queued = new String( queuedString); public static final String printing = new String( printingString); public static final String printed = new String( printedString); public static final StatusType queued = new StatusType( queued); public static final StatusType printing = new StatusType( printing); public static final StatusType printed = new StatusType( printed); public StatusType() { } protected StatusType(String val) { this.value = val; } public String getValue() { return value; } public void setValue(String s) { if (s== queuedString) value= queued; if (s== printingString) value= printing; if (s== printedString) value= printed; } // Hier können wie bei der automatisch generierten Klasse // noch die Funktionen fromValue(), fromString(), toString(), // equals() und hashCode() implementiert werden ... } Da sich die Unterschiede zur der automatisch generierten Klasse beim TopDown-Ansatz nur am Anfang befinden, ist die Klasse StatusType aus Platzgründen hier nicht vollständig dargestellt. Der Name der Variablen value wurde hierbei beibehalten, anstatt sie z.B. in status umzutaufen, damit die Beispiele direkt vergleichbar sind. Bei der Erstellung der Klasse PrinterQueueEntry wurde ebenfalls darauf geachtet, dass sie die Bedingungen eines JAX-RPC-Typs entspricht. Aus diesem Grund werden für die Attribute der Klasse nur einfache unterstützte Datentypen verwendet. Alternativ hätte an dieser Stelle für das Attribut status statt des Typs String auch der selbstdefinierte Typ StatusType gewählt werden können. Die Klasse sieht wie folgt aus: package print; import java.io.*; 64 Beispielimplementierungen für Druckdienste public class PrinterQueueEntry implements Serializable { private int printID; private String status; private String fileName; private int percentagePrinted; private int positionInPrinterQueue; public printerQueueEntry(int prID, String stat, String name, int percentage, int position) { this.printID = prID; this.status = stat; this.fileName = name; this.percentagePrinted = percentage; this.positionInPrinterQueue = position; } public printerQueueEntry() { } // passende get- und set-Methoden müssen an dieser // Stelle für jedes Attribut der Klasse definiert // werden... ... } Für diese von JAX-RPC unterstützten Datentypen werden von jedem JAXRPC konformen System automatisch Serialisierer und Deserialisierer zum Übersetzen von Javaobjekten in das XML-Format und umgekehrt (marshalling, unmarshalling) zur Verfügung gestellt (siehe Abbildung 7). Für andere Java Type Serializer XML XML Deserializer Java Type JAXRPC Service Java Client Java Type Deserializer XML XML Serializer Java Type Abbildung 7: Serializers and Deserializers. Quelle: [MAG03], S. 388. Objekte muss der Programmierer sich seine Serialisierer und Deserialisierer selbst schreiben. Diese sind im Anschluss spätestens zur Laufzeit des Programmes in der TypeMappingRegistry des JAX-RPCs zu registrieren, damit zum Übersetzen darauf zurückgegriffen werden kann. Die TypeMappingRegistry ist eine Tabelle mit sogenannten TypeMapping -Einträgen, die bestimmten encoding styles zugeordnet werden [MAG03]. Ein TypeMappingEintrag besteht aus folgenden Attributen: Java-Typ (Klasse), SerializerFactory, DeserializerFactory und dem entsprechenden XML-Typ. Zur Laufzeit des Web Services schaut die JAX-RPC Routine in dieser Tabelle nach, damit sie weiß, wie die entsprechenden Datentypen serialisiert, deserialisiert Beispielimplementierungen für Druckdienste 65 und kodiert werden. Da die durch JAX-RPC zur De-/Serialisierung bereitgestellten Interfaces (Serializer, Deserializer, SerializationContext und DeserializationContext) keine Methoden enthalten, die die Funktionalität zur Serialisierung und Deserialisierung realisieren, wird oder muss der Anwendungsentwickler sich seine eigenen De-/Serialisierer als Sub- oder Unterklassen der zuvor genannten Interfaces programmieren. In der Regel sind die auf diese Weise vorgenommenen Implementierungen an die jeweilige Laufzeitumgebung angepasst. Sind sind folglich spezifisch für eine bestimmte Implementierung und daher nur für diese verwendbar [MAG03]. Der Rückgabewert der Funktion viewPrinterQueue() ist ein Array von dem Typ PrinterQueueEntry und damit kein Array eines der unterstützten Standardtypen. Dennoch wird der Befehl wscompile“ Serialisierer für ” den Datentyp generieren, was für alle in der WSDL-Datei definierten Datentypen möglich ist. Für die Serviceseite ist es wichtig, dass die Klasse, die den selbstdefinierten Datentyp definiert, das Interface Serializable implementiert. Ist dies der Fall, so werden durch den Befehl wsdeploy“ auto” matisch die benötigten Serialisierer (Serialisierer und Deserialisierer befinden sich dabei in der gleichen Klasse) generiert und in der TypeMappingRegistry registriert. Die einzige Einschränkung, die bei dieser Art von selbstdefinierten Datentypen existiert, ist die Tatsache, dass nur ein statischer Client über seinen stub“ automatisch auf diese Serialisierer zurückgreifen kann, ” ein dynamischer Proxy oder ein DII-Client würde einen Serialisierungsfehler melden. Zur Fertigstellung des Web Services wurden die Funktionen des JWSDP und das ant-Tool, wie in Kapitel 5.1.2 beschrieben, benutzt. Zum Testen des Web Services wurde ein statischer Client verwendet. Durch das automatische Erstellen der stubs“ für den Client ergibt sich eine weitere Variante der ” Klasse Statustype. Sie besitzt zwei öffentliche Konstruktoren und jeweils eine get- und eine set-Methode. Sie ist nachfolgend dargestellt: // This class was generated by the JAXRPC SI, do not edit. // Contents subject to change without notice. // JAX-RPC Standard Implementation (1.1, build EA-R39) package print.stubs; public class StatusType { protected java.lang.String value; public StatusType() { } public StatusType(java.lang.String value) { this.value = value; } 66 Beispielimplementierungen für Druckdienste public java.lang.String getValue() { return value; } public void setValue(java.lang.String value) { this.value = value; } } 5.2.2 PrintManagement - Top Down Ansatz Zunächst wurde untersucht, ob die in Kapitel 4.2 erstellte WSDL-Datei (siehe Seite 29) von dem JAX-RPC verwendet werden kann. Da die WSDL-Datei den Beschränkungen der unterstützten Datentypen unterliegt, die bereits in diesem Kapitel beschrieben wurden, musste die Datei von WSDL Version 1.2 auf die Version 1.1 angepasst und ein Array für den komplexen Typ PrinterQueueEntry definiert werden. Des Weiteren wurden zur Vervollständigung der Dienstbeschreibung zusätzliche WSDL-Elemente (<binding>, <endpoint>, <service>) und Erweiterungselemente für die Anbindung an SOAP über HTTP angefügt. Die resultierende WSDL-Datei kann im Anhang eingesehen werden. Mittels des wscompile-Tools, das als Eingabe eine Datei namens config.xml, die auf die WSDL-Datei verweist, benötigt, erstellte das JWSDP automatisch Klassen für die Datentypen StatusType und PrinterQueueEntry inklusive der für diese Klassen benötigten Serialisierer und Deserialisierer, damit die Datentypen in XML transformiert werden können und umgekehrt. Ferner wurde für jede der drei Funktionen in einer Klasse die Requestund Responsestruktur beschrieben, damit die SOAP-Nachricht entsprechend aufgebaut bzw. entpackt werden kann. Letztendlich wurde für den Client ein stub“ und für den ” Dienstanbieter ein tie“ erstellt sowie das Interface PrintIF. Die Klasse StatusType“ wird ” ” nachfolgend teilweise dargestellt, da sie sich durch die beim Bottom Up Ansatz erstellte unterscheidet. // This class was generated by the JAXRPC SI, do not edit. // Contents subject to change without notice. // JAX-RPC Standard Implementation (1.1, build EA-R39) package print.stubs; public class StatusType implements java.io.Serializable { private java.lang.String value; public static final String queuedString = queued“; ” public static final String printingString = printing“; ” public static final String printedString = printed“; ” public static final java.lang.String queued = new java.lang.String( queuedString); public static final java.lang.String printing = new java.lang.String( printingString); public static final java.lang.String printed = new java.lang.String( printedString); public static final StatusType queued = new StatusType( queued); public static final StatusType printing = new StatusType( printing); public static final StatusType printed = new StatusType( printed); Beispielimplementierungen für Druckdienste 67 protected StatusType(java.lang.String value) { this.value = value; } public java.lang.String getValue() { return value; } ... } Der Unterschied zu den beiden beim Bottom-Up-Ansatz erstellten Klassen ist sofort sichtbar, denn zum einen wird kein öffentlicher Konstruktor definiert und des anderen existiert für die Variable value keine set-Methode. Statt dessen besitzt die Klasse einen geschützten Konstruktor, der außerhalb der Klasse nicht aufgerufen werden kann. Damit entspricht die Klasse nicht mehr den für einen JAX-RPC-Typ geforderten Eigenschaften und würde beim Versuch, die Klasse als Eingabe für den Bottom-Up-Ansatz zu verwenden, einer Fehlermeldung herbeiführen. Im Anschluss wurde eine Klasse geschrieben, die das Interface implementiert. Sie unterscheidet sich nicht von der Klasse, die beim Bottom Up Ansatz implementiert wurde und ist deswegen hier weder dargestellt noch beschrieben. Anschließend wurde wie in Kapitel 5.1.2 beschrieben weiterverfahren. Zum Testen des Web Services wurde der gleiche statische Client wie beim Bottom-Up-Ansatz verwendet. 5.2.3 JAXM-basierter PrintService In diesem Kapitel wird der Web Service PrintService mittels der API JAXM implementiert. Wie bereits zuvor beschrieben, müssen sich der Dienstanbieter und der Client über die Bedeutung (Semantik) der Nachrichten einig sein, wenn sie erfolgreich miteinander kommunizieren möchten. Deswegen wird zum besseren Verständnis des Beispiels in der folgenden Beschreibung zwischen Client-Code und Service-Code, passend zum Szenario eines Druckaufrufs, hin und her gewechselt. Begonnen wird an dieser Stelle mit dem Code des Client und dem Aufbau der SOAP-Message, die der Client an den Service sendet, um einen Druckauftrag auszulösen. Zunächst wird in der Main-Methode des Client ein SOAPConnection-Objekt erzeugt, mit dessen Hilfe die SOAP-Message an den Dienst gesendet werden kann. Anschließend wird ein SOAPFactory-Objekt erstellt, das dazu dient, Name-Objekte zu erstellen, die der SOAP-Spezifikation 1.1 entsprechen. Die letztgenannten Objekte werden benötigt, um den SOAP-Body der Nachricht mit Information zu füllen. Die Code-Zeilen sehen wie folgt aus: SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); SOAPConnection connection = 68 Beispielimplementierungen für Druckdienste soapConnectionFactory.createConnection(); SOAPFactory soapFactory = SOAPFactory.newInstance(); Als Nächstes erfolgt die Erstellung der SOAP-Message; dazu wird zunächst ein SOAPMessage-Objekt erzeugt, dessen Struktur der Spezifikation SOAP 1.1 entspricht. Danach werden die einzelnen Teile einer SOAP-Message (SOAPPart, SOAPEnvelope, SOAPHeader und SOAPBody) extrahiert, damit die SOAP-Message mit Information gefüllt werden kann. Der entsprechende Code sieht wie folgt aus: MessageFactory factory = MessageFactory.newInstance(); SOAPMessage message = factory.createMessage(); SOAPPart soapPart = message.getSOAPPart(); SOAPEnvelope envelope = soapPart.getEnvelope(); SOAPHeader header = envelope.getHeader(); SOAPBody body = envelope.getBody(); Nun kann der SOAP-Body mit Information gefüllt werden. Da jedes direkte Kindelement des SOAP-Bodys einen Namensraum besitzen muss, wird als erstes das Tag ¡p:Print¿ erstellt, das anschließend als Vaterelement für die XML-Tags dienen soll, die die Parameter für den Aufruf der Druckfunktion enthalten. Als Kindelemente von ¡p:Print¿ werden anschließend das Element ¡fileName¿ definiert, das den Namen der zu druckenden Datei speichert, ein Element ¡noc¿ für die Anzahl der Kopien und ein Element ¡printer¿, das den Namen des Druckers speichert. Für die letzten beiden Parameter der Druckfunktion wurden Vorgabewerte implementiert, sie können also, müssen aber nicht vom Nutzer des Druckdienstes spezifiziert werden. // add element <p:Print> to the SOAP body Name bodyName = soapFactory.createName("Print", "p", "http://www.icsy.de/xml/lawns/"); SOAPBodyElement bodyElement = body.addBodyElement(bodyName); // add child element <fileName> to the element <p:Print> Name name1 = soapFactory.createName("fileName"); SOAPElement fileName = bodyElement.addChildElement(name1); // <fileName>value of the variable file</fileName> fileName.addTextNode(file); // add child element <noc> to element <p:Print> Name name2 = soapFactory.createName("noc"); SOAPElement noc = bodyElement.addChildElement(name2); // <noc>value of the variable numberOfCopies</noc> noc.addTextNode(numberOfCopies); // add child element <printer> to element <p:Print> Name name3 = soapFactory.createName("printer"); SOAPElement String = bodyElement.addChildElement(name3); Beispielimplementierungen für Druckdienste 69 // <pinter>value of the variable printerName</printer> String.addTextNode(printerName); Nachdem der SOAP-Body gefüllt wurde, kann die zu druckende Datei als Attachment an die SOAP-Message angefügt werden. Hierzu wird ein DataHandler-Objekt verwendet, das selbstständig den MIME-Type einer Datei erkennt und in dem Attribut Content-Type speichert. Als Eingabe erhält das DataHandler-Objekt eine URI, die die Adresse der Datei angibt. Des Weiteren besitzt der AttachmentPart einer SOAP-Message das Attribut Content-Id, das alternativ benutzt werden könnte, um den Namen der Datei zu übertragen, anstatt, wie oben angegeben, ein Element im SOAP-Body dafür anzulegen. Die resultierende SOAP-Message, die der Client danach mit dem Aufruf connection.call(message, endpoint) an den Service sendet, sieht wie folgt aus: ------=_Part_1_7408068.1062688563166 Content-Type: text/xml <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <SOAP-ENV:Body> <p:Print xmlns:p="http://www.icsy.de/xml/lawns/"> <fileName>test.xml</fileName> <noc>1</noc> <printer>pseudo</printer> </p:Print> </SOAP-ENV:Body> </SOAP-ENV:Envelope> ------=_Part_1_7408068.1062688563166-Content-Type: text/plain Content-Id: file // here is the content of the attached file ------=_Part_1_7408068.1062688563166-- Im obigen Beispiel wurde eine Text-Datei als String an die SOAP-Message angehängt, deswegen wurde das Content-Type-Attribut des AttachmentParts auf den MIME-Type text/plain“ gesetzt, der Text selbst ist hier aus ” Platzgründen nicht dargestellt. Hat die Nachricht den Druckdienst erreicht, so wird die Methode onMessage (SOAPMessage message) der Klasse PrintService, die das JAXM-Servlet erweitert, aufgerufen. Zunächst werden wie beim Client die Elemente SOAPPart, SOAP-Envelope und SOAP-Body von der SOAP-Message extrahiert, dann können die Informationen im Body ausgelesen werden. An dieser Stelle ist es nun erforderlich, dass der Service die Bedeutung der an ihn gesendeten Daten kennt, und die Daten einsetzt, um die entsprechende Funktion (hier Druckfunktion) aufzurufen. Da der Client Defaultwerte für den Druckername und die Anzahl an Kopien setzt, wird der Body der Nachricht immer ein 70 Beispielimplementierungen für Druckdienste ¡p:Print¿-Element enthalten, das wiederum drei Kindelemente besitzt. Des Weiteren muss der Service wissen, in welcher Reihenfolge die Parameter für die Druckfunktion in den Tags enthalten sind. Mit folgendem Code werden die Informationen aus dem SOAP-Body ausgelesen und in den entsprechenden Variablen gespeichert: if (iterator.hasNext()) { SOAPBodyElement element = (SOAPBodyElement)iterator.next(); // create second iterator to get the children of the first // body element Iterator iterator2 = element.getChildElements(); // get first child and use its value to set the variable fileName if (iterator2.hasNext()) { SOAPElement child = (SOAPElement)iterator2.next(); fileName = child.getValue(); } // get second child and use its value to set the variable noc // then convert the String noc to int if (iterator2.hasNext()) { SOAPElement child2 = (SOAPElement)iterator2.next(); noc = child2.getValue(); numberOfCopies = Integer.parseInt(noc); } // get the third child and use its value to set the variable printerName if (iterator2.hasNext()) { SOAPElement child3 = (SOAPElement)iterator2.next(); printerName = child3.getValue(); } } Anschließend werden die Attachments der SOAP-Message ausgelesen. Zuvor muss allerdings mittels der Abfrage ap.getContentType().equals("text/plain\) getestet werden, welches Format die in der SOAP-Message enthaltene Datei besitzt, damit entschieden werden kann, ob der Service bzw. Drucker die Datei drucken kann. Besitzt die Datei das richtige Format, so kann sie unter Hinzunahme der Funktion ap.getContent() in einen String oder einen ByteArrayInputStream eingelesen werden. Nachdem die Datei eingelesen wurde, wird sie lokal zwischengespeichert und per UNIX-Befehl lp“ an den Drucker-Daemon geschickt. Die Ausgabe des Druckbefehls, wird ” dabei in einen String eingelesen. Zu guter Letzt wird eine Antwort-Nachricht erstellt, in deren Body der String als Information für den Client enthalten ist. Ein Beispiel für eine solche zum Kunden gesendete SOAP-Message ist nachfolgend dargestellt: <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header/> <SOAP-ENV:Body> Beispielimplementierungen für Druckdienste 71 <p:Print xmlns:p="http://www.icsy.de/xml/lawns/"> <PrintID>request id is pseudo-73 (1 file(s))</PrintID> </p:Print> </SOAP-ENV:Body> </SOAP-ENV:Envelope> Der von der Druckfunktion lp ausgegebene String enthält die ID des Druckjobs (im Beispiel entspricht die ID der Zahl 73) und den Namen des Druckers, auf dem die Datei gedruckt werden soll. Diese Angaben benötigt der Dienstnutzer, falls er den Status erfragen oder den Druckauftrag löschen möchte. Der Client, der bis zum Erhalt der Nachricht gestoppt wurde, entpackt die Nachricht und gibt den String für den Dienstnutzer auf der Konsole aus. Damit der Dienst per Tomcat 3 ins Internet gestellt werden kann, muss noch eine Datei namens web.xml“ erstellt werden. Sie sieht wie folgt aus: ” <web-app> <display-name>Web Service: printService.PrintService</display-name> <servlet> <servlet-name> PrintService </servlet-name> <servlet-class> printService.PrintService </servlet-class> <load-on-startup> 1 </load-on-startup> </servlet> <servlet-mapping> <servlet-name> PrintService </servlet-name> <url-pattern> /PrintService </url-pattern> </servlet-mapping> </web-app> Der erste Teil der Datei web.xml“, der von dem Tag <servlet> einge” rahmt wird, legt fest, dass die Klasse PrintService“ des Pakets printSer” ” vice“ der Code für das Servlet namens PrintService ist. Der zweite Teil, das <servlet-mapping>, legt fest, dass das Servlet mit dem Namen PrintSer” vice“ unter dem relativen Pfad /PrintService“ zu finden ist. Der absolute ” Pfad bzw. die URL unter der der Druckdienst zu finden ist, ergibt sich aus der Adresse, unter der die gepackte WAR-Datei zu finden ist, plus dem relativen Pfad. Nun kann die WAR-Datei des PrintServices erstellt werden, die 3 Eine Ablaufumgebung für serverseitiges Java (Servlet) und die Java Server Pages (JSP) von der Apache Software Foundation. 72 Beispielimplementierungen für Druckdienste mindestens die Datei web.xml“ und den Code der Klasse PrintService“ ” ” enthalten muss. Abschließend wird noch die Konfigurationsdatei PrintService.xml“ erstellt, ” die im Verzeichnis jwsdp-1.2/webapps“ des JWSDP Version 1.2 gespeichert ” wird und die die erforderlichen Daten enthält, damit beim Start des Tomcat (Laufzeitumgebung) die WAR-Datei automatisch ins Internet gestellt und das Servlet des Druckdienstes initialisiert wird. Unter anderem sind in dieser Datei angegeben, wo die WAR-Datei zu finden ist und über welchen Pfad sie im Internet erreichbar sein soll. Der Druckdienst dieses Beipiels ist nach dem Start des Tomcat im Internet unter folgender Adresse zu finden: http://localhost:8080/PrintService/PrintService. Der Client wurde nicht als Servlet implementiert, er besitzt eine MainMethode, innerhalb der er eine SOAP-Message erstellt, die zum Aufruf des Druckdienstes PrintService führt. Ein solcher Client, der keinen MessageProvider benutzt, wird auch als Standalone“-Client bezeichnet. Der kompi” lierte Code des Client wurde mittels der Datei build.xml“, die das ant-Tool ” als Eingabe benötigt, in eine WAR-Datei gepackt und kann mit dem Befehl ant run -DfileName=... -Dnumber=... -Dprinter=... aufgerufen werden. Das Attribut fileName ist Pflicht und muss angegeben werden, für die anderen beiden Attribute existieren Default-Werte – sie können optional angegeben werden. Die Reihenfolge der Attribute ist dabei beliebig, denn die Attribute werden in der Datei build.xml“ über ihren Namen angesprochen ” und immer in gleicher Reihenfolge an die Main-Methode des Client übergeben. Alternativ wurde im Rahmen dieser Arbeit die gleiche Funktionalität unter Nutzung der Klasse HTTP-Servlet implementiert. Das HTTP-Servlet wird hier wegen der großen Ähnlichkeit zum vorhergehenden Beispiel weder beschrieben noch dargestellt, sie kann im Anhang eingesehen werden. Abschließende Bemerkungen 6 73 Abschließende Bemerkungen Die vorliegende Arbeit kann grob in zwei Teile unterteilt werden. Der erste beschäftigt sich zunächst mit der Identifizierung von lokationsbasierten Diensten und der Kategorisierung gefundener Dienste in einer Taxonomie. Die erstellte Taxonomie besitzt fünf Hauptkategorien und fünf Hierarchiestufen. Da Verzeichnisse von Web Services zur Zeit vorwiegend von Menschen und nicht von Software-Agenten durchsucht werden (bisher existieren im besten Fall Ansätze für intelligente Suchagenten), ist es sinnvoll die Anzahl der Hierarchiestufen nicht zu groß zu wählen, damit der Nutzer nicht zu oft klicken muss, bis er zu seinem Ziel gelangt. Im Bereich der Erstellung intelligenter Suchagenten wird zur Zeit vor allen Dingen an Universitäten geforscht. Die zur Zeit in Entwicklung befindlichen Spezifikationen (beispielsweise SOAP, UDDI, WSDL, DAML-S) stellen Ansätze dafür dar, bestimmten XML-Tags, eine eindeutige Semantik zu verleihen, damit die erstellten Dokumente maschinell bearbeitet werden können. Nach der Kategorisierung der Dienste wurden ausgewählte Dienste der Taxonomie exemplarisch in WSDL-Fragmenten beschrieben. Bei der Erstellung der Fragemente wurde auch der Aspekt der Modularität und Wiederverwendung von Beschreibungen betrachtet. Zur Inkludierung bereits vorhandener Fragmente wurde das <import>-Element benutzt. Alternativ könnte an dieser Stelle bei gleichem Zielnamensraum auch das Element <include> benutzt oder die seit WSDL Version 1.2 hinzugekommene Möglichkeit der Vererbung von <interface>-Definitionen herangezogen werden. Durch diese drei Techniken zur Modularisierung von Beschreibungen, kann ein hoher Grad an Wiederverwendbarkeit von Dienstbeschreibungen erreicht werden. Im zweiten Teil der Arbeit wurden zwei Dienste exemplarisch mittels des JWSDP von Sun Microsystems in Java implementiert. Für einen der beiden Web Services wurde die API JAX-RPC verwendet und der Service mittels zweier verschiedener Ansätze generiert. Beim Top-Down-Ansatz konnten die in der Taxonomie definierten Fragmente zur Generierung von Code benutzt werden. Allerdings werden noch nicht alle Datentypen bzw. XMLSchema-Definitionen unterstützt, und die WSDL-Datei ist in ihren Möglichkeiten speziell bezüglich der Definition eigener Datentypen noch etwas eingeschränkt. Da die aktuelle Version des JWSDP (1.2) nur die Version 1.1 von WSDL unterstützt, nicht aber die aktuelle Version 1.2, konnte bei der Modularisierung von WSDL-Dateien von der Möglichkeit der Vererbung des <interface>-Elements noch kein Gebrauch gemacht werden. Der zweite Service, der die Druckfunktion anbietet, wurde mit Hilfe der API JAXM implementiert. Diese API war in der Version 1.1 des JWSDP noch enthalten, wurde aber in der Version 1.2 ausgelagert. Das JWSDP besteht aus einer Ansammlung von Technologien, die später in die Plattfor- 74 Abschließende Bemerkungen men J2EE und J2SE inkludiert werden sollen; das JAXM soll hingegen als eigenständige Veröffentlichung weiter existieren und wurde deshalb aus dem Pack ausgelagert. Eines der beiden Pakete des JAXM ist als SAAJ allerdings noch im JWSDP integriert. Beide Schnittstellen, die den Aufbau und die Handhabung von SOAP-Messages ermöglichen, setzen natürlich voraus, dass die Semantik ihrer gesendeten Nachrichten im Voraus bekannt ist. Zusammenfassend gesehen, sind das Thema Web Service sowie die Technologien, die die dahinter stehende Funktionalität realisieren, ein sehr dynamisches Forschungsgebiet, das sich in ständiger Entwicklung befindet. Bis zur Vision, dass Software-Agenten für Nutzer nach Diensten im Web suchen und dem Nutzer Möglichkeiten zur Auswahl anbieten, nach Auswahl eines Dientes die dafür benötigten Komponenten dynamisch koppeln und dafür sorgen, dass die Aktionen ausgeführt werden, wird noch einige Zeit vergehen. Das liegt vor allem in der Tatsache begründet, dass bisher nur wenige Dienste in Verzeichnissen eingetragen und allgemein beschrieben sind. Erst die zunehmende Verbreitung und Nutzung einer Technologie führt dazu, dass die Technologie sehr wertvoll wird (vergleiche Internet). Aber Web Services haben gute Aussichten, da sie eine relativ breite Unterstützung von der Industrie und Forschung besitzen, auch wenn sie bisher vor allem im B2B-Bereich benutzt werden. Darüber hinaus werden von den Web Services neben der Basisfunktionalität viele Zusatzfunktionalitäten gefordert, wie beispielsweise Authentisierung oder Workflow-Unterstützung, für die ebenso Lösungen bereitgestellt werden müssen. Des Weiteren wird die Vielzahl verschiedener Kriterien, die bei der Auswahl von Diensten in Verzeichnissen eine Rolle spielen, zu berücksichtigen sein. ABBILDUNGSVERZEICHNIS 75 Abbildungsverzeichnis 1 2 3 4 5 6 7 Basis Architektur. Quelle: [CHA02] . . . . . . . . . . . . . . . SOAP Message. Quelle:[ORMA02] und [NASKSR] . . . . . . Semantik und WSDL. Quelle: [BOO03] . . . . . . . . . . . . . Import-Hierarchie . . . . . . . . . . . . . . . . . . . . . . . . . Use stub“ to make remote call“. Quelle: The JavaTM Web ” ” Service Developer Pack, Part 2 [ORMA02]. . . . . . . . . . . Druckdienst Realisierung . . . . . . . . . . . . . . . . . . . . . Serializers and Deserializers. Quelle: [MAG03], S. 388. . . . . 6 11 15 34 57 60 64 76 LITERATUR Literatur [ARM03] Armstrong, E.; Ball, J.; Bodoff, S.; Carson, D. B.; Fisher, M.; Fordin, S.; Green, D.; Haase, K.; Jendrock, E.: The Java TM Web Services Tutorial, 25.07.2003, http://java.sun.com/webservices/docs/1.2/tutorial/doc/index.html. [BAR02] Bartel, M.; Boyer, J.; Fox, B.; LaMaccia, B.; Simon, E.: XMLSingnature Syntax and Processing - W3C Recommendation, 12.02.2002, http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/. [BEL02] Bellwood, T.; Clément, L.; Ehnebuske, D.; Hately, A.; Hondo, M.; Husband, Y. L.; Januszewski, K.; Lee, S.; McKee, B.; Munter, J.; von Riegen, C.: UDDI Version 3.0 – UDDI Spec Technical Committee Specification, 19.07.2002, http://uddi.org/pubs/uddi v3.htm. [BOO03] Booth, D.; Le Hégaret, P.; Liu, C. K.: Web Services Description Language (WSDL) Version 1.2 Part 0: Primer, Editors copy, 01.06.2003, http://www.w3.org/2002/ws/desc/wsdl12-primer. [BRA00] Bray, T.; Paoli, J; Sperberg-McQueen, C. M.; Maler, E.: Extensible Markup Language (XML) 1.0 (Second Edition) – W3C Recommendation 06.10.2000, http://www.w3.org/TR/2000/REC-xml-20001006. [CHA02] Champion, M.; Ferris, C.; Newcomer, E.; Orchard, D.: Web Service Architecture - W3C Working Draft, 14.11.02, http://www.w3.org/TR/2002/WD-ws-arch-20021114/. [CHJE03] Chappell, D.; Jewell, T.: Java Web Services, (Kapitel 7 verwendet) O’ Reilly & Associates, Inc., Sebastotpol (USA), März 2003. [CHI03] Chinnici, R.; Gudgin, M.; Moreau, J-J.; Weerawarana, S.: Web Services Description Language (WSDL) Version 1.2 - W3C Working Draft 11.06.03, LITERATUR 77 http://www.w3.org/TR/2003/WD-wsdl12-20030611. [CHR01] Christensen, E.; Curbera, F.; Meredith, G.; Weerawarana, S.: Web Services Description Language (WSDL) Version 1.1 W3C Working Draft 15.03.2001, http://www.w3.org/TR/2001/NOTE-wsdl-20010315. [COY02] Coyle, F. P.: XML, Web Services, and the Data Revolution. Addison-Wesley by Pearson Education , Inc. Boston 2002. [FAL01] Fallside, D. C.: XML Schema Part 0: Primer - W3C Recommendation, 02.05.2001, http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/. [FRA99] Franks, J.; Hallam-Baker, P.; Hostetler, J.; Lawrence, S.; Leach, P.; Luotonen, A.; Stuart, L.: HTTP Authentication: Basic and Digest Access Authentication, RFC 2617, Internet Engineering Task Force, June 1999, ftp://ftp.isi.edu/in-notes/rfc2617.txt. [GRA01] Granada Research: Using the UNSPSC – United Nations Standard Products and Services Code, White Paper, Why Coding and Classifying Products is Critical to Success in Electronic Commerce, October 2001, http://www.unspsc.org/AdminFolder/Documents/UNSPSC White Paper.doc. [IMA02] Imamura, T.; Dillaway, W.; Simon, E.: XML Encrytion Syntax and Processing, W3C Recommendation 10.12.2002, http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/. [Kre02] Kreidel, M.; Kemper, A.; Kossmann, D.; Kreutz, A.: Web Services, in: Erhard Rahm, Gottfried Vossen (Hrsg.), Web & Datenbanken. Konzepte, Architekturen, Anwendungen, Dpunkt-Verlag, Heidelberg, 2002, S. 293 - 331. [KUWÖ] Kuschke, M.; Wölfel, L.: Web Services - Kompakt. Spektrum Akad. Verlag, Heidelberg, Berlin 2002. 78 LITERATUR [MAG03] McGovern, J.; Stevens, E. M.; Stevens, M.; Tyagi, S.; Mathew, S.: Java Web Service Architecture, Elsevier Science, April 2003. [MOSC] Moreau, J-J.; Schlimmer, J.: Web Service Description Language (WSDL) Version 1.2 Part 3: Bindings - W3C Working Draft 11.06.03, http://www.w3.org/TR/2003/WD-wsdl12-20030611. [NASKSR] Nagappan, R.; Skoczylas, R.; Sriganesh, R. P.: Developing Java Web Services - Architecting and Developing Secure Web Services Using Java. Wiley Publishing Inc., Indianapolis, Indiana, 2003. [ORMA02] Orth, E.; Mandava, R.: The JavaTM Web Services Developer Pack, Part 2, Oktober 2002, http://developer.java.sun.com/developer/technicalArticles/WebServices/WSPack2/. 79 Taxonomie A Taxonomie Output Services: 1. Print Services 1.1 Black-White Print Services 1.1.1 Print Ascii Files 1.1.1.1 Print PS 1.1.1.2 Print HPGL 1.1.2 Print Binary Files 1.1.2.1 Print GIF 1.1.2.2 Print JPEG 1.1.2.3 Print PCL 1.1.2.4 Print PDF 1.1.2.5 ... 1.1.2.6 Print PNG 1.2 Color Print Services 1.2.1 Print Ascii Color 1.2.1.1 Print PS 1.2.1.2 Print HPGL 1.2.2 Print Binary Color 1.2.2.1 Print GIF 1.2.2.2 Print PCL 1.2.2.3 Print PDF 1.2.2.4 ... 1.2.2.5 Print PNG 2. Play 2.1 Play Audio 2.1.1 Play MP3 2.1.2 Play WAV 2.1.3 ... 2.2 Play Video 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 Play Play Play ... Play MPEG1 MPEG2 MPEG4 Quicktime 80 Taxonomie 3. Display 3.1 Display Document 3.1.1 Display ASCII Document 3.1.1.1 Display PS 3.1.1.2 Display HPGL 3.1.1.3 Display TXT 3.1.1.4 ... 3.1.2 Display Binary Document 3.1.2.1 Display DOC 3.1.2.2 Display PCL 3.1.2.3 Display PPT 3.1.2.4 ... 3.2 Display Image 3.2.1 3.2.2 3.2.3 3.2.4 Display GIF Display JPEG Display BMP ... Input Services: 1. Scan 2. Record 2.1 Audio Input 2.2 Video Input 3. Sensor Input 3.1 Measure Temperature 3.2 Measure Ozon 3.3 ... 3.4 DVD Input 3.5 Keyboard Input 3.6 Mouse Input Storage and Computational Services 1. Save on external data mediums 1.1 Burn CD 1.2 Burn DVD Taxonomie 2. Computational Services Device Control 1. Get-functions 2. Set-functions Communication Services 1. Chat 2. Message Services (Nachrichtendienste) 2.1 Fax 2.2 Mail 2.3 SMS 3. Conferences 3.1 Telephone Conference (over IP) 3.1.1 Dial In 3.1.2 Dial Out 3.2 Video Conference 3.2.1 Dial In 3.2.2 Dial Out 81 82 B selbstdefinierte WSDL für den Druckdienst selbstdefinierte WSDL für den Druckdienst <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://com.test/wsdl/Print" xmlns:ns2="http://com.test/types/Print" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="Print" targetNamespace="http://com.test/wsdl/Print"> <types> <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://com.test/types/Print" xmlns:soap11-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://com.test/types/Print"> <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/> <simpleType name="StatusType"> <restriction base="string"> <enumeration value="queued"/> <enumeration value="printing"/> <enumeration value="printed"/> </restriction> </simpleType> <complexType name="ArrayOfPrinterQueueEntry"> <complexContent> <restriction base="soap11-enc:Array"> <attribute ref="soap11-enc:arrayType" wsdl:arrayType="tns:PrinterQueueEntry[]"/> </restriction> </complexContent> </complexType> <complexType name="PrinterQueueEntry"> <sequence> <element name="fileName" type="string"/> <element name="percentagePrinted" type="int"/> <element name="positionInPrinterQueue" type="int"/> <element name="printID" type="int"/> <element name="status" type="string"/> </sequence> </complexType> </schema> </types> <message name="remove"> <part name="printID" type="xsd:int"/> <part name="printerName" type="xsd:string"/> </message> <message name="removeResponse"> <part name="printacknowledgement" type="xsd:string"/> </message> <message name="statusOfJob"> <part name="printID" type="xsd:int"/> <part name="printerName" type="xsd:string"/> selbstdefinierte WSDL für den Druckdienst 83 </message> <message name="statusOfJobResponse"> <part name="status" type="ns2:StatusType"/> </message> <message name="viewPrinterQueue"> <part name="printerName" type="xsd:string"/> </message> <message name="viewPrinterQueueResponse"> <part name="queue" type="ns2:ArrayOfPrinterQueueEntry"/> </message> <portType name="Print"> <operation name="remove" parameterOrder="printID printerName"> <input message="tns:remove"/> <output message="tns:removeResponse"/> </operation> <operation name="statusOfJob" parameterOrder="printID printerName"> <input message="tns:statusOfJob"/> <output message="tns:statusOfJobResponse"/> </operation> <operation name="viewPrinterQueue" > <input message="tns:viewPrinterQueue"/> <output message="tns:viewPrinterQueueResponse"/> </operation> </portType> <binding name="PrintIFBinding" type="tns:Print"> <operation name="remove"> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="encoded" namespace="http://com.test/wsdl/Print"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="encoded" namespace="http://com.test/wsdl/Print"/> </output> <soap:operation soapAction=""/> </operation> <operation name="statusOfJob"> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="encoded" namespace="http://com.test/wsdl/Print"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="encoded" namespace="http://com.test/wsdl/Print"/> </output> <soap:operation soapAction=""/> </operation> <operation name="viewPrinterQueue"> <input> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" use="encoded" namespace="http://com.test/wsdl/Print"/> </input> <output> <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" 84 selbstdefinierte WSDL für den Druckdienst use="encoded" namespace="http://com.test/wsdl/Print"/> </output> <soap:operation soapAction=""/> </operation> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/> </binding> <service name="Print"> <port name="PrintIFPort" binding="tns:PrintIFBinding"> <soap:address xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" location="http://localhost:8080/Print-jaxrpc/Print"/> </port> </service> </definitions> PrintService – HTTP-Servlet C 85 PrintService – HTTP-Servlet C.1 Client-Code package printOrder; import import import import import import import java.net.*; java.io.*; javax.xml.soap.*; java.util.*; javax.servlet.*; javax.servlet.http.*; javax.activation.*; import org.apache.commons.logging.*; public class PrintOrder extends HttpServlet { static Log logger = LogFactory.getFactory().getInstance("PrintServiceHttp"); String to = null; String data = null; ServletContext servletContext; // Connection to send message private SOAPConnection con; public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); servletContext = servletConfig.getServletContext(); try { // create a SOAP point-to-point connection SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance(); con = soapConnectionFactory.createConnection(); } catch (Exception e) { logger.error("Unable to open a SOAPConnection", e); } } public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException { // create, send and receive message (same as JAXM-Servlet) } } C.2 Service-Code package printService; import javax.xml.soap.*; import java.util.*; import java.io.*; 86 Service-Code import import import import javax.servlet.*; javax.xml.*; javax.servlet.http.*; javax.xml.transform.*; public class PrintService extends HttpServlet { static MessageFactory factory = null; /*static { try { factory = MessageFactory.newInstance(); System.out.println("Hier bin ich!"); } catch (Exception e) { e.printStackTrace(); } }*/ public void init(ServletConfig servletConfig) throws ServletException { super.init(servletConfig); try { factory = MessageFactory.newInstance(); System.out.println("Hier bin ich!"); } catch (Exception e) { throw new ServletException("Unable to create message factory" + e.getMessage()); } } public void doPost (HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { // get all the headers from the HTTP request MimeHeaders headers = getHeaders(req); // get the body of the HTTP request InputStream is = req.getInputStream(); //Now internalize the contents of a HTTP request and create a SOAPMessage SOAPMessage message = factory.createMessage(headers, is); SOAPMessage reply = null; reply = onMessage(message); if (reply != null) { if (reply.saveRequired()) { reply.saveChanges(); } resp.setStatus(HttpServletResponse.SC_OK); putHeaders(reply.getMimeHeaders(), resp); Service-Code 87 // write out the message on the response stream OutputStream os = resp.getOutputStream(); reply.writeTo(os); os.flush(); } else resp.setStatus(HttpServletResponse.SC_NO_CONTENT); } catch (Exception e) { throw new ServletException("POST failed " + e.getMessage()); } } static MimeHeaders getHeaders(HttpServletRequest req) { Enumeration enum = req.getHeaderNames(); MimeHeaders headers = new MimeHeaders(); while (enum.hasMoreElements()) { String headerName = (String)enum.nextElement(); String headerValue = req.getHeader(headerName); StringTokenizer values = new StringTokenizer(headerValue, ","); while (values.hasMoreTokens()) headers.addHeader(headerName, values.nextToken().trim()); } return headers; } static void putHeaders(MimeHeaders headers, HttpServletResponse res) { Iterator it = headers.getAllHeaders(); while (it.hasNext()) { MimeHeader header = (MimeHeader)it.next(); String[] values = headers.getHeader(header.getName()); if (values.length == 1) res.setHeader(header.getName(), header.getValue()); else { StringBuffer concat = new StringBuffer(); int i = 0; while (i < values.length) { if (i != 0) concat.append(’,’); concat.append(values[i++]); } res.setHeader(header.getName(), concat.toString()); } } } 88 Service-Code public SOAPMessage onMessage (SOAPMessage message) { // handling of the received message (same as JAXM-Servlet) } }