Der folgende Text gibt einen groben technischen Überblick über SOAP Web Services.
Programmierbeispiele finden Sie unter SOAP Web Services mit JAX-WS.
Alternativ zu SOAP Web Services gibt es zum Beispiel die RESTful Web Services (einen Vergleich finden Sie hier).
Web Services im allgemeineren Sinne ermöglichen Abwicklungen von Dienstleistungen und Geschäften über das Internet.
Web Services im engeren technischen Sinn (siehe auch http://www.w3.org/2002/ws) meint automatisierte Kommunikation zwischen Applikationen über Netzwerke, also möglicherweise auch übers Internet. Es werden also nicht HTML-Seiten zu einem Webbrowser geschickt, die von einem Menschen betrachtet werden, sondern Programme tauschen Daten und starten auf entfernten Rechnern Funktionen.
Während früher bei verteilten Systemen die elektronische Kommunikation über Rechnergrenzen hinweg oft per CORBA, RMI oder DCOM erfolgte, nutzen SOAP Web Services als Nachrichtenformat XML und als Transportprotokoll meistens HTTP (es sind auch andere Protokolle möglich, z.B. JMS und SMTP).
Die in diesem Dokument gemeinten SOAP Web Services basieren auf den Standards SOAP und WSDL. Eventuell wird auch UDDI hinzugezogen.
Alternativ gibt es zum Beispiel die RESTful Web Services.
SOAP (ursprünglich "Simple Object Access Protocol") ist ein vom W3C standardisiertes Nachrichtenprotokoll (http://www.w3.org/TR/soap). Darüber wird Kommunikation zwischen verteilten Anwendungen ermöglicht und standardisiert und Applikationen werden webfähig.
SOAP ist ein Remote-Prozeduraufruf-Mechanismus mit XML als Nachrichtenformat für die Anfrage und das Ergebnis. Informationen, die nicht als XML-Text übertragen werden sollen, wie zum Beispiel Bild- und andere Binärdateien, werden per MIME angehängt.
SOAP kann mit verschiedenen Transportprotokollen verwendet werden. Meistens wird HTTP gewählt, aber zum Beispiel können SOAP-Anfragen auch über JMS oder über die SMTP/POP3-E-Mail-Protokolle versandt werden. Die Standard-Internetprotokolle erleichtern den Betrieb auch über Firewalls hinweg, was mit CORBA, RMI und DCOM schwieriger zu realisieren wäre.
SOAP ist unabhängig von Betriebssystemen, Programmiersprachen und Objektmodellen, kann verschiedene Plattformen verbinden (z.B. .NET und Java) und ist leichter zu implementieren als CORBA und DCOM.
Der Bestandteil "Object" im "Simple Object Access Protocol" bedeuted nicht wirklich Objektorientiertheit. SOAP kann hervorragend in objektorientierten Programmiersprachen umgesetzt werden, könnte aber auch in nicht-objektorientierten Programmiersprachen realisiert werden. Eine Übermittlung von Objekt-Referenzen ist in SOAP nicht definiert. Die per SOAP aufrufbaren Funktionen sind eher mit statischen Methoden vergleichbar.
Eine Besonderheit von SOAP ist seine Zustandslosigkeit. Dies bietet Vorteile, zum Beispiel kann besser skaliert werden, aber auch Nachteile, wenn Session-Daten zugeordnet werden müssen (z.B. Warenkorb).
Die wichtigsten Vorteile von SOAP sind: allgemein akzeptierte Standardisierung, Plattformunabhängigkeit, Offenheit, Robustheit und Skalierbarkeit. Der gravierendste Nachteil ist: mehr Overhead und dadurch etwas geringere Performance wegen des verwendeten Nachrichtenformats XML.
Listen von im Internet verfügbaren SOAP Web Services finden Sie zum Beispiel unter:
Wie SOAP in Java implementiert werden kann, ist in SOAP Web Services mit JAX-WS erklärt.
Bevor erläutert wird, wie SOAP über HTTP übertragen wird, soll kurz auf die Übertragung normaler Webseiten im HTML-Format eingegangen werden.
Wenn ein Webbrowser eine Webseite anfordert, könnte der HTML-Request zum Beispiel folgendermaßen aussehen (bei "GET" würden eventuelle Parameter an die URL angehängt, bei "POST" würden sie im HTTP-Header übertragen):
GET /techdocs/index.htm HTTP/1.1 Host: www.torsten-horn.de Content-Type: text/html;charset =utf-8 Content-Length: 0
Der Webserver könnte als Antwort zum Beispiel Folgendes schicken (hier im Beispiel drei Zeilen HTTP-Header, eine Leerzeile (CRLF) und anschließend der HTML-Code):
HTTP/1.1 200 OK Content-Type: text/html;charset =utf-8 Content-Length: 25 <html>Hello World!</html>
Sie können dies übrigens leicht nachvollziehen, indem Sie im Kommandozeilenfenster das Kommando 'telnet www.torsten-horn.de 80' eingeben und anschließend die obigen vier 'GET ...'-Zeilen eingeben.
Ein per HTTP übertragenes SOAP-Paket hat folgende Struktur
(die grünen Rahmen sind nicht Bestandteil, sondern verdeutlichen lediglich die Struktur):
+--------------------------------------------------HTTP-Header--+ | POST /realtimequotes/ncrouter HTTP/1.1 | | Host: mysoapserver | | Content-Type: text/xml;charset =utf-8 | | ... | +---------------------------------------------------------------+ <?xml version="1.0" encoding="UTF-8"?> +------------------------------------------------SOAP-Envelope--+ | <SOAP-ENV:Envelope | | xmlns:SOAP-ENV="http://..." | | ... | | +-----------------------------------SOAP-Header (optional)--+ | | | <SOAP-ENV:Header> | | | | <t:transaction | | | | xmlns:t="..." ... | | | | </SOAP-ENV:Header> | | | +-----------------------------------------------------------+ | | +------------------------------------------------SOAP-Body--+ | | | <SOAP-ENV:Body> | | | | <m:getLastTradePrice xmlns:m="trading-uri"> | | | | <ticker>SUNW</ticker> | | | | </m:getLastTradePrice> | | | | </SOAP-ENV:Body> | | | +-----------------------------------------------------------+ | | </SOAP-ENV:Envelope> | +---------------------------------------------------------------+
Im beim HTTP-Protokoll üblichen HTTP-Header würde bei HTML-Dateien als Content-Type "text/html" definiert. Für SOAP muss "text/xml" definiert sein, da XML-Dateien übertragen werden. Der HTTP-Header endet mit einer leeren Zeile (CRLF).
Anschließend folgt der XML-Teil, beginnend mit "<?xml ...".
Der XML-Teil besteht hauptsächlich aus dem so genannten "Envelope"-XML-Element. Dieses wiederum enthält die beiden XML-Elemente "Header" und "Body", wobei das "Header"-Element auch entfallen kann.
Das "Body"-Element muss enthalten sein. Hierin wird der eigentliche Inhalt plaziert, also die Daten, eine Meldung, eventuell eine Fehlermeldung oder ein RPC-Funktionsaufruf.
Im Folgenden wird anhand eines reellen Beispiels demonstriert, welche Informationen bei einer SOAP-Anfrage und -Antwort per HTTP und TCP/IP übertragen werden.
Das Beispiel benutzt den AltaVista Babelfish Translation Service, der von XMethods als BabelFish-SOAP-Dienst zur Verfügung gestellt wurde. Leider steht der Service nicht mehr zur Verfügung.
Unter "java-soap-axis.htm" finden Sie ein Java-Programm, mit dem die Abfrage abgesetzt werden kann.
Unter "jsp-taglibs.htm#ErsteTestanwendungApacheJakartaTaglibs" finden Sie eine einfache JSP-Anwendung, die Babelfish per JSP Apache Jakarta Taglibs aufruft.
Unter "java-soap-axis.htm#TCPMonitor" wird erläutert, wie die übertragenen Daten life mit TCP Monitor "mitgelesen" werden können.
SOAP-Request
POST /perl/soaplite.cgi HTTP/1.0 Host: services.xmethods.net:80 Content-Type: text/xml;charset =utf-8 Content-Length: 546 SOAPAction: "" <?xml version='1.0' encoding='UTF-8'?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <ns1:BabelFish xmlns:ns1="urn:xmethodsBabelFish" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <translationmode xsi:type="xsd:string">de_en</translationmode> <sourcedata xsi:type="xsd:string">Hallo Welt, Guten Tag</sourcedata> </ns1:BabelFish> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Lassen Sie sich von den vielen Namespace-Deklarationen nicht verwirren. Deutlich erkennbar ist folgende Struktur: Einige Zeilen HTTP-Header, eine Leerzeile, im XML-Teil das alles umfassende "Envelope"-Element und darin enthalten das "Body"-Element.
Im "Body"-Element befinden sich die eigentlichen Nutzdaten, hier im Beispiel "de_en", da von Deutsch nach Englisch übersetzt werden soll, und der eigentliche zu übersetzende Text "Hallo Welt, Guten Tag".
Dazugehöriger SOAP-Response
HTTP/1.1 200 OK Date: Thu, 05 Sep 2002 08:01:13 GMT Server: Apache/1.3.22 (Unix) Enhydra-Director SOAPServer: SOAP::Lite/Perl/0.52 Content-Length: 546 Connection: close Content-Type: text/xml;charset =utf-8 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <SOAP-ENV:Body> <namesp1:BabelFishResponse xmlns:namesp1="urn:xmethodsBabelFish"> <return xsi:type="xsd:string">hello world, good day</return> </namesp1:BabelFishResponse> </SOAP-ENV:Body> </SOAP-ENV:Envelope>
Auch hier ist wieder deutlich die Struktur erkennbar: HTTP-Header, Leerzeile, XML-Teil mit dem "Envelope"-Element und darin das "Body"-Element.
Im "Body"-Element befindet sich das Ergebnis, hier im Beispiel die mehr oder weniger gut gelungene Übersetzung "hello world, good day".
Viele Web-Service-Frameworks (z.B. JAX-WS) vereinfachen den Umgang mit Web Services und SOAP, so dass ein tieferes Verständnis der XML-Interna meistens nicht notwendig ist. Trotzdem ist ein gewisses Grundverständnis vorteilhaft.
Die Spezifikation von XML finden Sie unter http://www.w3.org/XML.
Wie XML von Java aus gelesen und bearbeitet werden kann, ist erklärt in java-xml.htm.
Die Syntax von XML ähnelt etwas der von HTML. Auch XML verwendet in spitzen Klammern ("<...>") eingefasste Tags. Aber es gibt mehr Unterschiede als Gemeinsamkeiten: Bei XML müssen alle Tags wieder geschlossen werden, nach "<meintag>" muss "</meintag>" folgen (bzw. es wird "<meintag/>" verwendet). Das zuletzt geöffnete Tag muss als erstes geschlossen werden, bevor ein anderes geschlossen wird. Anders als HTML ist XML "case sensitive", Groß-/Kleinschreibung wird unterschieden.
HTML beschreibt mehr das Erscheinungsbild des übermittelten Inhalts. XML dagegen beschreibt die Art der Daten und strukturiert sie inhaltlich.
XML-Dokumente sind in Unicode kodiert und beginnen in der ersten Zeile mit einer "processing Instruction", die zum Beispiel lauten kann:
<?xml version="1.0" encoding="UTF-8"?>
Weiter besteht das XML-Dokument aus XML-Elementen. Diese können XML-Kindelemente beinhalten, die wiederum weitere enthalten. Außerdem können den Elementen Attribute hinzugefügt werden. Eine einfache XML-Datei könnte so aussehen:
<?xml version="1.0" encoding="UTF-8"?> <xmlelement1> <xmlelement2> <xmlelement20> Wert21 </xmlelement20> </xmlelement2> <xmlelement3 attrname3="AttributWert3"> <xmlelement30 attrname31="AttributWert31" attrname32="AttributWert32" /> </xmlelement3> </xmlelement1>
XML-Elemente repräsentieren eine Dateneinheit und beginnen mit dem Start-Tag (z.B. "<meintag>") und enden mit dem Ende-Tag (z.B. "</meintag>") beziehungsweise kombinieren beide Tags (z.B. "<meintag/>").
XML-Attribute sind beliebige Name/Werte-Paare (z.B. attrname="AttrWert"), die im Start-Tag eines XML-Elements eingefügt werden.
Damit bestimmte Bezeichner in verschiedenen Zusammenhängen mit unterschiedlicher Bedeutung benutzt werden können, macht XML sehr ausgiebig Gebrauch vom Konzept der Namespaces. Namespaces sind Namensräume, vergleichbar in etwa mit den Packages in Java.
Eine XML-Datei mit Namespaces könnte zum Beispiel so aussehen:
<?xml version="1.0" encoding="UTF-8"?> <subjects xmlns="http://www.meinedomain.de/xyz1" xmlns:myns="http://www.meinedomain.de/xyz2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.meinedomain.de/xyz1 MySchema1.xsd http://www.meinedomain.de/xyz2 MySchema2.xsd"> <subject name="Bücher"> <category name="Java"> <book title="Java in 3 Tagen" myns:size="dünn"> <myns:category>Paperback</myns:category> <myns:price currency="Euro" value="3.50"/> </book> <book title="Java in 333 Tagen" myns:size="dick"> <myns:category>Hardcover</myns:category> <myns:price currency="Euro" value="59.50"/> <myns:price currency="USD" value="49.99"/> </book> </category> <category name="SOAP"> <book title="SOAP mit Java"> </book> <book title="SOAP mit .NET"> </book> </category> </subject> </subjects>
"xmlns="http://www.meinedomain.de/xyz1"" definiert den zu benutzenden Namespace, wenn kein Namespace-Name angegeben wird, also den "default Namespace".
"xmlns:myns="http://www.meinedomain.de/xyz2"" definiert den Namespace für den Namespace-Bezeichner "myns".
Die in beiden Fällen verwendeten Zeichenketten in den doppelten Hochkommas ("...") in der Form von URLs sind keine URLs, sondern URIs.
Eine URL (Uniform Resource Locator) lokalisiert eine Ressource (gibt also die Adresse an).
Eine URN (Uniform Resource Name) gibt keinen Ort an, aber identifiziert eine Ressource über einen eindeutigen Namen, vergleichbar mit den UUIDs bei IDL oder den GUIDs bei COM.
Eine URI (Uniform Resource Identifier) kann eine URL oder URN sein.
"xsi:schemaLocation="http://www.meinedomain.de/xyz1 MySchema1.xsd http://www.meinedomain.de/xyz2 MySchema2.xsd"
ordnet den beiden URIs jeweils eine .xsd-Schema-Datei zu (im Beispiel die Dateien "MySchema1.xsd" und "MySchema2.xsd").
.xsd-Schema-Dateien ersetzen DTDs (Document Type Definitions).
Sie enthalten "<xs:schema/>" als Root-Element und definieren die Datenstruktur.
Sie definieren zum Beispiel, welche Datenelemente und Attribute zwingend notwendig oder optional sind, wie oft sie auftreten dürfen und welche Bedeutung sie haben.
"category" kommt im Beispiel mehrfach in zwei verschiedenen Zusammenhängen vor, die durch die unterschiedlichen Namespaces auseinandergehalten werden ("category" und "myns:category").
Namespaces können, wie hier im Beispiel, zu Beginn definiert werden. Die Definition kann aber auch mitten im Dokument erfolgen. Oft erfolgt sie in dem Tag, in dem sie das erste Mal benutzt wird, und zwar nach dieser ersten Benutzung. Also zum Beispiel so:
"<myns:category xmlns:myns="http://www.meinedomain.de/xyz2"/>"
Weiteres zu Namespaces finden Sie unter http://www.w3.org/TR/REC-xml-names.
WSDL (Web Services Description Language, http://www.w3.org/TR/wsdl) ist ein XML-Derivat zur Beschreibung der Schnittstellen von Web Services. Nachrichtenstrom-Formate und Funktionsaufrufe werden definiert.
Wie eine WSDL-Datei automatisch aus Java-Source-Dateien erzeugt werden kann und wie aus einer WSDL-Datei automatisch passender Java-Source-Code erzeugt werden kann, ist in "SOAP Web Services mit JAX-WS" erklärt.
UDDI
UDDI (Universal Description, Discovery, and Integration, http://uddi.xml.org) ist ein webbasiertes Informationssystem für Web Services. Es bietet ein Verzeichnis von Adress- und Produktdaten sowie von Anwendungsprogrammierschnittstellen. Bitte beachten Sie, dass UDDI immer weniger unterstützt wird.
Früher gab es UDDI-Server (UBR = UDDI Business Registry Nodes) und UDDI-Browser von IBM, Microsoft und SAP, die für Testzwecke zur Verfügung standen. Leider sind diese Server abgeschaltet.
Einen UDDI-Browser finden Sie unter:
Eintrag erzeugen
Einen Eintrag in einer UDDI-Registry können Sie auf zweierlei Arten erzeugen:
Bei den meisten UDDI-Registries müssen Sie registriert sein (z.B. bei den IBM-Servern über den "IBM UDDI account").
Die Prozedur für einen Eintrag in einer UDDI-Registry ist bei den meisten UDDIs recht ähnlich.
Interaktiv im Webbrowser könnte es zum Beispiel folgendermaßen verlaufen:
Code | Description | Category Type |
54151 | Computer Systems Design and Related Services | NAICS (North American Industrial Classification System) |
43.16.00.00.00 | Software | UNSPSC (Universal Standard Products and Services Classification) |
DE-NW | Germany Nordrhein-Westfalen | GCS (Geographic Classification System, ISO 3166-1999) |
Eintrag suchen
Einen Eintrag in einer UDDI-Registry können Sie auf zweierlei Arten suchen:
Die Suchprozedur ist bei den meisten UDDIs recht ähnlich, interaktiv im Webbrowser zum Beispiel folgendermaßen:
Für eine in einem Programm benötigte Währungsumrechnung soll ein Web Service gefunden werden, um die jederzeit aktuellen Umrechnungskurse (Exchange Currency Conversion Rate) programmgesteuert automatisch im Hintergrund zu ermitteln.
java org.apache.axis.wsdl.WSDL2Java -o src -p meinpackageWSDL2Java http://www.webservicex.net/CurrencyConvertor.asmx?wsdl
die Java-Klasse "class CurrencyConvertorSoapStub", welche die Java-Methode "double conversionRate( fromCurrency, toCurrency )" enthält, worüber die Währungsumrechnung leicht von Java aus durchgeführt werden kann.Hier im Beispiel wurden viele Schritte zur Demonstration per Webbrowser durchgeführt. Sie können aber alle auch rein elektronisch programmgesteuert automatisiert werden.
... siehe SOAP Web Services mit JAX-WS.
Das Tabellenkalkulationsprogramm Microsoft Excel 2002 kann als SOAP-Client verwendet werden.
Unter älteren Windows-Versionen muss das 'SOAP Toolkit 3.0' installiert werden:
Für die Benutzung von Web Services müssen in Excel 'VBAProject'-'Verweise' eingefügt werden:
Das folgende Beispiel benutzt den 'Currency Exchange Rate'-Service:
Sub CommandButton1_Click() On Error GoTo SOAPError URL = "http://www.xmethods.net/sd/CurrencyExchangeService.wsdl" For i = 2 To 100 country1 = Worksheets("Tabelle1").Range("A" & i).Value country2 = Worksheets("Tabelle1").Range("B" & i).Value If country1 = "" Then Exit For End If Set service = New SoapClient30 service.MSSoapInit (URL) ret = service.getRate(country1, country2) Worksheets("Tabelle1").Range("C" & i).Value = ret Next Exit Sub SOAPError: If service.FaultString <> "" Then MsgBox "Fehler: " & service.FaultString & " " & service.Detail Else MsgBox "Fehler: " & Err.Description End If Err.Clear End Sub
A | B | C | |
1 | |||
2 | Euro | USA | |
3 | Euro | Japan | |
4 | USA | Japan |
A | B | C | |
1 | |||
2 | Euro | USA | 1,2831 |
3 | Euro | Japan | 134,49 |
4 | USA | Japan | 104,82 |
Das folgende Beispiel benutzt den 'Babel Fish'-Service:
Sub CommandButton1_Click() On Error GoTo SOAPError URL = "http://www.xmethods.net/sd/2001/BabelFishService.wsdl" For i = 2 To 100 translationmode = Worksheets("Tabelle1").Range("A" & i).Value SourceData = Worksheets("Tabelle1").Range("B" & i).Value If SourceData = "" Then Exit For End If If translationmode = "" Then translationmode = translationmodeLast End If translationmodeLast = translationmode Set service = New SoapClient30 service.MSSoapInit (URL) ret = service.BabelFish(translationmode, SourceData) Worksheets("Tabelle1").Range("C" & i).Value = ret Next Exit Sub SOAPError: If service.FaultString <> "" Then MsgBox "Fehler: " & service.FaultString & " " & service.Detail Else MsgBox "Fehler: " & Err.Description End If Err.Clear End Sub
A | B | C | |
1 | |||
2 | de_en | Hallo | |
3 | Auto | ||
4 | Haus |
A | B | C | |
1 | |||
2 | de_en | Hallo | hello |
3 | Auto | car | |
4 | Haus | house |
OpenOffice bietet direkte Unterstützung für Java-Anwendungen. Einen in OpenOffice eingebundenen Web-Service-Client mit Axis stellt der Artikel "Wortschatz - Besserer OpenOffice-Thesaurus dank Web-Services" von Oliver Lau in der c't 2005.15 ab Seite 214 vor (Listings: 0515-214.zip).