WSDL Lesen für Einsteiger
Von: Thomas Bayer
Datum: 12.09.2009
Letztes Update: 10.01.2012
Ein WSDL Dokument beschreibt die Schnittstelle eines Web Service und dient zur Generierung von Client- oder Service-Code.
Werkzeuge, wie z.B. Code Generatoren sind dazu gebaut, WSDL zu verstehen. Für uns Menschen wirkt WSDL unübersichtlich und unverständlich.
Im Laufe des Artikels wird aus dem Inhalt eines WSDL Dokumentes ein Baumdiagramm erstellt, welches die Struktur von WSDL illustriert. Der Leser bekommt so ein Verständnis der WSDL Elemente und deren Beziehung zueinander.
Als Beispiel für diesen Artikel dient uns die WSDL eines öffentlichen Services für Bankleitzahlen. Am besten drucken sie sich die WSDL aus oder laden Sie sich diese in einen Text- oder WSDL Editor.
Wir beginnen mit dem Root-Elementdes WSDL Dokumentes, welches den Namen definitions trägt. Die Kindelemente von definitions analysieren wir nicht in der Reihenfolge des Dokumentes, sondern von unten nach oben. Dadurch können wir Verweise in WSDL Dokument besser verfolgen.
Abbildung 1:
<wsdl:service name="BLZService"> <wsdl:port name="BLZServiceSOAP11port_http" binding="tns:BLZServiceSOAP11Binding"> <soap:address location="http://www.thomas-bayer.com:80/axis2/services/BLZService"/> </wsdl:port> <wsdl:port name="BLZServiceSOAP12port_http" binding="tns:BLZServiceSOAP12Binding"> <soap12:address location="http://www.thomas-bayer.com:80/axis2/services/BLZService"/> </wsdl:port> <wsdl:port name="BLZServiceHttpport" binding="tns:BLZServiceHttpBinding"> <http:address location="http://www.thomas-bayer.com:80/axis2/services/BLZService"/> </wsdl:port> </wsdl:service>
Der Name des Services lautet BLZService. Ein Service kann mehrere Ports haben, wie in Abbildung 2 mit einem * dargestellt. Jeder Port beschreibt eine Möglichkeit den Service aufzurufen. In unserem Beispiel gibt es drei Ports. Einen für SOAP 1.1, einen für SOAP 1.2 und einen für das HTTP Binding.
Abbildung 2:
Sehen wir uns den ersten Port in Listing 2 genauer an.
<wsdl:port name="BLZServiceSOAP11port_http" binding="tns:BLZServiceSOAP11Binding"> <soap:address location="http://www.thomas-bayer.com:80/axis2/services/BLZService"/> </wsdl:port>
Sein Kindelement address hat einen anderen XML Prefix als die anderen Elemente. Der Prefix soap ist an das SOAP 1.1 Binding aus diesem Dokument gebunden. Anstatt des SOAP Bindings können auch andere Bindings für den JMS oder Dateizugriff verwendet werden. Das address Element besitzt ein Attribut namens location, welches auf eine Endpoint Adresse des Service zeigt.
Abbildung 3:
Als nächstes interessiert und das binding Attribut des Ports. Der Wert tns:BLZServiceSOAP11Binding zeigt auf ein Binding, das ein wenig höher im Dokument steht. In diesem Beispiel zeigt jeder Port auf ein anderes Binding. Deswegen hat die BLZService WSDL drei Bindings.
Abbildung 4:
Ein Binding liefert Details über den spezifischen Transportweg. Das Binding in Abbildung 5 besitzt zwei verschiedene Arten von Kindelementen.
Abbildung 5:
Als erstes werfen wir einen einen Blick auf das soap:binding Element in Listing 3. Der Wert des transport Attributes ist eine URI, die bestimmt, dass SOAP Nachrichten über HTTP übertragen werden sollen. Der Wert document des style Attributs gibt uns zusammen mit dem use Attribut aus den soap:body Elementen einen Hinweis über den Nachrichtenstil. In unserem Beispiel benutzen wir ein Document/Literal Nachrichtenstil.
Ein Binding kann verschiedene Transport Optionen für jede einzelne Methode des Services spezifizieren.
<wsdl:binding name="BLZServiceSOAP11Binding" type="tns:BLZServicePortType"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <wsdl:operation name="getBank"> <soap:operation soapAction="" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding>
Schauen Sie sich nun Listing 4 an. Sie finden dort die Transport Optionen der getBank Methode. In dem wsdl:operation Element befindet sich in Zeile 2 ein soap:operation Element, welches Einzelheiten zum SOAP Protokoll und dessen Transport festlegt. Die soapAction ist ein Überbleibsel von früher. Das Basic Profile der Web Services Interoperability Organization sieht vor, dass soapAction mit einem leeren String belegt werden sollte.
<wsdl:operation name="getBank"> <soap:operation soapAction="" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation>
Da bei Web Services der Focus auf Nachrichten und nicht auf Parametern liegt, können die Informationen über den Transport dieser Nachrichten in den wsdl:input und wsdl:output Elementen gefunden werden. Ein Service kann auch einen oder mehrere Faults als Output spezifizieren.
Abbildung 6:
Das soap:body und das soap:header Element können weitere Besonderheiten einer Nachricht beschreiben. Im Beispiel wird für den Nachrichtenstil immer literal verwendet.
Abbildung 7:
Lassen Sie uns im WSDL weiter nach oben gehen. Verfolgen wir nun den Wert des type Attributes des Bindings. Es zeigt auf einen portType gleichen Namens weiter oben im Dokument.
Abbildung 8:
Wir haben jetzt die Grenze zwischen den konkreten Details des Transportes sowie der Location eines Services und der abstrakten Beschreibung des Interfaces überschritten. PortType ist in WSDL 1.1 dasselbe wie das Interface eines Web Services. In WSDL 2.0 assoziiert der Ausdruck portType das Interface des Services. Ein Interface kann mehrere Operationen besitzen. Eine Operation entspricht einer Funktion in der prozeduralen Programmierung. Die WSDL des BLZService hat nur einen portType. Alle drei Bindings referenzieren den portType namens BLZServicePortType.
Abbildung 9:
In einem portType finden wir wie im Binding operation Elemente. Diesmal beschreiben input und output allerdings die Struktur der Nachricht und nicht transportspezifische Optionen.
Abbildung 10:
Das message Attribut des Inputs referenziert wieder einen Teil weiter oben im WSDL Dokumentes. Und zwar eine Nachricht namens tns:getBank. Weiter oberhalb finden wir die dazugehörige Nachricht mit diesem Namen.
<wsdl:portType name="BLZServicePortType"> <wsdl:operation name="getBank"> <wsdl:input message="tns:getBank"/> <wsdl:output message="tns:getBankResponse" wsaw:Action="http://thomas-bayer.com/blz/BLZService/getBankResponse"/> </wsdl:operation> </wsdl:portType>
Abbildung 11:
Die Nachricht getBank hat ein part Element als Kind. Ein WSDL Experte wird anhand des Attributes name und dessen Wert parameters erkennen, dass es sich um den Substyle Wrapped des Document/Literal Stils handelt.
<wsdl:message name="getBank"> <wsdl:part name="parameters" element="tns:getBank"/> </wsdl:message>
Das Attribut element in Zeile 2 zeigt wieder weiter nach oben. Es referenziert auf das tns:getBank Element, welches im XML Schema zu finden ist.
Abbildung 12:
Das nächste Kind von definitions lautet types.
Abbildung 13:
Das types Element kann mehrere XML Schemas als Kinder besitzen.
Abbildung 14:
Listing 7 zeigt das types Element und ein eingebettetes Schema.
<wsdl:types> <xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://thomas-bayer.com/blz/"> <xsd:element name="getBank" type="tns:getBankType"/> <xsd:element name="getBankResponse" type="tns:getBankResponseType"/> <xsd:complexType name="getBankType"> <xsd:sequence> <xsd:element name="blz" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="getBankResponseType"> <xsd:sequence> <xsd:element name="details" type="tns:detailsType"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="detailsType"> <xsd:sequence> <xsd:element minOccurs="0" name="bezeichnung" type="xsd:string"/> <xsd:element minOccurs="0" name="bic" type="xsd:string"/> <xsd:element minOccurs="0" name="ort" type="xsd:string"/> <xsd:element minOccurs="0" name="plz" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema> </wsdl:types>
In einem Schema findet man die Definition von:
- Komplexen Typen
- Simplen Typen
sowie die Deklaration von:
- Elementen
Abbildung 15:
Listing 8 stellt die Deklaration des getBank Elements dar.
<xsd:element name="getBank" type="tns:getBankType"/>
Dieses Element ist vom Typ complexType und heisst getBankType und wird woanders im Schema definiert.
Abbildung 16:
Der Typ dieses Elements hat eine sequence als Modelgroup, die ein Element namens blz des build-in Schema Types string besitzt.
Abbildung 17:
Listing 9 zeigt die Definition des getBankType.
<xsd:complexType name="getBankType"> <xsd:sequence> <xsd:element name="blz" type="xsd:string"/> </xsd:sequence> </xsd:complexType>
Eine sequence kann aus mehreren Elementen bestehen, die die Reihenfolge der Elemente in einer SOAP Nachricht beschreiben.
Abbildung 18:
Nun haben wir uns die gesamte WSDL Beschreibung des Beispielservices angeschaut.
Alle WSDL Dokumente haben dieselbe Struktur wie der BLZService. Um eine WSDL zu verstehen, beginnt man mit dem Lesen am Ende des Dokuments und arbeitet sich nach oben vor, indem man den Verweisen in den Attributen folgt.
Ich hoffe, dass der Artikel Ihnen den Einstieg in WSDL erleichtert hat.
Thomas Bayer
bayer@predic8.com