Web Services

Ein Vortrag von Martin Hedler

Hinweis:
Bei der Ausarbeitung dieses Vortrages hat mir das Buch "Web Services kompakt" von Michael Kuschke und Ludger Wölfel, sehr geholfen. Ich habe einige Ideen daraus aufgegriffen und in diesem Vortrag verwendet.

Inhalt

  1. Was ist ein Web Service und warum brauche ich ihn?
  2. Grundlagen: XML
  3. Die Web Service Protokolle: SOAP und WSDL
  4. Beispiel

1. Was ist ein Web Service und warum brauche ich ihn?

Szenario

Die Allgemeinen Informatiker entwickeln im Rahmen eines Projektseminars ein Projektverwaltungssystem mit folgendem Funktionsumfang:

Das Projektverwaltungssystem wird über eine Web-Schnittstelle (HTML) zur Verfügung gestellt. Als technische Basis dient LAMP

Das System wird rege genutzt. Die Mitglieder eines Projektteams können von jedem System, welches einen Internetanschluss und einen Web-Browser besitzt, auf das Projektverwaltungssystem zugreifen, die Protokolle herunter bzw. hoch laden, Termine für Meilensteine oder Aufgabenabschlüsse eintragen oder sich über die aktuell anstehenden Termine informieren.

Die ersten Anfragen

Schon bald melden sich einige Nutzer, die für ihre Terminplanung bereits ein Programm auf ihren Rechner benutzen und die das Abgleichen der beiden Datenquellen (Programm - Projektverwaltung) sehr mühselig finden. Es wird nach einer Möglichkeit gefragt, die beiden Systeme direkt miteinander zu verbinden.

Der federführende Professor hält dies für eine ausgezeichnete Weiterentwicklung und gibt diese bei der nächsten Projektgruppe in Auftrag.

Die Umsetzung

Analyse:

Die Entwickler haben es mit einer heterogenen Systemwelt zu tun:

Eine weitere Anforderung, die man sich stellt, ist, das eigene bestehendes System so wenig wie möglich zu ändern.

Lösungssuche:

Lösung 1: Entwicklung einer Programmbibliothek, die den Zugriff auf die Web-Sites übernimmt und die benötigten Information herausliest. Hierfür würde sich C empfehlen, da diese Sprache von den meisten Systemen unterstützt wird. Die Bibliothek würde eine Anfrage an den Webserver senden, das zurückgesendete HTML-Dokument parsen und die Informationen an den Nutzer weitergeben. Die Bibliothek würde nach außen hin für den Entwickler den Zugriff auf die Internetseiten in Funktionen kapseln, so dass der Anwender von dem Datentransfer über das Netz nichts mitbekommt.

Problem:

Lösung 2: Remote-Procedure-Calls.

Wenn man das Verfahren der RPC mit dem objektorientierten Programmierparadigma verbinden will, kommen unter anderem folgende Verfahren in Frage:

Problem:

Lösungsansätze

Lösung:

Nutzung von XML und HTTP zur Kommunikation der verschiedenen Systeme miteinander: Web Services

Zurück zum Anfang...

2. Grundlagen:

XML (eXtensible Markup Language)

Problem: Heterogene Welt

Lösung: XML

Aufbau eines XML-Dokuments

Wohlgeformt

Ein wohlgeformtes XML-Dokument muss zwei Regeln gehorchen:

  1. Elemente treten immer paarweise auf.
  2. Elementpaare dürfen sich nicht überlappen.

Beispiele:

<name>Martin</name>

XML-Tags können außerdem beliebig viele Attribute enthalten.

<Mitarbeiter geschlecht="w">Cindy</Mitarbeiter>

Es gibt eine Ausnahme für die ersten Regel, nämlich dann, wenn zwischen dem Start-Tag und dem End-Tag keine Daten mehr stehen. Zwei Schreibweisen sind dann möglich:

<mail></mail> oder <mail/>

Die letzte Schreibweise wird als leeres Element bezeichnet.

In XML-Dokumenten können auch Kommentare eingefügt werden, die beim Parsen übergangen werden.

<!-- Kommentar -->

Beispiele für XML-Dokument

<?xml version="1.0" encoding="utf-8"?>
<terminplaner>
   <termin>
      <absender>Martin Hedler</absender>
      <text>Vortrag über Web-Services</text>
      <datum tag="22" monat="10" jahr="2003" />
   </termin>
   <termin wichtig="true">
      <absender>Projektleiter</absender>
      <text>Abschluss: Pflichtenheft</text>
      <datum tag="2" monat="11" jahr="2003" />
   </termin>
</terminplaner>
<?xml version="1.0" encoding="utf-8"?>
<person>
   <name>Hedler</name>
   <vorname>Martin</vorname>
   <datum tag="32" monat="01" jahr="1872"/>
</person>

Gültigkeit

Jeder kann letztendlich ein wohlgeformtes XML-Dokument erstellen. Man muss sich dazu nur an die obigen Regeln halten und seiner Fantasie freien Lauf lassen. Möchte man jedoch, dass ein Parser auch überprüft ob ein Dokument richtig ist, also ob z.B. all die Elemente enthalten sind, die enthalten sein müssen, so muss für das XML-Dokument eine Definition, eine Document Type Defintion (DTD), existieren. Eine solche DTD für den obigen Terminplaner soll als Beispiel hier kurz angegeben werden. Ein XML-Dokument welches gegen eine DTD validiert werden kann, ist nicht nur wohlgeformt, sonder auch noch gültig.

<!ELEMENT terminplaner (termin*)>
<!ELEMENT termin       (absender, text, datum)>
<!ELEMENT absender     (#PCDATA)>
<!ELEMENT text         (#PCDATA)>
<!ELEMENT datum        EMPTY>

<ATTLIST datum
   tag   CDATA   #REQUIRED
   monat CDATA   #REQUIRED
   jahr  CDATA   #REQUIRED
>

Ein Verweis auf eine DTD in einem XML-Dokument sieht folgendermaßen aus:

<?xml version="1.0">
<!DOCTYPE termin SYSTEM "../srq/termin.dtd">

Nachteile:

Es gibt zwei entscheidenden Nachteile der DTDs:

Lösung: XML Schema-Spezifikation

<?xml version="1.0">
<xsd:schema xmlns="http://www.w3c.org/2001/XMLSchema">

   <xsd:complexType name="termin-info">
      <xsd:sequence>
         <xsd:element name="absender" type="xsd:string"/>
         <xsd:element name="text" type="xsd:string"/>
      </xsd:sequence>
   </xsd:complexType>

   <xsd:element name="terminplaner">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="termin" type="termin-info"
               minOccurs="0" maxOccurs="unbounded"/>
         </xsd:sequence>
      </xsd:complexType>
   </xsd:element>

</xsd:schema>

Das Prinzip der Namensräume (Namespaces)

Das Prinzip der Namensräume muss kurz erwähnt werden, weil diese bei den Web Service Protokollen rege Anwendung finden.

In einem XML-Dokument können andere XML-Dokumente verwendet/eingebettet werden. Damit der Parser jedoch weiß, welcher Block zu welchen XML-Daten gehört (Stichwort: DTD/Schema) muss ein Namensraum angegeben werden.

Beispiel ohne Namespace und dadurch falsch

<?xml version="1.0" encoding="utf-8"?>
<terminplaner>
   <termin>
      <absender>
         <person>
            <name>Hedler</name>
            <vorname>Martin</vorname>
            <datum tag="32" monat="01" jahr="1872" />
         </person>
      </absender>
      <text>Vortrag &uuml;ber Web-Services</text>
      <datum tag="22" monat="10" jahr="2003" />
   </termin>
</terminplaner>

Beispiel mit Namespace (richtig)

<?xml version="1.0" encoding="utf-8"?>
<terminplaner>
   <termin>
      <absender>
         <person xmlns="http://www.htw-dresden.de/s4137/person">
            <name>Hedler</name>
            <vorname>Martin</vorname>
            <datum tag="32" monat="01" jahr="1872" />
         </person>
      </absender>
      <text>Vortrag &uuml;ber Web-Services</text>
      <datum tag="22" monat="10" jahr="2003" />
   </termin>
</terminplaner>

Beispiel mit expliziter Namespace Angabe

<?xml version="1.0" encoding="utf-8"?>
<terminplaner xmlns:p="http://www.htw-dresden.de/s4137/person">
   <termin>
      <absender>
         <p:person>
            <p:name>Hedler</name>
            <p:vorname>Martin</vorname>
            <p:datum tag="32" monat="01" jahr="1872" />
         </p:person>
      </absender>
      <text>Vortrag &uuml;ber Web-Services</text>
      <datum tag="22" monat="10" jahr="2003" />
   </termin>
</terminplaner>
Zurück zum Anfang...

3. Web Service Protokolle

SOAP

Soap definiert ein XML-Dokument mit folgenden Elementen:

Beispiel

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope">
   <soap:Header>
   </soap:Header>
   <soap:Body>
   </soap:Body>
</soap:Envelope>

Innerhalb des Body Teils kommt "unser" Dokument rein - natürlich mir Namespace Angabe. Wir unterscheiden dabei zwischen:

Der Header wird für Daten genutzt, die nicht direkt mit den Daten im Body zusammenhängen, z.B. Authentisierung.

Beispiel für eine Anfrage, eine Antwort und eine Fehlermeldung.

Anfrage:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlSOAP.org/SOAP/envelope">
   <soap:Body>
      <req:sucheTermin xmlns:req="http://www.htw-dresden.de/~s4137/termin">
         <req:tag>22</req:tag>
         <req:monat>10</req:monat>
         <req:jahr>2003</req:jahr>
      </req:sucheTermin>
   </soap:Body>
<soap:Envelope>

Antwort:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlSOAP.org/SOAP/envelope">
   <soap:Body>
      <res:sucheTerminResponse xmlns:req="http://www.htw-dresden.de/~s4137/termin">
         <res:termin>
            <res:absender>Martin Hedler</res:absender>
            <res:text>Vortrag&uuml;ber Web-Services</res:text>
            <res:datum tag="22" monat="10" jahr="2003" />
         </res:termin>
      </res:sucheTerminResponse>
   </soap:Body>
<soap:Envelope>

Fehlermeldung:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlSOAP.org/SOAP/envelope">
   <soap:Body>
      <soap:Fault>
      <faultcode>VersionMismatch</faultcode>
      <faultstring>Ungueltige Version</faultstring>
   </soap:Fault>
   </soap:Body>
<soap:Envelope>

In einer Fehlernachricht können folgende Elemente enhalten sein:

Bei faultcode sind folgende Angaben möglich:

In faultfactor wird angegeben, bei welchem Rechner zwischen Client und Server der Fehler auftrat.

WSDL

In WSDL wird der Web Service beschrieben.

Grundsätzlicher Aufbau:

<?xml version="1.0" encoding="utf-8">
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/">
   <types></types>
   <message></message>
   <portType></portType>
   <binding></binding>
   <service></service>
</definitions>

Das WSDL-Element "types":

In types können Typspezifikationen mit hilfe von XML-Schema vorgenommen werden.

<?xml version="1.0" encoding="utf-8">
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/">
   <types>
      <xsd:schema xmlns="http://www.w3c.org/2001/XMLSchema">
         <xsd:complexType name="termin-info">
            <xsd:sequence>
               <xsd:element name="absender" type="xsd:string"/>
               <xsd:element name="text" type="xsd:string"/>
            </xsd:sequence>
         </xsd:complexType>
      </xsd:schema>
   </types>
   ...
</definitions>

Das WSDL-Element "message":

In message wird angegeben, welche Datenfelder eine Nachricht enthält und von welchem Typ sie sind.

<?xml version="1.0" encoding="utf-8">
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/">
   ...
   <message name="sucheTermin">
      <part name="tag" type="xds:integer"/>
      <part name="monat" type="xsd:integer"/>
      <part name="jahr" type="xsd:integer"/>
   </message>
   <message name="sucheTerminResponse">
      <part name="termin" type="termin-info"/>
   </message>
   ...
</definitions>

Das WSDL-Element "portType":

In portType werden Operationen definiert. Eine Operation kann aus einer input message, einer output message und einer fault message bestehen.

<?xml version="1.0" encoding="utf-8">
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/">
   ...
   <portType name="Terminsuche">
      <operation name="sucheTermin">
         <input message="sucheTermin"/>
         <output message="sucheTerminResponse"/>
         <fault message="sucheTerminFault"/>
      </operation>
   </portType>
   ...
</definitions>

Das WSDL-Element "binding":

In binding wird angegeben, mit Hilfe welcher Protokolle eine Operation genutzt werden kann. Z.B. ob http genutzt werden soll oder smtp.

<?xml version="1.0" encoding="utf-8">
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/">
   ...
   <binding name="sucheTerminBinding" type="Terminsuche">
      <SOAP:binding transport="http://schemas.xmlsoap.org/soap/http"
         style="rpc"/>
   </binding>
   ...
</definitions>

Innerhalb einer binding-Angabe können noch operations angegeben werden, die definieren, wie eine einzelne Operation jeweils aussieht.

Außerdem sind neben SOAP noch weitere Transportwege möglich.

Das WSDL-Element "service":

In service werden nun die Operationen mit einer Adresse in Verbindung gebracht, unter der sie dann zu erreichen sind.

<?xml version="1.0" encoding="utf-8">
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/">
   ...
   <service name="terminplaner">
      <port="terminplanerSoap" binding="sucheTerminBinding">
         <SOAP:address location="http://irgendwo.com" />
      </port>
   </service>
   ...
</definitions>
Zurück zum Anfang...

4. Beispiel

Ganz dem Motto folgend: "Versuch macht kluch" wollen wir uns nun ein kleines Programm schreiben, welches mit einem Web Service kommuniziert. Als erstes müssen wir eines solchen Web Service finden. Ich habe mich dafür auf der Homepage www.xmethods.com umgeschaut, wo eine unüberschaubare Anzahl von Web Services aufgelistet ist. Dort habe ich einen kleinen Web Servies gefunden, der mir zu einer Bankleitzahl das entsprechende Geldinstitut liefert und umgekehrt. Wir wollen die erste Möglichkeit nutzen. Als nächstes lade ich mir die zur Verfügung gestellte WSDL Datei herunter, die den Web Service beschreibt. Nun gilt es die benötigten Informationen aus dieser Datei herauszulesen. (Dies muss man nicht von Hand machen. Es gibt im Netz viele Programmpakete, die aus einer WSDL Datei automatisch eine Schnittstelle generieren. Zur Anschauung wollen wir uns jedoch dieses eine Mal selbst die Hände schmutzig machen.) Als erstes schaue ich mir das service Element der WSDL Datei an.

<service name="BankCode">
   <documentation>Translates german bank codes (Bankleitzahlen) to bank names and vice versa.</documentation> 
   <port name="BankCodePort" binding="tns:BankCodeBinding">
      <soap:address location="http://appserver.pepperzak.net:80/bankcode/bankcodeuri" /> 
   </port>
</service>

Er enthält zum einen ein documentation Element in dem eine Beschreibung des Dienstes zu finden ist. Für uns wichtiger ist das port Element. Hier nämlich ist beschrieben, wo der gewünschte Dienst zu finden ist:

<service name="BankCode">
   <documentation>Translates german bank codes (Bankleitzahlen) to bank names and vice versa.</documentation> 
   <port name="BankCodePort" binding="tns:BankCodeBinding">
      <soap:address location="http://appserver.pepperzak.net:80/bankcode/bankcodeuri" />
   </port>
</service>

Damit hätten wir also schon einmal eine Adresse, die wir uns notieren.

Notizen
Adresse: http://appserver.pepperzak.net:80/bankcode/bankcodeuri

Aus dem port Element entnehmen wir weiter, welches Binding für diese Adresse genutzt wird:

<service name="BankCode">
   <documentation>Translates german bank codes (Bankleitzahlen) to bank names and vice versa.</documentation> 
   <port name="BankCodePort" binding="tns:BankCodeBinding">
      <soap:address location="http://appserver.pepperzak.net:80/bankcode/bankcodeuri" /> 
   </port>
</service>

Das binding Element mit dem Namen "BankCodeBinding" wollen wir uns jetzt anschauen.

<binding name="BankCodeBinding" type="tns:BankCodePortType">
   <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /> 
   <operation name="getNameByCode">
      <soap:operation soapAction="urn:getNameByCode" /> 
      <input>
         <soap:body use="encoded" namespace="urn:BankCode" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> 
      </input>
      <output>
         <soap:body use="encoded" namespace="urn:BankCode" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> 
      </output>
   </operation>
   <operation name="getCodeByName">
      <soap:operation soapAction="urn:getCodeByName" /> 
      <input>
         <soap:body use="encoded" namespace="urn:BankCode" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> 
      </input>
      <output>
         <soap:body use="encoded" namespace="urn:BankCode" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /> 
      </output>
   </operation>
</binding>

Was sagt uns dieser Ausschnitt? Als erstes sagt er uns, dass der portType mit dem Namen "BankCodePortType" genutz wird:

<binding name="BankCodeBinding" type="tns:BankCodePortType">
   <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
   <operation name="getNameByCode">
   ...
   </operation>
   <operation name="getCodeByName">
   ...
   </operation>
</binding>

Als nächstes erfahren wir, dass die Übertragung mittels http stattfindet und das der Ablauf dem eines Remote Procedure Calls (rpc) entspricht, also Anfrage gefolgt von einer Antwort.

<binding name="BankCodeBinding" type="tns:BankCodePortType">
   <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
   <operation name="getNameByCode">
   ...
   </operation>
   <operation name="getCodeByName">
   ...
   </operation>
</binding>
Notizen
Adresse: http://appserver.pepperzak.net:80/bankcode/bankcodeuri
Protokoll: http

Die Angaben in den operation Elementen unter binding enthalten noch Informationen zur Kodierung der Nachrichten. In unserem Falle schenken wir ihnen jedoch keine weitere Beachtung.

Nun sollten wir uns den im binding Element angegebenen PortType anschauen:

<portType name="BankCodePortType">
   <operation name="getNameByCode">
      <input message="tns:getNameByCodeRequest" /> 
      <output message="tns:getNameByCodeResponse" /> 
   </operation>
   <operation name="getCodeByName">
      <input message="tns:getCodeByNameRequest" /> 
      <output message="tns:getCodeByNameResponse" /> 
   </operation>
</portType>

Im portType Element erfahren wir, dass es zwei Operationen gibt:

<portType name="BankCodePortType">
   <operation name="getNameByCode">
      <input message="tns:getNameByCodeRequest" /> 
      <output message="tns:getNameByCodeResponse" /> 
   </operation>
   <operation name="getCodeByName">
      <input message="tns:getCodeByNameRequest" /> 
      <output message="tns:getCodeByNameResponse" /> 
   </operation>
</portType>

Da wir den Namen zu einer Bankleitzahl ermitteln wollen ist die Operation "getNameByCode" für uns interessant.

Notizen
Adresse: http://appserver.pepperzak.net:80/bankcode/bankcodeuri
Protokoll: http
Operation: getNameByCode

Im operation Element werden jetzt die Nachrichten angegeben, die für die Operation genutzt werden.

<portType name="BankCodePortType">
   <operation name="getNameByCode">
      <input message="tns:getNameByCodeRequest" /> 
      <output message="tns:getNameByCodeResponse" />
   </operation>
   ...
</portType>

Wir erfahren also, dass der Service eine Input Message benötigt, welche wir an das System senden und daraufhin eine Output Message generiert, die es an uns zurücksendet. Schauen wir uns als erstes an, wie die Nachricht "getNameByCodeRequest" aufgebaut ist. Dazu gehen wir in das message Element mit dem Namen "getNameByCodeRequest".

<message name="getNameByCodeRequest">
   <part name="arg0" type="xsd:string" /> 
</message>

Diese Nachricht enthält also nur eine Variable mit dem Namen "arg0" und ist vom Typ "xsd:string"

Notizen
Adresse: http://appserver.pepperzak.net:80/bankcode/bankcodeuri
Protokoll: http
Operation: getNameByCode
Input: arg0 (String)

Schauen wir uns nun die Nachricht an, die an uns zurückgeschickt wird: "getNameByCodeResponse"

<message name="getNameByCodeResponse">
   <part name="return" type="xsd:string" /> 
</message>

Auch diese Nachricht enthält nur eine Variable. Diese trägt den Namen "return" und ist ebenfalls vom Typ "xsd:string".

Notizen
Adresse: http://appserver.pepperzak.net:80/bankcode/bankcodeuri
Protokoll: http
Operation: getNameByCode
Input: arg0 (String)
Output: return (String)

Ganz zum Schluss schauen wir uns noch an, welchen Namespace wir benötigen, um die angegebenen Elemente gültig zu nutzen. Den Namespace finden wir im definitions Elementkopf:

<definitions name="BankCode" targetNamespace="java:com.pepperzak.webservices.ecommerce"
   xmlns="http://schemas.xmlsoap.org/wsdl/"
   xmlns:tns="java:com.pepperzak.webservices.ecommerce"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

Der Namspace lautet "java:com.pepperzak.webservices.ecommerce"

Notizen
Adresse: http://appserver.pepperzak.net:80/bankcode/bankcodeuri
Protokoll: http
Operation: getNameByCode
Input: arg0 (String)
Output: return (String)
Namespace: java:com.pepperzak.webservices.ecommerce

Nun können wir uns an die Erstellung unseres Programms machen. Wir wissen, dass wir unsere Anfrage mit Hilfe von SOAP an den Service senden müssen. Wir basteln uns jetzt also einfach eine solche SOAP Nachricht:

Als erstes der XML Kopf:

<?xml version="1.0" encoding="utf-8"?>

Nun die SOAP Bestandteile. Als erstes der Umschlag:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
</soap:Envelope>

Den Header lassen wir weg, da wir ihn nicht benötigen. Somit folgt als nächstes das Body Element:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
   </soap:Body>
</soap:Envelope>

Und in das Body Element fügen wir nun die gewünschte Nachricht ein. Nach unseren Notizen wollen wir die Operation "getNameByCode" aufrufen. Und da dies ein Element aus einer anderen DTD ist, müssen wir auch den entsprechenden Namespace mit angeben.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <getNameByCode xmlns="java:com.pepperzak.webservices.ecommerce">
      </getNameByCode>
   </soap:Body>
</soap:Envelope>

Welche Parameter müssen wir der Operation mitgeben? Die Antwort steht in unseren Notizen bei Input. Wir fügen also eine Variable mit dem Namen "arg0" ein.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <getNameByCode xmlns="java:com.pepperzak.webservices.ecommerce">
         <arg0></arg0>
      </getNameByCode>
   </soap:Body>
</soap:Envelope>

Und innerhalb des "arg0" Elements können wir nun unsere gewünschte Bankleitzahl eintragen, zu welcher wir den Namen des Geldinstituts wissen wollen.

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <getNameByCode xmlns="java:com.pepperzak.webservices.ecommerce">
         <arg0>10070000</arg0>
      </getNameByCode>
   </soap:Body>
</soap:Envelope>

Zur Kommunikation mit dem Server benutze ich ein kleines Java Programm. Das Programm hat folgenden Ablauf:

  1. Öffnen einer Socketverbindung
  2. Übertragung der HTTP Header Daten
  3. Übertragung der SOAP Nachricht.
  4. Empfangen der Antwort.

Hier der vollständige Quelltext:

import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;

public class Client
{
   public static void main(String[] args) throws IOException
   {
      Socket sock = new Socket("appserver.pepperzak.net", 80); // Socket zum Web Service

      /* String mit SOAP Nachricht zusammenfuegen */
      String s =
      "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
      "<soap:Envelope\n" +
         "xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
         "<soap:Body>\n" +
            "<getNameByCode xmlns=\"java:com.pepperzak.webservices.ecommerce\">\n" +
               "<arg0>10070000</arg0>\n" +
            "</getNameByCode>\n" +
         "</soap:Body>\n" +
      "</soap:Envelope>\n";

      /* String fuer HTTP Header zusammenfuegen */
      String ht =
      "POST /bankcode/bankcodeuri HTTP/1.1\r\n" +
      "Host: appserver.pepperzak.net\r\n" +
      "Content-Type: text/xml; charset=utf-8\r\n" +
      "Content-Length: " + Integer.toString(s.length()) + "\r\n\r\n";

       PrintStream o = new PrintStream(sock.getOutputStream());
       o.print(ht); // HTTP Header senden
       o.print(s); // SOAP Nachricht senden

      /* So lange etwas am Socket anliegt, vom Socket lesen */
      for (int c = sock.getInputStream().read(); c != -1; c = sock.getInputStream().read())
      {
         System.out.print((char) c); // Empfangene Zeichen ausgeben
      }
   }
}

Die Antwort des Web Service wird vollständig auf der Standartausgabe ausgegeben. Wenn man das Programm noch weiter treiben möchte, so könnte man die Antwort noch parsen. Wie ich aber schon bemerkte, gibt es genug Werkzeuge, die einem die aufwendige Arbeit eine WSDL Datei auszuwerten abnehmen. Die Nutzung eines Web Services sieht für den Entwickler dann nur noch wie ein ganz normaler Methodenaufruf aus.

von Martin Hedler

Zurück zum Anfang...

Quellen:


Buchcover

Web Services kompakt

von Michael Kuschke und Ludger Wölfel

Preis: 9,95 Euro
ISBN: 3827413753
Verlag: Spektrum Akademischer Verlag
Seiten: 100
  Bestellung bei amazon.de
Zurück zur Startseite...

Kontakt: webmaster@hpfsc.de
letzte Änderung: 20.02.2006
Falls nicht vorhanden, dann hiermit Navigationsleiste laden